0
Help us understand the problem. What are the problem?

posted at

【Golangエラー】type does not implement as method has a pointer receiver

interfaceを受け取る関数に構造体を渡そうとしたところ、エラーが出てきてちょっとつまづいたのでメモです。
hello worldを出力するシンプルなプログラムを見ながら挙動を確認します。

うまくいかない場合

以下のコードだと Type does not implement 'sampleInterface' as the ... has a pointer receiverというエラーが出てうまくいきません。

main.go
package main

import "fmt"

type sampleInterface interface {
	DoSomething()
}

func interfaceReceiverFunc(si sampleInterface) {
	si.DoSomething()
}

type sampleStruct struct {}

func (s *sampleStruct) DoSomething()  {
	fmt.Println("hello world")
}

func main() {
	s := sampleStruct{}
	interfaceReceiverFunc(s)
}

スクリーンショット 2022-04-26 0.50.51.png

うまくいく場合その1:構造体のポインタを渡す

mainの中身をポインタに直せばうまくいきます。

main.go
func main() {
	s := &sampleStruct{}
	interfaceReceiverFunc(s)
}

なぜでこれでうまくいくのか?以下のコードを見るとポインタレシーバに対して、インターフェースのメソッドが定義されているためです。DoSomething*sampleStructのメソッドであり、sampleStructのメソッドではありません。なのでポインタで渡すことでうまくいったのです。

func (s *sampleStruct) DoSomething()  {
	fmt.Println("hello world")
}

うまくいく場合その2:構造体レシーバを実体にする

構造体のレシーバを実体にすれば、回避できます。ただこれよりはポインタレシーバにする場合がほとんどだと思うので、その1がいいかと思います。

main.go
func (s sampleStruct) DoSomething()  {
	fmt.Println("hello world")
}

func main() {
	s := sampleStruct{}
	interfaceReceiverFunc(s)
}

参考

以下が参考になりました。

こちらに以下のように書かれていまして、そちらをほぼ意訳した感じになります。

  • A pointer to the value must be used, whose method set will include the method with the pointer receiver
  • Or the receiver type must be changed to non-pointer, so the method set of the non-pointer concrete type will also contain the method (and thus satisfy the interface). This may or may not be viable, as if the method has to modify the value, a non-pointer receiver is not an option.

Register as a new user and use Qiita more conveniently

  1. You can follow users and tags
  2. you can stock useful information
  3. You can make editorial suggestions for articles
What you can do with signing up
0
Help us understand the problem. What are the problem?