Go の interface

Go の interface は Java, PHP といった言語と比べて使い方が異なる。例えば, 独自例外の定義には, error interface の実装が必要。

golang/go

とてもシンプルなインターフェースで実装例は以下の通り

package hoge

type MyError struct {
  Id int
  Name string
}

func (e *MyError) Error() string {
  return fmt.Sprintf("id: %s name: %s")
}

var undefinedError := &MyError{Id: 1, Name: "undefined"}

// 型として error を返すメソッドの中で実際 error が実装されていることを確認できる
func hoge() error {
  return undefinedError
}

こんな感じで実装する側では interface にあるメソッドを実装するだけでいい。自身で定義する場合でも同じ。

  1. interface を定義する
  2. interface にあるメソッドを書く

Accept Interfaces, Return structs

Go は本家がベスプラ(推奨レベル)を公開してる。タイトルに含まれる「Accept Interfaces, Return structs」は, その中の一つ。

golang/go

先ほど紹介した error interface は, go 側では「エラーはこのような振る舞いをする。どのように実装するかはあなた次第だ。」となっている。これに従うよう「扱う側でインターフェース。実装する側は実物。」を定義したほうがいいぞ。という話。

シンプルな例を出す。packge foo が Hoge interface を扱う例。

package foo

import "fmt"

type Hoge interface {
	HogeMethod() string
}

func Exec(h Hoge) {
	fmt.Println(h.HogeMethod())
}

この場合, 単に string を返す HogeMethod を持つなんかを実装すればいい。

package hoge

type Hoge struct{}

func New() *Hoge {
	return &Hoge{}
}

func (h *Hoge) HogeMethod() string {
	return "hoge method."
}
package main

import (
	"fmt"

	"github.com/somen440/zatsu/golang/interface/foo"
	"github.com/somen440/zatsu/golang/interface/hoge"
)

func main() {
	fmt.Println("interface test --")
	foo.Exec(hoge.New())
}

結果は以下の通り, 読み込める。

zatsu/golang/interface on  master [$?] via 🐹 v1.14.4 
❯ go run .
interface test --
        hoge method.