Golang基础:结构体和new()关键字

huangapple go评论69阅读模式
英文:

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 }

请帮我解答以下疑问:

  1. 在使用pointerp1 := &p3时,pointerp1是指向p3的引用变量,它保存了实际的数据。类似地,对于pointerp2来说,保存数据的实际变量是什么?

  2. 在哪些情况下最适合使用这些不同类型的初始化方式?

英文:

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.

  1. in the usage pointerp1 := &p3, pointerp1 is the reference variable to p3, which holds the actual data. Similarly, what would be the actual variable that holds the data for pointerp2?

  2. What would be the best scenarios to use these different types of initialization?

答案1

得分: 78

new为新项目或类型分配了一个零值存储空间,然后返回一个指向它的指针。我认为使用new和使用短变量声明:= type{}来分配零值存储空间并没有太大区别,主要是个人偏好。

至于pointer2pointer2变量保存了自己的数据,当你执行以下操作时:

// 在内存中初始化一个零值的'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

  1. 有一个变量仍然保存着数据。你可以使用*pointerp2来取消引用指针,甚至可以将其赋值给一个变量(p2 := pointerp2),但是这个变量将是数据的副本。也就是说,修改一个变量不再影响另一个变量(http://play.golang.org/p/9yRYbyvG8q)。

  2. new在使用上不太流行,特别是在结构体方面。关于它的目的(提示:它是最早出现的)和使用场景的讨论可以在https://softwareengineering.stackexchange.com/a/216582找到。

编辑:此外,p1p3的初始化方式并不完全不同,只是没有给类型的任何字段赋值,它们被初始化为它们的零值(string""[]bytenil)。对于任何省略的字段,都会发生同样的情况:

p4 := passport{
    Name: "Scott",
    Surname: "Adam",
}

在这种情况下,p4.Photop4.DateOfBirth仍然是零值(分别为nil"")。passport{}的情况只是所有字段都被省略的情况之一。

英文:
  1. 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).

  2. 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.

huangapple
  • 本文由 发表于 2015年12月31日 16:27:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/34543430.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定