结构体
2026年9月6日
结构体把一组字段收成一种类型。没有 class,方法和数据靠「接收者」绑在一起。
结构体定义
type User struct {
Name string
Age int
}
u := User{Name: "槿", Age: 18}
fmt.Println(u.Name)
go
字段零值规则和基本类型一样。字面量可以按字段名写,也可以按顺序写(不推荐,换字段顺序会 silently 写错)。
给类型加方法:
func (u User) Hello() string {
return "hi, " + u.Name
}
go
值接收者拿到的是拷贝,改字段不影响外面。
继承
Go 没有继承关键字,用嵌套(匿名嵌入)把内层字段和方法提升出来:
type Person struct {
Name string
}
func (p Person) Hello() string {
return p.Name
}
type Student struct {
Person
Grade int
}
s := Student{Person: Person{Name: "槿"}, Grade: 3}
fmt.Println(s.Name, s.Hello())
go
外层有同名字段或方法时,外层优先。这是组合,不是子类关系。
结构体指针
要在函数或方法里改结构体字段,传指针(或用指针接收者):
func (u *User) Grow() {
u.Age++
}
p := &User{Name: "槿", Age: 18}
p.Grow()
fmt.Println(p.Age) // 19
go
Go 会自动在 u 和 &u 之间补一层,调用时两种写法都能编过。结构体比较大,或方法需要改接收者,用指针接收者。
new(User) 得到 *User,字段是零值。
结构体 tag
字段后面的反引号字符串是 tag,给 encoding/json、orm 这些包看,程序自己一般不读。
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
go
用 reflect 可以取出 tag,反射那一课再写。
json tag
encoding/json 只导出首字母大写的字段。不写 tag 时,JSON 里的 key 就是字段名。
| tag | 作用 |
|---|---|
json:"name" | key 改成 name |
json:"-" | 这个字段不进 JSON |
json:"age,omitempty" | 零值时省略 |
type User struct {
Name string `json:"name"`
Age int `json:"age,omitempty"`
Token string `json:"-"`
hidden string
}
b, _ := json.Marshal(User{Name: "槿", Token: "secret"})
fmt.Println(string(b)) // {"name":"槿"}
go
hidden 是小写,序列化时直接丢掉。Age 是 0,加上 omitempty 也不会出现。