HomeBlogProjects

Go 中 struct 初始化

sorcererxw

刚接触的 Golang 总是被 Golang 当中的 struct 困扰,无论是初始化方式、多种数据类型和结构体组合方式,都和以往接触的其他语言有不小的区别,本文将进行梳理。

疑问

Go 当中有多种方式来初始化一个 struct:

那么这些方式都有什么区别呢?为什么简洁至上的 Go 要引入这么多不同的初始化方式?

Go 当中存在多种类型,包括以下:

定义如下的 Foobar 结构体:

type Foo struct {
}

func (Foo) callVFoo() {
	fmt.Println("vfoo")
}

func (*Foo) callPFoo() {
	fmt.Println("pfoo")
}

type Bar struct {
}

func (Bar) callVBar() {
	fmt.Println("vbar")
}

func (*Bar) callPBar() {
	fmt.Println("pbar")
}
type Foobar struct {
	Foo
	*Bar

	vFoo Foo
	pFoo *Foo

	vNum int
	pNum *int

	vArr [5]int
	pArr *[5]int

  s  []int
	m  map[int]int
	c  chan int
}
这些成员变量都会以何种信息被初始化?

实验

对于不同的 fb 分别运行以下代码,并观察结果:

1. fb := Foobar{}
2. fb := new(Foobar)
3. var fb Foobar
4. var fb *Foobar

func test(fb) {
	fmt.Printf("%+v\n", fb)
  fmt.Printf("slice is nil: %t\n", fb.s == nil)
	fmt.Printf("map is nil: %t\n", fb.m == nil)
	fmt.Printf("chan is nil: %t\n", fb.c == nil)

	fb.callPFoo()
	fb.callVFoo()
	fb.callPBar()
	fb.callVBar()
}
运行结果1:
{Foo:{} Bar:<nil> vFoo:{} pFoo:<nil> vNum:0 pNum:<nil> vArr:[0 0 0 0 0] pArr:<nil> s:[] m:map[] c:<nil>}
slice is nil: true
map is nil: true
chan is nil: true
pfoo
vfoo
pbar
panic: runtime error: invalid memory address or nil pointer dereference
运行结果2:
&{Foo:{} Bar:<nil> vFoo:{} pFoo:<nil> vNum:0 pNum:<nil> vArr:[0 0 0 0 0] pArr:<nil> s:[] m:map[] c:<nil>}
slice is nil: true
map is nil: true
chan is nil: true
pfoo
vfoo
pbar
panic: runtime error: invalid memory address or nil pointer dereference
运行结果3:
{Foo:{} Bar:<nil> vFoo:{} pFoo:<nil> vNum:0 pNum:<nil> vArr:[0 0 0 0 0] pArr:<nil> s:[] m:map[] c:<nil>}
slice is nil: true
map is nil: true
chan is nil: true
pfoo
vfoo
pbar
panic: runtime error: invalid memory address or nil pointer dereference
运行结果4:
<nil>
panic: runtime error: invalid memory address or nil pointer dereference

结论