Struct 附加到结构片时内存地址无效或无指针取消引用

Struct 附加到结构片时内存地址无效或无指针取消引用,struct,go,slice,Struct,Go,Slice,以上方法很好 package main import ( "fmt" ) type Person struct { name string } func main() { p := make([]*Person, 0) p = append(p, &Person{"Brian"}) fmt.Println(p[0].name) p = append(p, &Person{"Le Tu"}) fmt.Println

以上方法很好

package main

import (
    "fmt"
)

type Person struct {
    name    string
}

func main() {
    p := make([]*Person, 0)
    p = append(p, &Person{"Brian"})
    fmt.Println(p[0].name)
    p = append(p, &Person{"Le Tu"})
    fmt.Println(p[1].name)
}
上述恐慌

我对append的理解是它隐藏了扩展/添加的机制。显然,我使用
append
作为切片“推送”的思维模式是不正确的。有人能解释为什么上面的第二个样本会恐慌吗?为什么我不能只
附加
我的结构

例如

package main

import (
    "fmt"
)

type Person struct {
    name    string
}

func main() {
    p := make([]*Person, 1) //Changed to 1 instead of 0
    p = append(p, &Person{"Brian"})
    fmt.Println(p[0].name)
    p = append(p, &Person{"Le Tu"})
    fmt.Println(p[1].name)
}
输出:

package main

import (
    "fmt"
)

type Person struct {
    name string
}

func main() {
    p := make([]*Person, 1) //Changed to 1 instead of 0
    fmt.Println(len(p), p)
    p = append(p, &Person{"Brian"})
    fmt.Println(len(p), p)
    fmt.Println(p[1].name)
    fmt.Println(p[0])
    fmt.Println(p[0].name)
}
1[]
2[0x10500190]
布瑞恩
死机:运行时错误:无效内存地址或零指针取消引用
p
追加前长度为1,追加后长度为2。因此,
p[0]
具有未初始化的指针值
nil
p[0]。name
无效

变量函数append将零个或多个值x附加到 类型S,它必须是切片类型,并返回结果切片, 也属于S型

未初始化指针的值为零

以下规则适用于选择器:

4) 如果x是指针类型,且值为nil,且x.f表示结构字段,则为x.f赋值或求值会导致运行时死机

使用
make
构建切片时,第一个整数参数是所创建切片的实际长度:

1 [<nil>]
2 [<nil> 0x10500190]
Brian
<nil>
panic: runtime error: invalid memory address or nil pointer dereference

关于如何使用这两种情况的简单示例:

p := make([]*Person, 0, 100) //<- slice of length 0, but the first 100 append 
                             //   won't reallocate the slice
//100单元切片:
p1:=制造([]*人,100)
对于i:=0;i<100;i++{
名称:=fmt.Sprintf(“Foo%d”,i+1)
//您可以访问并分配给p1[i],因为p1有100个单元格:
p1[i]=&个人{name}
}
fmt.Printf(“p1[0]。名称:%s\n”,p1[0]。名称)
fmt.Printf(“p1[99]。名称:%s\n”,p1[99]。名称)
//0单元,100容量片:
p2:=制造([]*人,0,100)
对于i:=0;i<100;i++{
名称:=fmt.Sprintf(“Foo%d”,i+1)
//您无法访问p2[i],该单元格尚不存在:
p2=追加(p2,&个人{name})
}
fmt.Printf(“p2[0]。名称:%s\n”,p2[0]。名称)
fmt.Printf(“p2[99]。名称:%s\n”,p2[99]。名称)

p := make([]*Person, 0, 100) //<- slice of length 0, but the first 100 append 
                             //   won't reallocate the slice
//100-cell slice :
p1 := make([]*Person, 100)
for i := 0; i < 100; i++ {
    name := fmt.Sprintf("Foo %d", i+1)
    //you can access and assign to p1[i] because p1 has 100 cells :
    p1[i] = &Person{name}
}
fmt.Printf("p1[0].Name : %s\n", p1[0].Name)
fmt.Printf("p1[99].Name : %s\n", p1[99].Name)

//0-cell, 100-capacity slice :
p2 := make([]*Person, 0, 100)
for i := 0; i < 100; i++ {
    name := fmt.Sprintf("Foo %d", i+1)
    //you cannot access p2[i], the cell doesn't exist yet :
    p2 = append(p2, &Person{name})
}
fmt.Printf("p2[0].Name : %s\n", p2[0].Name)
fmt.Printf("p2[99].Name : %s\n", p2[99].Name)