Why can I type alias functions and use them without casting?
在Go中,如果定义了新类型,例如:
1 | type MyInt int |
然后不能将
1 2 3 4 5 6 7 8 | func test(i MyInt) { //do something with i } func main() { anInt := 0 test(anInt) //doesn't work, int is not of type MyInt } |
好的。但为什么同样的情况不适用于函数呢?例如。:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 } |
现在,我没有抱怨,因为这样我就不用像在第一个例子中那样显式地将
我之所以问这个问题,主要是因为我想用这种方式缩短一些相当长的函数类型,但我想确保这样做是可以预期的和可以接受的:)
事实证明,这是我对Go如何处理类型的误解,可以通过阅读规范的相关部分来解决:
http://golang.org/ref/spec_type_标识
我不知道的相关区别是命名和未命名类型的区别。
命名类型是具有名称的类型,例如int、int64、float、string、bool。此外,使用"type"创建的任何类型都是命名类型。
未命名的类型是那些类型,如[]string、map[string]string、[4]int。它们没有名称,只是与它们的结构相对应的描述。
如果比较两个命名类型,则名称必须匹配才能互换。如果比较一个命名类型和一个未命名类型,那么只要底层表示匹配,就可以了!
例如,给定以下类型:
1 2 3 4 | type MyInt int type MyMap map[int]int type MySlice []int type MyFunc func(int) |
以下内容无效:
1 2 3 | var i int = 2 var i2 MyInt = 4 i = i2 //both named (int and MyInt) and names don't match, so invalid |
以下是好的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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) |
我有点失望,我不知道这么快,所以我希望这澄清了类型百灵鸟有点为别人!这意味着比我一开始想的要少得多。
这个问题和答案都很有启发性。然而,我想提出一个在莱特努斯的回答中不清楚的区别。
命名类型与未命名类型不同。
命名类型的变量可以分配给未命名类型的变量,反之亦然。
不同命名类型的变量不能相互赋值。
http://play.golang.org/p/uayhenoft9
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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 } |