Golang结构体(Struct)定义与实例化_自定义数据类型

8次阅读

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

Golang结构体(Struct)定义与实例化_自定义数据类型

Struct字段首字母大小写决定是否可导出

Go里没有public/private关键字,靠命名规则控制可见性。字段名首字母大写才能被其他包访问,小写就只能在当前包用。

常见错误现象:json.Marshal序列化时字段为空、reflect读不到值、跨包调用报“undefined”——八成是字段没导出。

  • 导出字段:Name StringID int
  • 非导出字段:name stringid int(哪怕加了json:"name"标签,json.Marshal也拿不到值)
  • 如果只在本包内用,小写没问题;但只要涉及JSON、Gob、数据库映射或跨包使用,必须大写

匿名字段嵌入不是继承,而是字段提升

type User struct { Person }看起来像继承,其实只是把Person的**可导出字段**直接“提上来”,变成User自己的字段。

使用场景:复用通用字段(比如IDCreatedAt),避免重复定义;但别指望它有方法继承或运行时多态

立即学习go语言免费学习笔记(深入)”;

  • 如果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 valuescannot use ... as type User in assignment

  • 正确写法:User{Name: "tom", Age: 25}
  • 可以省略部分字段(未赋值的按零值处理):User{Name: "tom"}Age0
  • 如果结构体字段多且初始化逻辑分散,建议封装工厂函数,而不是依赖字面量拼接

指针接收者 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空、方法不生效或者赋不了值。

text=ZqhQzanResources