Go中接口指针赋值报错原因及正确赋值方法
Go代码编译错误分析与修复方案
错误产生的原因
你这里的问题核心是混淆了接口类型和指向接口的指针类型:
- 你定义的
foo结构体中,bar字段的类型是*intr,也就是「指向intr接口的指针」。 - 而
&bar1的实际类型是*bar,虽然*bar确实实现了intr接口,但Go不会自动把一个实现了接口的具体类型指针,转换为「指向接口的指针」——因为接口本身已经是一个包含类型元信息和值的封装体,绝大多数场景下完全不需要使用接口的指针。
编译器的错误提示已经说得很明确:*intr is pointer to interface, not interface,意思是你把具体类型指针当成了接口指针来用,但这俩不是一回事。
正确的赋值方式
根据你的需求,有两种常见的修复方案:
方案1:直接使用接口类型(推荐,绝大多数场景都用这个)
把foo结构体的bar字段类型从*intr改成intr,这样直接赋值实现了接口的类型值(或指针)即可:
package main import "fmt" type intr interface { String() string } type bar struct{} func (b *bar) String() string { return "bar" } // 修改字段类型为intr,而非*intr type foo struct { bar intr } func main() { bar1 := bar{} // 直接把*bar类型的&bar1赋值给intr类型的字段 foo1 := foo{bar: &bar1} fmt.Println(foo1) }
方案2:必须使用接口指针的场景(极少用到)
如果你确实需要保留*intr类型的字段,那得先把*bar赋值给一个intr类型的变量,再取这个变量的地址:
package main import "fmt" type intr interface { String() string } type bar struct{} func (b *bar) String() string { return "bar" } type foo struct { bar *intr } func main() { bar1 := bar{} // 先把*bar赋值给intr类型变量 var i intr = &bar1 // 再取变量的地址赋值给*intr类型的字段 foo1 := foo{bar: &i} fmt.Println(foo1) }
一般来说,方案1是Go里的常规写法,除非你有特别的理由需要操作接口的指针,否则优先用方案1。
内容的提问来源于stack exchange,提问作者施虞斌
相关产品推荐
相关产品推荐

