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

Kay*_*lly 3 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())
    }
} 
Run Code Online (Sandbox Code Playgroud)

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

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x20 pc=0x400efd]
Run Code Online (Sandbox Code Playgroud)

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

Ken*_*oom 6

你的问题就在于此

 t := make(TestList, 1, 100)
Run Code Online (Sandbox Code Playgroud)

在这里,你已经初始化吨至已经有一个TestRecord在里面,但你没有设置任何在该领域TestRecord,所以t[0].testnil.你不能在nil接口上调用方法,因为Go不知道要调用什么方法.

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

t := make(TestList, 0, 100)
Run Code Online (Sandbox Code Playgroud)

但是,如果您愿意,您也可以依赖于必要时append进行分配t,并nil TestList以声明t如下开头:

var t TestList
Run Code Online (Sandbox Code Playgroud)

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


在nil值上调用方法

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