2013-10-12 23 views
59

在走,如果你定義一個新的類型例如爲:爲什麼我可以輸入別名函數並在不投射的情況下使用它們?

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,因爲我會在第一個例子做;它似乎不一致。我確信有一個很好的理由。任何人都可以啓發我嗎?

我想問的原因,主要是因爲我想縮短我的一些相當長的函數類型的這種方式,但我想,以確保它的預期和可接受做到這一點:)

+3

**在走,沒有這樣的事,作爲一個'型alias' **的'type'關鍵字引入新命名的類型。他們不是別名。 (這是Go與其他各種語言相比的重要優勢之一) –

+0

@ Rick-777存在類型別名,例如'byte'是'uint8'的別名,'rune'是'int32'的別名,但是確實'type'關鍵字不會生成別名,而是新的類型。 – icza

+0

是的,謝謝指出 - 有兩種特殊情況:字節和符文。這些*是*別名,但不可能創建任何新的別名。 https://golang.org/ref/spec#Numeric_types –

回答

107

事實證明,這是一種誤解,認爲我對圍棋是如何處理的類型,這可以通過閱讀該規範的相關部分來解決:

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) 

我有點燒燬我不知道得越早,所以我希望能爲其他人澄清一下這種類型的百靈鳥!而且意味着比我想象的要少得多的想法:)

+0

這個鏈接也有幫助:http://golang.org/ref/spec#Type_declarations –

10

問題和答案都非常有啓發性。但是,我想提出一個在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 
} 
相關問題