面试题答案
一键面试-
不同点及原因:
- 指针类型赋值给接口变量:当把
S
的指针类型赋值给接口变量时,调用M()
方法,实际上是通过指针来调用方法。这是因为Go语言中方法集的概念,对于指针接收器的方法,只有指针类型才能调用。如果使用值类型去调用指针接收器的方法,Go语言会隐式地帮我们取地址,但是在接口调用的情况下,需要明确传递指针。 - 值类型赋值给接口变量:如果把
S
的值类型赋值给接口变量,并且M()
方法是指针接收器的方法,会编译错误。因为值类型没有实现接口I
(尽管值类型可以隐式转换为指针类型去调用指针接收器的方法,但在接口赋值时这种隐式转换不适用)。如果M()
方法是值接收器的方法,值类型可以赋值给接口变量并正常调用M()
方法。
- 指针类型赋值给接口变量:当把
-
示例代码:
package main
import "fmt"
// 定义接口I
type I interface {
M()
}
// 定义结构体S
type S struct{}
// 指针接收器的方法M
func (s *S) M() {
fmt.Println("This is a method with pointer receiver")
}
func main() {
// 指针类型赋值给接口变量
var i1 I
s1 := &S{}
i1 = s1
i1.M()
// 值类型赋值给接口变量,会编译错误
// var i2 I
// s2 := S{}
// i2 = s2 // 报错:cannot use s2 (type S) as type I in assignment: S does not implement I (M method has pointer receiver)
}
如果M
方法是值接收器的方法:
package main
import "fmt"
// 定义接口I
type I interface {
M()
}
// 定义结构体S
type S struct{}
// 值接收器的方法M
func (s S) M() {
fmt.Println("This is a method with value receiver")
}
func main() {
// 指针类型赋值给接口变量
var i1 I
s1 := &S{}
i1 = s1
i1.M()
// 值类型赋值给接口变量
var i2 I
s2 := S{}
i2 = s2
i2.M()
}