types - tour - golang variable type




為什麼我可以鍵入別名函數並使用它們而不進行轉換? (2)

在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

我不知道的相關區別是命名未命名類型。

命名類型是具有名稱的類型,例如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