如何避免“无效的内存地址或空指针解除引用”错误?

时间:2012-02-27 11:48:40

标签: go

我想知道如何构造这个示例代码以帮助避免空指针解除引用恐慌:

package main

import "fmt"

type Astruct struct {
    Number int
    Letter string
}

type Bstruct struct {
    foo int
    AStructList *[]Astruct
}

type Cstruct struct {
    Bstruct
}

func (a *Astruct) String() string {
    return fmt.Sprintf("Number = %d, Letter = %s", a.Number, a.Letter)
}

func main() {
    astructlist := make([]Astruct, 3)      // line 1
    for i := range astructlist {           // line 2
        astructlist[i] = Astruct{i, "a"}   // line 3
    }                                      // line 4
    c := new(Cstruct)
    c.Bstruct = Bstruct{100, &astructlist} // line 6

    for _, x := range(*c.Bstruct.AStructList) {
        fmt.Printf("%s\n", &x)
    }
}

如果省略main()的第1-4和第6行,我会得到一个空指针解除引用恐慌。如果没有检查c!= nil,有没有办法避免这些恐慌?

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:6)

在这种特殊情况下,您可以使用惯用Go。将AStructList *[]Astruct更改为AStructList []*Astruct。例如,

package main

import "fmt"

type Astruct struct {
    Number int
    Letter string
}

type Bstruct struct {
    foo         int
    AStructList []*Astruct
}

type Cstruct struct {
    Bstruct
}

func (a *Astruct) String() string {
    return fmt.Sprintf("Number = %d, Letter = %s", a.Number, a.Letter)
}

func main() {
    astructlist := make([]*Astruct, 3)            // line 1
    for i := range astructlist {                  // line 2
        astructlist[i] = &Astruct{i, "a"}         // line 3 
    }                                             // line 4
    c := new(Cstruct)
    c.Bstruct = Bstruct{100, astructlist}         // line 6

    for _, x := range c.Bstruct.AStructList {
        fmt.Printf("%s\n", x)
    }
}

通常,您有责任在使用前为nil指定非nil值或指针nil。如果在未明确初始化的情况下分配内存,则会将其设置为类型的零值,即指针的{{1}}。

  

The zero value

     

当分配内存来存储值时,通过a   声明或调用make或new,并且没有明确的初始化   如果提供,则为存储器提供默认初始化。每   将此类值的元素设置为其类型的零值:false   对于布尔值,0表示整数,0.0表示浮点数,""对于字符串,没有   用于指针,函数,接口,切片,通道和映射。这个   初始化是递归完成的,所以例如每个元素   如果没有指定值,结构数组将使其字段归零。