Goで、新しいタイプを定義する場合:例:
type MyInt int
その後、MyInt
をintが必要な関数に渡すことはできません。逆も同様です。
func test(i MyInt) {
//do something with i
}
func main() {
anInt := 0
test(anInt) //doesn't work, int is not of type MyInt
}
いいよしかし、なぜ同じことが関数に適用されないのですか?例えば。:
type MyFunc func(i int)
func (m MyFunc) Run(i int) {
m(i)
}
func run(f MyFunc, i int) {
f.Run(i)
}
func main() {
var newfunc func(int) //explicit declaration
newfunc = func(i int) {
fmt.Println(i)
}
run(newfunc, 10) //works just fine, even though types seem to differ
}
最初の例で行うように、newfunc
をタイプMyFunc
に明示的にキャストする必要がないので、文句を言いません。一貫していないようです。それには十分な理由があると確信しています。誰でも私を啓発できますか?
私が尋ねる理由は主に、この方法でかなり長い関数タイプのいくつかを短くしたいからですが、これを行うことが期待され、受け入れられることを確認したいです:)
結局のところ、これはGoが型をどのように扱うかについての誤解であり、仕様の関連部分を読むことで解決できます。
http://golang.org/ref/spec#Type_identity
私が知らなかった関連する区別は、namedとunnamedタイプ。
Named型は、int、int64、float、string、boolなどの名前を持つ型です。また、「type」を使用して作成するタイプは名前付きタイプです。
Unnamedタイプは、[] string、map [string] string、[4] intなどです。それらには名前はなく、単に構造化方法に対応する説明があります。
2つの名前付きタイプを比較する場合、それらを交換可能にするには名前が一致する必要があります。名前付き型と名前なし型を比較する場合、基礎となる表現が一致する限り、行ってもいいです!
例えば次のタイプが与えられます:
type MyInt int
type MyMap map[int]int
type MySlice []int
type MyFunc func(int)
次は無効です。
var i int = 2
var i2 MyInt = 4
i = i2 //both named (int and MyInt) and names don't match, so invalid
以下は問題ありません:
is := make([]int)
m := make(map[int]int)
f := func(i int){}
//OK: comparing named and unnamed type, and underlying representation
//is the same:
func doSlice(input MySlice){...}
doSlice(is)
func doMap(input MyMap){...}
doMap(m)
func doFunc(input MyFunc){...}
doFunc(f)
私はそれをすぐに知りませんでしたが、少し意気消沈しているので、他の誰かのためにタイプラークを少し明確にすることを願っています!そして、私が最初に考えたよりもはるかに少ないキャストを意味します:)
質問と回答はどちらも非常に啓発的です。しかし、リトヌスの答えでは明確ではない区別を持ち出したいと思います。
名前付きタイプは、名前なしタイプとは異なります。
Named Typeの変数は、Unnamed Typeの変数に割り当て可能です。
異なるNamed Typeの変数は、互いに割り当てることができません。
http://play.golang.org/p/uaYHEnofT9
import (
"fmt"
"reflect"
)
type T1 []string
type T2 []string
func main() {
foo0 := []string{}
foo1 := T1{}
foo2 := T2{}
fmt.Println(reflect.TypeOf(foo0))
fmt.Println(reflect.TypeOf(foo1))
fmt.Println(reflect.TypeOf(foo2))
// Output:
// []string
// main.T1
// main.T2
// foo0 can be assigned to foo1, vice versa
foo1 = foo0
foo0 = foo1
// foo2 cannot be assigned to foo1
// prog.go:28: cannot use foo2 (type T2) as type T1 in assignment
// foo1 = foo2
}