go中struct字段首字母大小写决定是否可导出:小写字段包外不可见,大写字段才可被跨包访问、序列化和反射;json标签等struct tag需配合对应库解析,且key须小写、无空格、用ascii引号。

Struct 字段首字母大小写决定是否可导出
Go 没有 public/private 关键字,靠字段名首字母大小写控制包外可见性。小写字段(如 name)只能在定义它的包内访问;大写字段(如 Name)才能被其他包读写。
常见错误现象:json.Marshal 返回空对象或零值,或外部包调用时字段始终为零值——八成是字段没大写。
- 导出字段必须首字母大写,否则序列化、反射、跨包访问都会失效
- 即使结构体本身是导出的(
User),内部小写字段(id)对外仍是“隐身”的 - JSON 标签(
json:"user_id")不能绕过导出规则:字段不导出,json包直接跳过它
嵌套 Struct 时避免循环引用和零值陷阱
嵌套结构体很常见,但容易忽略初始化顺序和零值传播。比如 type Order struct { User User },如果 User 是值类型,每次复制都深拷贝;如果是指针(*User),则共享底层数据,但也可能引入 nil panic。
使用场景:API 响应结构、ORM 模型、配置嵌套解析。
立即学习“go语言免费学习笔记(深入)”;
- 优先用指针嵌套(
User *User)处理可选关联,避免无意义的零值填充 - 若嵌套结构体字段全为小写,外层即使导出也无法访问内层字段
-
==不能比较含 slice/map/func 的 struct,嵌套了这些类型时要手写比较逻辑
Struct Tag 不只是给 JSON 用的
Struct tag 是紧挨字段声明的字符串注释,形如 `json:"id,string" db:"user_id" validate:"required"`。它本身不生效,必须由对应库(如 encoding/json、gorm.io/gorm、go-playground/validator)主动解析。
容易踩的坑:写了 tag 却没调用对应库的解析函数,或者拼错 key 名(如写成 jsom)导致完全被忽略。
- tag key 必须全小写,且与使用它的库约定一致(
json、db、yaml等) - 空格敏感:
`json:"name,omitempty" `末尾多一个空格,整个 tag 就失效 - 双引号必须是 ASCII 直角引号,中文引号或全角符号会导致编译失败
匿名字段不是“继承”,只是字段提升
Go 支持匿名字段(如 User),看起来像面向对象的继承,实际只是语法糖:编译器把匿名字段的导出字段“提升”到外层 struct 范围内,不带任何方法或运行时关系。
典型误用:以为 type Admin struct { User } 能自动获得 User 的方法,结果编译报错 Admin has no field or method XXX。
- 匿名字段只能是类型名(
User),不能是泛型实例(Generic[string])或带参数的类型别名 - 字段提升只作用于导出字段;如果
User里只有小写字段,Admin依然看不到它们 - 同名字段冲突时(如
Admin自己也定义了Name),提升失效,必须显式通过admin.User.Name访问










