英文:
Golang basics struct and new() keyword
问题
以下是翻译好的内容:
我正在学习Golang,在学习描述结构体的章节时,我遇到了不同的结构体初始化方式。
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
来说,保存数据的实际变量是什么? -
在哪些情况下最适合使用这些不同类型的初始化方式?
英文:
I was learning golang, and as I was going through the chapter that describes Structures, I came across different ways to initialize 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)
While these print the values of the structures as
{ }
{ }
{ Scott Adam Some time}
, the following code below prints with an ampersand because it is a reference.
pointerp1 := &p3
fmt.Printf("%s", pointerp1)
pointerp2 := new(passport)
pointerp2.Name = "Anotherscott"
fmt.Printf("%s", pointerp2)
&{ Scott Adam Some time}&{ Anotherscott }
Kindly help me with my doubts.
-
in the usage
pointerp1 := &p3
,pointerp1
is the reference variable top3
, which holds the actual data. Similarly, what would be the actual variable that holds the data forpointerp2
? -
What would be the best scenarios to use these different types of initialization?
答案1
得分: 78
new
为新项目或类型分配了一个零值存储空间,然后返回一个指向它的指针。我认为使用new
和使用短变量声明:= type{}
来分配零值存储空间并没有太大区别,主要是个人偏好。
至于pointer2
,pointer2
变量保存了自己的数据,当你执行以下操作时:
// 在内存中初始化一个零值的'passport'
pointerp2 := new(passport)
// 将字段Name设置为任意值
pointerp2.Name = "Anotherscott"
new
为内存分配了零值存储空间,并返回一个指向它的指针,所以简而言之,new
将返回一个指向你正在创建的对象的指针,这就是为什么pointerp2
返回&{ Anotherscott }
。
当你需要修改传递的变量时,主要使用指针(但要小心数据竞争,使用互斥锁或通道来读写来自不同函数的变量)。
人们通常使用短变量声明来代替new
,只需声明一个指针类型:
blah := &passport{}
现在,blah
是指向passport
类型的指针。
你可以在这个playground中看到示例:
http://play.golang.org/p/9OuM2Kqncq
当传递指针时,你可以修改原始值。当传递非指针时,你无法修改它。这是因为在Go中,变量是按值传递的。所以在iDontTakeAPointer
函数中,它接收到的是tester
结构体的副本,然后修改了name
字段,然后返回,这对我们来说没有任何作用,因为它修改的是副本而不是原始值。
英文:
new
allocates zeroed storage for a new item or type whatever and then returns a pointer to it. I don't think it really matters on if you use new
vs short variable declaration := type{}
it's mostly just preference
As for pointer2
, the pointer2
variable holds its own data, when you do
// initializing a zeroed 'passport in memory'
pointerp2 := new(passport)
// setting the field Name to whatever
pointerp2.Name = "Anotherscott"
new
allocates zeroed storage in memory and returns a pointer to it, so in short, new will return a pointer to whatever you're making that is why pointerp2
returns &{ Anotherscott }
You mainly want to use pointers when you're passing a variable around that you need to modify (but be careful of data races use mutexes or channels If you need to read and write to a variable from different functions)
A common method people use instead of new
is just short dec a pointer type:
blah := &passport{}
blah is now a pointer to type passport
You can see in this playground:
http://play.golang.org/p/9OuM2Kqncq
When passing a pointer, you can modify the original value. When passing a non pointer you can't modify it. That is because in go variables are passed as a copy. So in the iDontTakeAPointer
function it is receiving a copy of the tester struct then modifying the name field and then returning, which does nothing for us as it is modifying the copy and not the original.
答案2
得分: 4
-
有一个变量仍然保存着数据。你可以使用
*pointerp2
来取消引用指针,甚至可以将其赋值给一个变量(p2 := pointerp2
),但是这个变量将是数据的副本。也就是说,修改一个变量不再影响另一个变量(http://play.golang.org/p/9yRYbyvG8q)。 -
new
在使用上不太流行,特别是在结构体方面。关于它的目的(提示:它是最早出现的)和使用场景的讨论可以在https://softwareengineering.stackexchange.com/a/216582找到。
编辑:此外,p1
与p3
的初始化方式并不完全不同,只是没有给类型的任何字段赋值,它们被初始化为它们的零值(string
为""
,[]byte
为nil
)。对于任何省略的字段,都会发生同样的情况:
p4 := passport{
Name: "Scott",
Surname: "Adam",
}
在这种情况下,p4.Photo
和p4.DateOfBirth
仍然是零值(分别为nil
和""
)。passport{}
的情况只是所有字段都被省略的情况之一。
英文:
-
There is variable that holds the data yet. You can dereference the pointer using
*pointerp2
, and even assign it that to a variable (p2 := pointerp2
), but this variable would be a copy of the data. That is, modifying one no longer affects the other (http://play.golang.org/p/9yRYbyvG8q). -
new
tends to be less popular, especially with regard to structs. A good discussion of its purpose (hint: it came first) and use cases can be found at https://softwareengineering.stackexchange.com/a/216582.
Edit: Also, p1
is not really a different kind of initialization from p3
, but instead of assigning a value to any of the type's fields they are initialized to their zero value (""
for string
, nil
for []byte
). The same would happen for any omitted fields:
p4 := passport{
Name: "Scott",
Surname: "Adam",
}
In this case, p4.Photo
and p4.DateOfBirth
would still be zero-valued (nil
and ""
respectively). The passport{}
case it just one where all the fields are omitted.
答案3
得分: 4
所有new关键字做的基本上只是创建一个你想要的类型的实例。然而,它不是返回类型的简单声明,而是引用它并返回该类型在程序进程堆中的实际内存地址。
英文:
All the new keyword does is basically create a instance of the type you want. However instead of returning the plain declaration of the type, it references it and return the acutal memory address of that type in the program process heap.
答案4
得分: 0
我在使用Golang时遇到了奇怪的现象。我声明的指针myptr:= new(ptrtype)
在if myptr==nil
中结果为false,所以我尝试将其定义为myptr:=&ptrtype{}
,但仍然不起作用。然后我只是使用new()定义了指针,然后将其设置为nil,现在它可以正常工作了。不知道为什么其他的方式不需要这样做。
英文:
I was experiencing strange phenomena in golang where my pointer declared as myptr:= new(ptrtype)
was resulting in false from if myptr==nil
, so I went ahead and tried defining it as myptr:=&ptrtype{}
and still didn't work. So then I just defined the pointer with new() and then i set it = nill and now it works. don't know why I didn't have to do that with the other ones.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论