【问题标题】:Golang basics struct and new() keywordGolang 基础结构和 new() 关键字
【发布时间】:2016-04-05 05:58:21
【问题描述】:

我正在学习 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. 使用这些不同类型的初始化的最佳方案是什么?

【问题讨论】:

  • Go 没有“引用”的概念。不要将指针命名为“引用”。

标签: pointers struct go


【解决方案1】:

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 的常用方法就是short dec 指针类型:

blah := &passport{}

blah 现在是输入护照的指针

你可以在这个游乐场看到:

http://play.golang.org/p/9OuM2Kqncq

传递指针时,可以修改原始值。传递非指针时,您无法修改它。那是因为在 go 中变量是作为副本传递的。因此,在iDontTakeAPointer 函数中,它接收测试器结构的副本,然后修改名称字段然后返回,这对我们没有任何作用,因为它正在修改副本而不是原始结构。

【讨论】:

  • iDoTakeAPointer 函数也接收到指针的副本(但它指向的数据完全一样)。
  • 我发现 new 来自 go 团队的一个完全奇怪的决定,& 是其他语言使用的,new 似乎你正在分配内存并将项目复制到它,这是逆。
【解决方案2】:
  1. 还有保存数据的变量。您可以使用*pointerp2 取消对指针的引用,甚至将其分配给一个变量(p2 := pointerp2),但该变量将是数据的副本。也就是说,修改一个不再影响另一个 (http://play.golang.org/p/9yRYbyvG8q)。

  2. new 往往不太受欢迎,尤其是在结构方面。可以在https://softwareengineering.stackexchange.com/a/216582 找到关于其目的(提示:它是第一位的)和用例的详细讨论。

编辑:另外,p1 与p3 并没有真正不同的初始化类型,而是没有为任何类型的字段赋值,而是将它们初始化为零值("" for string , nil 为 []byte)。任何省略的字段都会发生同样的情况:

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

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

【讨论】:

【解决方案3】:

new 关键字所做的基本上就是创建一个你想要的类型的实例。但是,它不是返回类型的普通声明,而是引用它并返回程序进程堆中该类型的实际内存地址。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    • 2013-10-20
    • 1970-01-01
    相关资源
    最近更新 更多