Go语言调用切片内接口类型元素的方法触发panic如何解决
问题根因
两个核心错误触发panic:
- 方法名大小写不匹配,结构体未真正实现接口
你定义的RGTree接口要求的方法是GetID()、GetParentID(),但你给ItemTest实现的是小写结尾的GetId()、GetParentId(),Go语言大小写敏感,这两个不属于接口要求的实现方法。 - 结构体嵌入了未初始化的接口字段导致空指针
你在ItemTest结构体里嵌入了RGTree类型的字段,但初始化ItemTest实例时没有给这个嵌入字段赋值,它默认是nil。因为你没有实现接口全部方法,Go会自动将嵌入接口的方法提升为结构体方法,调用时就会触发nil指针panic。
为什么直接调用切片外的实例方法没问题?因为你直接调用的是
ItemTest结构体自己定义的GetId方法,走的是结构体方法调用逻辑,不需要走接口派发。而存入[]RGTree切片后,调用方法会走接口的动态派发逻辑,此时发现你没有实现对应方法,就会调用嵌入的nil接口字段的方法,触发空指针panic。
修复方案
第一步:删掉结构体里不必要的嵌入接口字段
要让ItemTest实现RGTree接口,不需要把接口作为字段嵌入,直接删除对应声明即可。
第二步:把方法名改成和接口定义一致
把GetId改成GetID,GetParentId改成GetParentID。
修复后的可运行代码:
package RGTree import ( "fmt" "testing" ) type RGTree interface { GetParent () RGTree SetParent (RGTree) GetID () int GetParentID () int } // 删掉嵌入的RGTree接口字段 type ItemTest struct { ID int ParentId int } func (it ItemTest) SetParent(item RGTree) { } func (it ItemTest) GetParent() RGTree { return it } // 方法名改成和接口一致的GetID func (it ItemTest) GetID() int { return it.ID } // 方法名改成和接口一致的GetParentID func (it ItemTest) GetParentID() int { return it.ParentId } func TestMakeTreeMap(t *testing.T) { var plain []RGTree root := ItemTest{ID: 1} plain = append(plain, root) plain = append(plain, ItemTest{ID: 2, ParentId: 1}) plain = append(plain, ItemTest{ID: 3, ParentId: 1}) plain = append(plain, ItemTest{ID: 4, ParentId: 2}) plain = append(plain, ItemTest{ID: 5, ParentId: 2}) plain = append(plain, ItemTest{ID: 6, ParentId: 2}) plain = append(plain, ItemTest{ID: 7, ParentId: 3}) plain = append(plain, ItemTest{ID: 8, ParentId: 3}) plain = append(plain, ItemTest{ID: 9, ParentId: 4}) plain = append(plain, ItemTest{ID: 10, ParentId: 4}) fmt.Println(plain[0].GetID()) // 现在可以正常输出1 }
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

