我正在学习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
的数据的实际变量是什么?
使用这些不同类型的初始化的最佳方案是什么?
答案 0 :(得分:37)
new
为新项目分配归零存储或输入任何内容,然后返回指向它的指针。我认为,如果你使用new
vs短变量声明:= 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 }
< / p>
当你传递一个你需要修改的变量时,你主要想要使用指针(但要注意数据竞争使用互斥或通道如果你需要读取和写入来自不同函数的变量)
人们使用的常用方法而不是new
只是短指针类型:
blah := &passport{}
blah现在是指向护照
的指针你可以在这个游乐场看到:
http://play.golang.org/p/9OuM2Kqncq
传递指针时,可以修改原始值。传递非指针时,无法修改它。那是因为go变量作为副本传递。因此,在iDontTakeAPointer
函数中,它接收到测试器结构的副本,然后修改名称字段然后返回,这对我们没有任何作用,因为它正在修改副本而不是原始副本。
答案 1 :(得分:3)
还有保存数据的变量。您可以使用*pointerp2
取消引用指针,甚至将其指定给变量(p2 := pointerp2
),但此变量将是数据的副本。也就是说,修改一个不再影响另一个(http://play.golang.org/p/9yRYbyvG8q)。
new
往往不那么受欢迎,特别是在结构方面。可以在https://softwareengineering.stackexchange.com/a/216582找到关于其目的(提示:它首先出现)和用例的良好讨论。
编辑:此外,p1
实际上并不是p3
的另一种初始化,而是将值分配给任何类型的字段,而不是将它们初始化为零值({{1 } ""
,string
代表nil
)。任何省略的字段都会发生同样的情况:
[]byte
在这种情况下,p4 := passport{
Name: "Scott",
Surname: "Adam",
}
和p4.Photo
仍然是零值(分别为p4.DateOfBirth
和nil
)。 ""
只是一个省略所有字段的情况。
答案 2 :(得分:2)
所有新关键字的作用基本上都是创建所需类型的实例。但是,它不是返回该类型的普通声明,而是引用它并在程序进程堆中返回该类型的实际内存地址。