Go でインターフェース型の reflect.Type を取得する方法

Go の reflect パッケージを使っていて、ときどき操作している変数型との比較のために error などのインターフェース型の reflect.Type がほしいことがあるのだけれど、これは reflect.TypeOf((*error)(nil)).Elem() のように書くことで得られる。つまり、

  • nil をほしい型のポインタ型に変換
  • それを reflect.TypeOf に渡してポインタ型の reflect.Type を取得し
  • Elem() でポインタをデリファレンスしてできる基本型の reflect.Type を得る

という流れ。 Go の公式パッケージではよく見かける書法。これを使うと、たとえば変数が error インターフェースを満たすかどうかの判定は

package main

import (
        "errors"
        "fmt"
        "reflect"
)

func main() {
	err := errors.New("A problem occurs")
	et := reflect.TypeOf(err)
	if et.Implements(reflect.TypeOf((*error)(nil)).Elem()) {
		fmt.Println("This is an error type")
	} else {
		fmt.Println("This isn't an error type")
	}
}

のように書ける。もちろん、これはリフレクションを操作してる時の話で、普通は

package main

import (
        "errors"
        "fmt"
)

func main() {
	err := errors.New("A problem occurs")
	if _, ok := err.(error); ok {
		fmt.Println("This is an error type")
	} else {
		fmt.Println("This isn't an error type")
	}
}

とするのがよい