Go结构体非类,无继承重载,靠首字母大小写控制字段导出性;嵌入实现组合提升,值/指针接收影响方法修改;零值确定,初始化须按序或用字段名。
Go 语言中结构体(struct)不是类,不支持继承、方法重载或隐藏字段,但它是组合与封装的核心载体。定义和访问字段看似简单,实际容易在导出控制、嵌入、零值初始化和指针接收上出错。
字段首字母大写才可被其他包访问;小写字母开头即为包私有。没有 public/private 关键字,全靠命名约定。
常见错误:误以为加了 json:"name" 标签就能让未导出字段被外部序列化——不行,encoding/json 只能访问导出字段。

Name、ID、CreatedAt
cache、version、isValid
type User struct {
ID int `json:"id"`
Name string `json:"name"`
email string `json:"email"` // 小写 → 包内可用,JSON 不会序列化
}
访问字段本身无区别,但调用方法时,值接收者会复制整个 struct,指针接收者才真正修改原值。字段赋值不受影响,但字段是 slice/map/chan/interface 时需注意底层引用共享。
常见错误:对值接收者方法修改字段,却发现调用后原变量没变;或误以为 u.Name = "x" 需要取地址才能生效——不需要,只要字段可写即可。
u.Name = "Alice" 合法,u 是变量且 Name 导出users[0].ID = 100 合法,即使 users 是切片u 是 *User,u.Name 仍可直接写,Go 自动解引用嵌入非命名字段(如 time.Time 或 Logger)后,其导出字段和方法会“提升”到外层 struct,可直接访问。但提升不等于继承,没有多态,也没有字段冲突自动覆盖机制。
常见错误:两个嵌入 struct 有同名导出字段(如都含 ID),编译报错 “ambiguous selector”;或误以为嵌入后能用子类型赋值给父类型变量——Go 没有子类型关系。
time.Time 后,可直接写 event.Before(...) 和 event.Year()
*sync.Mutex 后,可直接调用 event.Lock()
mu sync.Mutex,则必须写 e.mu.Lock()
type Event struct {
time.Time
Title string
}
e := Event{Time: time.Now(), Title: "Launch"}
fmt.Println(e.Year()) // OK — Year() 被提升
struct 零值是每个字段的零值组合(0、""、nil)。字段初始化必须按定义顺序或使用字段名,混用会导致编译错误。未指定字段将取零值,不会跳过。
常见错误:用位置参数初始化时漏掉中间某个字段,导致后续所有字段错位;或误以为未赋值字段会保持“未初始化”状态——它一定有明确零值。
User{Name: "Bob", ID: 42}
Point{1, 2}
最容易被忽略的是:嵌入 struct 的零值行为不透明——比如嵌入 sync.Mutex,它的零值本身就是有效可锁的;但嵌入自定义 struct 时,若其字段含指针或 map,零值可能引发 panic(如对 nil map 写入)。这时候得靠构造函数或显式初始化。