go结构体字段首字母大写才可导出,影响json序列化、跨包访问等;匿名字段仅提升可导出字段;字面量初始化必须显式命名字段;方法接收者类型决定是否可修改原值及性能表现。

Struct字段首字母大小写决定是否可导出
Go里没有public/private关键字,靠命名规则控制可见性。字段名首字母大写才能被其他包访问,小写就只能在当前包用。
常见错误现象:json.Marshal序列化时字段为空、reflect读不到值、跨包调用报“undefined”——八成是字段没导出。
- 导出字段:
Name string、ID int - 非导出字段:
name string、id int(哪怕加了json:"name"标签,json.Marshal也拿不到值) - 如果只在本包内用,小写没问题;但只要涉及JSON、Gob、数据库映射或跨包使用,必须大写
匿名字段嵌入不是继承,而是字段提升
写type User struct { Person }看起来像继承,其实只是把Person的**可导出字段**直接“提上来”,变成User自己的字段。
使用场景:复用通用字段(比如ID、CreatedAt),避免重复定义;但别指望它有方法继承或运行时多态。
立即学习“go语言免费学习笔记(深入)”;
使用模板与程序分离的方式构建,依靠专门设计的数据库操作类实现数据库存取,具有专有错误处理模块,通过 Email 实时报告数据库错误,除具有满足购物需要的全部功能外,成新商城购物系统还对购物系统体系做了丰富的扩展,全新设计的搜索功能,自定义成新商城购物系统代码功能代码已经全面优化,杜绝SQL注入漏洞前台测试用户名:admin密码:admin888后台管理员名:admin密码:admin888
- 如果
Person有字段Name string,那么u := User{}; u.Name = "x"合法 - 但如果
Person有个方法func (p Person) Greet(),u.Greet()不能直接调,得显式写u.Person.Greet() - 两个匿名字段含同名导出字段会编译报错:
ambiguous selector u.Name
结构体字面量初始化时字段顺序无关,但必须带字段名
Go要求结构体字面量必须显式写出字段名,不能靠顺序推断——这是为了可维护性,但也让初学者觉得啰嗦。
常见错误现象:写User{"tom", 25}直接编译失败,提示too few values或cannot use ... as type User in assignment。
- 正确写法:
User{Name: "tom", Age: 25} - 可以省略部分字段(未赋值的按零值处理):
User{Name: "tom"}→Age为0 - 如果结构体字段多且初始化逻辑分散,建议封装工厂函数,而不是依赖字面量拼接
指针接收者 vs 值接收者影响方法调用和内存行为
定义方法时用func (u *User) Save()还是func (u User) Save(),不只是语法区别,它决定了你操作的是原数据还是副本。
性能/兼容性影响:值接收者每次调用都复制整个结构体;指针接收者只传地址,但要求调用方必须能取地址(即不能对字面量或临时值直接调用)。
- 要修改结构体字段?必须用指针接收者:
func (u *User) SetName(n string) { u.Name = n } - 结构体很大(比如含
[]byte或大数组)?优先指针接收者,避免拷贝开销 - 常见坑:
User{Name: "x"}.SetName("y")编译失败——字面量没地址,无法取&;得先赋值给变量再调
字段导出规则、匿名字段的“扁平化”语义、字面量强制命名、接收者类型选择——这四点串起来,才是日常写Struct时真正卡住人的地方。漏掉任何一个,都可能花半小时查不出为什么JSON空、方法不生效或者赋不了值。









