Skip to content

Instantly share code, notes, and snippets.

@guomaimang
Created March 29, 2023 14:09
Show Gist options
  • Save guomaimang/bace6f0dbae63825c8ce00a4ac296e03 to your computer and use it in GitHub Desktop.
Save guomaimang/bace6f0dbae63825c8ce00a4ac296e03 to your computer and use it in GitHub Desktop.
go 函数传参接口类型

如何理解

如果一个函数的参数是接口类型,传进去的参数可以是指针,也可以不是指针,这得看你传的对象是怎么实现这个接口类型的 如果实现接口的方法的接收器是指针类型,则传参给接口类型时必需是指针,如果不是,则随便传?

这段话的意思是,

  • 如果一个函数的参数是接口类型,那么这个参数可以接收任何实现了该接口的类型的值。
  • 这个值既可以是指针类型,也可以是非指针类型,取决于实现接口的类型的方法的接收器类型。
    • 如果实现接口的方法的接收器是指针类型,那么在传参给接口类型时,必须将该类型的值作为指针传入。
    • 否则,将该类型的值作为非指针传入,编译器将会报错。

例如,假设我们有一个接口类型 MyInterface,和一个实现了该接口类型的结构体类型 MyStruct,其中 MyStruct 类型的方法的接收器类型为指针类型:

type MyInterface interface {
    MyMethod()
}

type MyStruct struct{}

func (p *MyStruct) MyMethod() {}

现在,如果我们定义一个函数,其参数为 MyInterface 类型:

func MyFunction(p MyInterface) {}

那么,我们可以将一个指向 MyStruct 类型的指针作为参数传递给该函数,例如:

var p *MyStruct = &MyStruct{}
MyFunction(p)

这是因为,实现接口的方法的接收器类型是指针类型,因此在传参给接口类型时,必须将该类型的值作为指针传入。如果我们将 MyStruct 类型的值作为非指针传入,编译器将会报错:

var p MyStruct = MyStruct{}
MyFunction(p)  // compilation error: cannot use p (type MyStruct) as type MyInterface in argument to MyFunction

因此,我们必须将 MyStruct 类型的值作为指针传入:

var p *MyStruct = &MyStruct{}
MyFunction(p)

而对于实现接口的方法的接收器类型为非指针类型的情况,我们既可以将该类型的值作为指针传入,也可以将该类型的值作为非指针传入。例如,假设我们有一个实现了 MyInterface 接口的结构体类型 MyStruct2,其中 MyStruct2 类型的方法的接收器类型为非指针类型:

type MyStruct2 struct{}

func (p MyStruct2) MyMethod() {}

现在,我们可以将 MyStruct2 类型的值作为指针或非指针传递给参数类型为 MyInterface 的函数,例如:

var p MyStruct2 = MyStruct2{}
MyFunction(p)

var q *MyStruct2 = &MyStruct2{}
MyFunction(q)

也就是说,在实现接口的方法的接收器类型为非指针类型的情况下,参数类型为该接口的函数可以接受该类型的值作为指针或非指针类型的参数。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment