同じシグネチャを持つ異なる関数たちのreflect.Typeのidentityについて

シグネチャが同じ関数のreflect.Typeが一致することに気づかずハマったりしていた1

package main

import (
    "fmt"
    "reflect"
)

type Foo string
type Bar string
type Alias = string

func Hello(string) string {
    return ""
}
func Byebye(string) string {
    return ""
}

func main() {
    fmt.Println(reflect.TypeOf(func() string { return "" }()))

    // new typeはそれぞれ異なるreflect.Type
    fmt.Println("----------------------------------------")
    fmt.Println(reflect.TypeOf(func() Foo { return Foo("") }()))
    fmt.Println(reflect.TypeOf(func() Bar { return Bar("") }()))

    // aliasはもちろん元の型と同じ。
    fmt.Println("----------------------------------------")
    fmt.Println(reflect.TypeOf(func() Alias { return Alias("") }()))

    // この関数たちのreflect.Typeが同じことに気づかなかった
    fmt.Println("========================================")
    fmt.Println(reflect.TypeOf(func() interface{} { return Hello }()))
    fmt.Println(reflect.TypeOf(func() interface{} { return Byebye }()))
}

実行結果。

string
----------------------------------------
main.Foo
main.Bar
----------------------------------------
string
========================================
func(string) string
func(string) string

考えてみれば当たり前だけど、たしかにね、と言う感じ。

gist


  1. 何を作っていたかは一つ前の記事を見ればわかる。あと、関数のシグネチャとしてみたときに引数名も消えてしまうのが結構辛かった。