I am very new to Go so there is probably a very simple fix for this. I am having trouble calling a method of an interface that is within a struct in an array. I think this is best explained through an example, so here is the most basic example I was able to boil my code down to.
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())
}
}
When I try to execute this, I get the following error:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xb code=0x1 addr=0x20 pc=0x400efd]
How do I properly call Hello while looping through the array in this setup?
Your problem is in the line
t := make(TestList, 1, 100)
Here, you've initialized t to already have one TestRecord
in it, but you didn't set any of the fields in that TestRecord
, so t[0].test
is nil
. You can't call methods on a nil
interface, because Go doesn't know what method to call.
The simplest fix (the one that changes your source code the least) is to start with an empty TestList
, using the following statement:
t := make(TestList, 0, 100)
However, if you wish, you can also rely on append
to allocate t
as necessary, and start with a nil
TestList
by declaring t
as follows:
var t TestList
(I recommend the second version in your test program, since you're not using the full capacity anyway, however I recognize that you may have condensed this from a real program where specifying the capacity in advance is actually helpful.)
nil
struct pointer, because Go can determine what function should be called at compile time. However, if that function dereferences the struct pointer, then you'll get this same crash at the site of the dereference.