结构体

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/jsonorm 这些包看,程序自己一般不读。

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 也不会出现。


参考文档