在 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
;它似乎不一致。我确信这是有充分理由的。谁能启发我?
我问的原因主要是因为我想以这种方式缩短一些相当长的函数类型,但我想确保这样做是可以预期和可以接受的:)
type
在 Go 中比 Scala 更有用。 Scala only 有类型别名,唉。
事实证明,这是我对 Go 如何处理类型的误解,可以通过阅读规范的相关部分来解决:
http://golang.org/ref/spec#Type_identity
我不知道的相关区别是命名类型和未命名类型。
命名类型是具有名称的类型,例如 int、int64、float、string、bool。此外,您使用 'type' 创建的任何类型都是命名类型。
未命名类型是诸如 []string、map[string]string、[4]int 之类的类型。它们没有名称,只是与它们的结构相对应的描述。
如果比较两个命名类型,则名称必须匹配才能使它们可互换。如果您比较命名类型和未命名类型,那么只要底层表示匹配,您就可以开始了!
例如,给定以下类型:
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)
我有点内疚,我没有早点知道,所以我希望能为别人澄清一下云雀类型!并且意味着比我最初想象的要少得多:)
问题和答案都很有启发性。但是,我想提出一个在 lytnus 的回答中并不清楚的区别。
命名类型不同于未命名类型。
命名类型的变量可分配给未命名类型的变量,反之亦然。
不同命名类型的变量不能相互分配。
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
}
如果最终(作为类型的类型可能是案例)基础类型是原始类型,则 GO 将不允许将一种类型的变量直接分配给另一种类型,反之亦然。但是,可以将值强制转换为目标类型并使用。
package main
import (
"fmt"
)
type T int
type U T
type V U
type UU U
func main() {
var s int
var t T
var u U
var uu UU
s = 9
t = 10
u = 11
uu = 111
fmt.Println(s)
fmt.Println(t)
fmt.Println(u)
fmt.Println(uu)
fmt.Println("========")
//s = t
//u = s
//v = s
u = (U)(uu)
//fmt.Println(s)
//fmt.Println(u)
fmt.Println(u)
}
is := make(MySlice, 0); m := make(MyMap)
,它在某些情况下更具可读性。