当范围超过结构片段时,Golang内存地址问题

时间:2014-06-15 12:39:02

标签: go

我是Go的新手,所以可能有一个非常简单的解决方案。我在调用数组结构中的接口方法时遇到问题。我认为最好通过一个例子来解释,所以这里是我能够将代码简化为最基本的例子。

package main

import "fmt"

/* Test Types */
type Test interface {
    Hello() string
}

type TestRecord struct {
    test Test
    name string
}

type TestList []TestRecord

/* Other Type */
type Other struct{}

func (o Other) Hello() string {
return "Hello From Other"
}

func main() {
    /* Init TestList into t */
    t := make(TestList, 1, 100)

    /* Create TestRecord and add it to the list */
    tr := TestRecord{Other{}, "OtherRecord"}
    t = append(t, tr)

    /* Loop over list and  */
    for _, otr := range t {
        fmt.Println(otr.name)
        fmt.Println(otr.test.Hello())
    }
} 

当我尝试执行此操作时,出现以下错误:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x20 pc=0x400efd]

如何在此设置中循环播放数组时正确调用Hello?

1 个答案:

答案 0 :(得分:6)

你的问题在

 t := make(TestList, 1, 100)

在这里,您已初始化t已经有一个TestRecord,但您没有设置TestRecord中的任何字段,因此t[0].testnil。您无法在nil界面上调用方法,因为Go不知道要调用哪种方法。

最简单的修补程序(最少修改源代码的修复程序)是使用以下语句从空TestList开始:

t := make(TestList, 0, 100)

但是,如果您愿意,您还可以依赖append根据需要分配t,并通过声明nil TestList t开始如下:

var t TestList

(我推荐你的测试程序中的第二个版本,因为你还没有使用完整的容量,但是我知道你可能已经从真正的程序中浓缩了这个,预先指定容量实际上是有帮助的。 )


在零值

上调用方法
  • 您可以在nil 结构指针上调用方法,因为Go可以确定在编译时应该调用哪个函数。但是,如果该函数取消引用结构指针,那么您将在取消引用的站点上遇到同样的崩溃。
  • 当您通过界面访问此指针时,Go需要取消引用它以确定要调用的函数,因此一旦您进行函数调用,程序就会崩溃。 / LI>