8.1 Go Struct 结构体基础

8.1 Go Struct 结构体基础知识学习笔记

1. 定义结构体

结构体是自定义类型,用于将相关数据组合在一起。

go 复制代码
type Person struct {
    Name string
    Age  int
}

type Book struct {
    Title  string
    Author string
    Pages  int
}

type Address struct {
    Street string
    City   string
    State  string
    Zip    string
}

要点

  • 字段名大写开头 → 其他包可访问(public)
  • 字段名小写开头 → 仅当前包可访问(private)
  • 每个字段占一行,类型跟在字段名后面

2. 创建结构体实例的三种方式

方式一:指定字段名(推荐)

go 复制代码
person1 := Person{Name: "Alice", Age: 30}

优点:字段顺序无关,可读性好,不容易出错。

方式二:不指定字段名(位置参数)

go 复制代码
person2 := Person{"Bob", 25}

必须按定义时的字段顺序填写所有字段,少写或顺序错都会编译报错。实际开发中不推荐使用。

方式三:零值 + 逐个赋值

go 复制代码
var person3 Person        // 所有字段为零值:Name="", Age=0
person3.Name = "Charlie"  // 逐个赋值
person3.Age = 35

var 声明的结构体,所有字段自动初始化为类型的零值(string 为 "",int 为 0,bool 为 false)。


3. 访问和修改字段

使用 . 操作符:

go 复制代码
fmt.Printf("Person1: Name=%s, Age=%d\n", person1.Name, person1.Age)

book.Pages += 20  // 修改字段值

4. 结构体嵌入(嵌套)

结构体可以嵌入另一个结构体作为字段,有两种写法:

写法一:具名嵌入

go 复制代码
type Student struct {
    Name    string
    ID      int
    Address Address  // 具名字段,必须通过 student.Address.City 访问
}

访问时需要写完整路径:

go 复制代码
fmt.Printf("City: %s\n", student.Address.City)

写法二:匿名嵌入(嵌入式)

go 复制代码
type Student struct {
    Name string
    ID   int
    Address  // 匿名嵌入,字段提升,可直接访问 student.City
}

访问时可以直接用字段名(字段提升):

go 复制代码
fmt.Printf("City: %s\n", student.City)        // 直接访问
fmt.Printf("Address: %+v\n", student.Address)  // 也可以整体访问

初始化方式相同:

go 复制代码
student := Student{
    Name: "Diana",
    ID:   12345,
    Address: Address{
        Street: "123 Main St",
        City:   "Boston",
        State:  "MA",
        Zip:    "02101",
    },
}

5. 结构体比较

如果所有字段类型都可比较(string、int、bool 等),结构体可以直接用 == 比较:

go 复制代码
person1 := Person{Name: "Alice", Age: 30}
person4 := Person{Name: "Alice", Age: 30}

if person1 == person4 {
    fmt.Println("person1 and person4 are equal")  // 输出: equal
}

注意 :如果结构体包含不可比较的字段(如 slice、map),则不能用 == 比较,编译会报错。


6. 结构体是值类型(拷贝而非引用)

赋值结构体会创建一个独立的副本,修改副本不影响原值:

go 复制代码
personCopy := person1       // 创建副本
personCopy.Age = 31         // 修改副本

fmt.Printf("Original: %+v\n", person1)   // {Name:Alice Age:30}
fmt.Printf("Copy: %+v\n", personCopy)     // {Name:Alice Age:31}

person1 的 Age 仍然是 30,personCopy 的 Age 是 31,两者互不影响。

如果想要引用(修改副本也修改原值),需要使用指针

go 复制代码
personPtr := &person1       // 指针,指向同一个实例
personPtr.Age = 31          // 修改指针指向的值

fmt.Printf("Original: %+v\n", person1)   // {Name:Alice Age:31} --- 原值也被修改了

7. 格式化输出

格式化动词 输出 示例
%v 默认格式 {Alice 30}
%+v 带字段名 {Name:Alice Age:30}
%#v Go 语法表示 main.Person{Name:"Alice", Age:30}

知识点总结

知识点 关键概念
定义结构体 type Name struct { ... },字段大写=公开,小写=私有
创建实例 三种方式:指定字段名、位置参数、零值逐个赋值
访问/修改字段 . 操作符,如 person.Name
嵌入结构体 具名嵌入 vs 匿名嵌入(匿名嵌入有字段提升)
比较 字段类型都可比较时,可用 ==
值类型 赋值产生独立副本,想共享需用指针
格式化输出 %+v 带字段名,最常用
相关推荐
ttwuai32 分钟前
Go 后台接入 CAS 单点登录后,原来的权限怎么继续生效?
开发语言·后端·golang
蓝宝石的傻话17 小时前
因为MiBeeNVR,决定接 onvif-go 自己管理并重构
数码相机·重构·golang
ttwuai1 天前
Go 后台管理系统组件库文档怎么写,才不会坑后续维护?
开发语言·javascript·golang
2601_962066231 天前
golang超详细基础入门教程_golang教程
前端·python·golang
互联网中的一颗神经元2 天前
10. Large 对象分配:直接路径
开发语言·golang
microrain2 天前
从关系库硬扛到专业时序引擎:SagooIoT时序数据存储的架构取舍
物联网·golang·开源·sagooiot
Vect__2 天前
channel 底层剖析
golang
李燚2 天前
数据库迁移不翻车:golang-migrate 实战,143 个 DDL 有序执行(第97篇-E83)
golang·agent·multiagent·migrate·eino·subagent·deepflux