在 Go 语言中,有多种方式可以实例化结构体(struct)。下面是几种常见的方法:
1. 使用 var
关键字
var p Person // p 是 Person 类型的零值实例
- 这种方式创建的
p
是结构体的零值实例,字段的值都是默认值(比如int
是0
,string
是""
)。
2. 使用 :=
直接赋值
p := Person{}
- 这与
var p Person
类似,但使用:=
方式定义并初始化。
3. 使用字段名初始化
p := Person{Name: "Alice", Age: 25}
- 这种方式可以按照字段名赋值,推荐使用,可读性强。
4. 不指定字段名的顺序初始化
p := Person{"Alice", 25}
- 这种方式必须按照结构体定义的字段顺序传值,不推荐使用,因为结构体字段顺序变化会导致代码不可用。
5. 使用 new
关键字
p := new(Person)
p.Name = "Bob"
p.Age = 30
new(Person)
返回的是*Person
指针,而p.Name
这种访问方式是 Go 允许的简写,等价于(*p).Name = "Bob"
。
6. 使用 &
取地址
p := &Person{Name: "Charlie", Age: 28}
- 这种方式直接返回结构体的指针,避免手动取地址。
7. 使用构造函数
Go 语言没有构造函数的概念,但可以使用函数来封装结构体的初始化逻辑:
func NewPerson(name string, age int) *Person {
return &Person{Name: name, Age: age}
}
p := NewPerson("David", 35)
- 这种方式在实际开发中非常常见,类似于构造函数。
8. 结合 sync.Pool
实现对象池
如果结构体实例化开销大,可用 sync.Pool
进行优化:
import "sync"
var personPool = sync.Pool{
New: func() interface{} {
return &Person{}
},
}
p := personPool.Get().(*Person)
p.Name = "Eve"
p.Age = 40
// 用完后放回池中
personPool.Put(p)
sync.Pool
适用于需要频繁创建和销毁的结构体,减少 GC 压力。
结构体示例代码:
package main
import "fmt"
type Person struct {
Name string
Age int
}
func main() {
// 方式 1: var
var p1 Person
fmt.Println(p1)
// 方式 2: {}
p2 := Person{}
fmt.Println(p2)
// 方式 3: 字段名初始化
p3 := Person{Name: "Alice", Age: 25}
fmt.Println(p3)
// 方式 4: 省略字段名
p4 := Person{"Bob", 30}
fmt.Println(p4)
// 方式 5: new 关键字
p5 := new(Person)
p5.Name = "Charlie"
p5.Age = 28
fmt.Println(*p5)
// 方式 6: & 取地址
p6 := &Person{Name: "David", Age: 35}
fmt.Println(*p6)
// 方式 7: 使用构造函数
p7 := NewPerson("Eve", 40)
fmt.Println(*p7)
}
func NewPerson(name string, age int) *Person {
return &Person{Name: name, Age: age}
}
总结
方法 | 代码示例 | 说明 |
---|---|---|
var 关键字 | var p Person | 结构体零值 |
:= 赋值 | p := Person{} | 结构体零值 |
使用字段名初始化 | p := Person{Name: "Alice", Age: 25} | 推荐,清晰可读 |
省略字段名初始化 | p := Person{"Alice", 25} | 不推荐,字段顺序变动会出错 |
new 关键字 | p := new(Person) | 返回 *Person 指针 |
& 取地址 | p := &Person{Name: "Bob", Age: 30} | 直接返回 *Person 指针 |
构造函数封装 | p := NewPerson("David", 35) | 推荐,封装逻辑 |
sync.Pool 对象池 | p := personPool.Get().(*Person) | 适用于高频对象创建销毁 |
最推荐的方式:
- 使用字段名初始化
Person{Name: "Alice", Age: 25}
—— 直观易读 - 使用构造函数
NewPerson("David", 35)
—— 可封装逻辑 - 使用
&
取地址&Person{Name: "Bob", Age: 30}
—— 直接返回指针,简洁高效