Pointers Golang basics结构和new()关键字

Pointers Golang basics结构和new()关键字,pointers,struct,go,Pointers,Struct,Go,我在学习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) 而这些将结构的值打印为 {} {

我在学习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某时}
,下面的代码使用符号AND打印,因为它是一个参考

pointerp1 := &p3
fmt.Printf("%s", pointerp1)
pointerp2 := new(passport)
pointerp2.Name = "Anotherscott"
fmt.Printf("%s", pointerp2)
&{Scott Adam某时}&{Anotherscott}

请帮我解答我的疑问

  • 在用法
    pointerp1:=&p3
    中,
    pointerp1
    p3
    的参考变量,它保存实际数据。类似地,保存
    pointerp2
    数据的实际变量是什么

  • 使用这些不同类型的初始化的最佳方案是什么


  • 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}

    在传递需要修改的变量时,您主要希望使用指针(但如果需要从不同的函数读取和写入变量,请小心使用互斥量或通道)

    人们使用的一种代替新的
    的常用方法是指针类型:

    blah:=&passport{}

    blah现在是指向passport类型的指针

    你可以在这个操场上看到:

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

  • 还有一个变量保存数据。您可以使用
    *pointerp2
    取消对指针的引用,甚至将其分配给变量(
    p2:=pointerp2
    ),但该变量将是数据的副本。也就是说,修改一个不再影响另一个()

  • new
    不太受欢迎,尤其是在结构方面。关于它的用途(提示:它首先出现)和用例的详细讨论可以在上找到

  • 编辑:另外,
    p1
    p3
    实际上并不是一种不同的初始化类型,而是将它们初始化为零值(
    用于
    字符串
    nil
    用于
    []字节
    )。任何省略的字段也会发生同样的情况:

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

    在这种情况下,
    p4.Photo
    p4.DateOfBirth
    仍然是零值(
    nil
    )。
    passport{}
    案例只是一个省略所有字段的案例。

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

    @Datsik它打印
    []
    ,但其值
    nil
    ;看见这里也有很好的讨论。TL;DR:nil切片在许多方面都像空切片。我知道这一点,但对于下一个新的广告来说,这应该理解,即使他们看到[]它实际上仍然是零。一个典型的例子是json值为null:即使在调试时,您认为您有一个空的切片,但Go并没有“引用”的概念。不要将指针命名为“引用”。
    iDoTakeAPointer
    函数也会收到指针的副本(但它指向的数据完全相同)。我发现go团队做出了一个非常奇怪的决定,
    &
    是其他语言使用的,
    new
    似乎您正在分配内存并将项目复制到内存中,而这恰恰相反。