MST

星途 面试题库

面试题:Go接口运算之方法集匹配问题

在Go语言中,假设有一个接口`I`定义了一个方法`M()`,有一个结构体`S`实现了该方法。现在将`S`的指针类型和值类型分别赋值给`I`类型的变量,在调用`M()`方法时会有什么不同?请说明原因并举例代码实现。
11.2万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
  1. 不同点及原因

    • 指针类型赋值给接口变量:当把S的指针类型赋值给接口变量时,调用M()方法,实际上是通过指针来调用方法。这是因为Go语言中方法集的概念,对于指针接收器的方法,只有指针类型才能调用。如果使用值类型去调用指针接收器的方法,Go语言会隐式地帮我们取地址,但是在接口调用的情况下,需要明确传递指针。
    • 值类型赋值给接口变量:如果把S的值类型赋值给接口变量,并且M()方法是指针接收器的方法,会编译错误。因为值类型没有实现接口I(尽管值类型可以隐式转换为指针类型去调用指针接收器的方法,但在接口赋值时这种隐式转换不适用)。如果M()方法是值接收器的方法,值类型可以赋值给接口变量并正常调用M()方法。
  2. 示例代码

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()
}