最常用且易出错的是字面量初始化,需严格匹配字段顺序与大小写;new()和&User{}仅做零值分配;含默认值或校验时应使用New开头的自定义函数。
Go 中结构体初始化最直观的是用字面量,但必须注意字段顺序和是否导出。如果结构体字段未全部赋值,未指定的字段会按类型零值初始化(int 为 0,string 为 "",指针为 nil)。
UserName 和 username 是两个不同字段 User{"tom", Age: 25} ❌,必须全用键值式或全用位置式 type User struct {
Name string
Age int
}
u1 := User{"Alice", 30} // 位置式,依赖声明顺序
u2 := User{Name: "Bob", Age: 28} // 键值式,推荐,可读性强、抗字段增删new(User) 返回指向零值结构体的指针(*User),所有字段都是零值;&User{} 效果相同,但更常用、更直观。
new(User) 和 &User{} 都不会调用任何构造逻辑,只是内存分配 + 零初始化 new() 是“构造函数”——Go 没有构造函数概念 Status 默认是 "active"),这两种方式都做不到,必须封装成函数 uPtr1 := new(User) // *User,Name="", Age=0
uPtr2 := &User{} // 等价于上面,但更常见
uPtr3 := &User{Name: "Cindy"} // 字段可部分初始化,未写的仍是零值当结构体需要非零默认值、字段校验、或初始化时需访问外部资源(如配置、DB 连接),应封装为函数,通常命名为 NewXXX。
New 开头表示它返回一个新实例(Go 社区惯例) func NewUser(name string, age int) *User {
if name == "" {
name = "anonymous"
}
if age < 0 {
age = 0
}
return &User{Name: name, Age: age}
}
// 调用
u := NewUser("David", -5) // → Name="David", Age=0
嵌套结构体初始化时,键值式写法必须显式写出每一层字段名;匿名字段(内嵌)则允许“提升”访问,但初始化仍需按实际结构展开。
Profile: Profile{Nick: "X"},不能简写为 Nick: "X" 
json.Unmarshal 或其他序列化库时,嵌套字段标签(如 json:"nick")不影响初始化语法,只影响编解码行为 type Profile struct {
Nick string
}
type User struct {
Name string
Profile // 匿名字段
}
// 正确初始化(显式写出嵌套)
u := User{
Name: "Eve",
Profile: Profile{Nick: "evie"},
}
// 错误:不能直接写 Nick(Go 不支持字段提升式初始化)
// u := User{Name: "Eve", Nick: "evie"} ❌
字段多、嵌套深、有默认逻辑的结构体,靠裸字面量初始化很快会失控。真正工程中,90% 的非 trivial 结构体都应该配一个 NewXXX 函数——不是为了“规范”,而是为了把默认值、约束、上下文耦合点收口到一处。