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 带字段名,最常用 |