我正在学习golang,当我阅读描述Structures的章节时,我遇到了不同的方法来初始化结构。
p1 := passport{}
var p2 passport
p3 := passport{
Photo: make([]byte, 0, 0),
Name: "Scott",
Surname: "Adam",
DateOfBirth: "Some time",
}
fmt.Printf("%s\n%s\n%s\n", p1, p2, p3)
虽然这些打印结构的值为
{ }
{ }
{ Scott Adam Some time}
,下面的代码用&符号打印,因为它是一个参考。
pointerp1 := &p3
fmt.Printf("%s", pointerp1)
pointerp2 := new(passport)
pointerp2.Name = "Anotherscott"
fmt.Printf("%s", pointerp2)
&{ Scott Adam Some time}&{ Anotherscott }
请帮助我解决疑惑。
pointerp1 := &p3
中,pointerp1
是p3
的引用变量,它保存实际数据。同样,保存pointerp2
数据的实际变量是什么?new
为新项目分配归零存储或输入任何内容,然后返回指向它的指针。我不认为如果你使用new
与短变量声明:= type{}
它真的很重要它主要只是偏好
至于pointer2
,当你这样做时,pointer2
变量拥有自己的数据
// initializing a zeroed 'passport in memory'
pointerp2 := new(passport)
// setting the field Name to whatever
pointerp2.Name = "Anotherscott"
new
在内存中分配归零存储并返回指向它的指针,所以简而言之,new会返回指向你所做的任何东西的指针,这就是为什么pointerp2
返回&{ Anotherscott }
当你传递一个你需要修改的变量时,你主要想要使用指针(但要注意数据竞争使用互斥锁或通道如果你需要读取和写入来自不同函数的变量)
人们使用的常用方法而不是new
只是一个短指针类型:
blah := &passport{}
blah现在是指向护照的指针
你可以在这个游乐场看到:
http://play.golang.org/p/9OuM2Kqncq
传递指针时,可以修改原始值。传递非指针时,无法修改它。那是因为go变量作为副本传递。因此,在iDontTakeAPointer
函数中,它接收测试器结构的副本,然后修改名称字段然后返回,这对我们没有任何作用,因为它正在修改副本而不是原始副本。
*pointerp2
取消引用指针,甚至将其指定给变量(p2 := pointerp2
),但此变量将是数据的副本。也就是说,修改一个不再影响另一个(http://play.golang.org/p/9yRYbyvG8q)。new
往往不那么受欢迎,特别是在结构方面。可以在https://softwareengineering.stackexchange.com/a/216582找到它的目的(提示:它首先出现)和用例的良好讨论。编辑:另外,p1
并不是真正与p3
不同的初始化,但是它不是为任何类型的字段赋值,而是将它们初始化为零值(""
为string
,nil
为[]byte
)。任何省略的字段都会发生同样的情况:
p4 := passport{
Name: "Scott",
Surname: "Adam",
}
在这种情况下,p4.Photo
和p4.DateOfBirth
仍将是零值(分别为nil
和""
)。 passport{}
案例只是省略所有字段的情况。
所有新关键字的作用基本上都是创建所需类型的实例。但是,它不是返回该类型的普通声明,而是引用它并在程序进程堆中返回该类型的实际内存地址。