2013-10-12 11 views
59

In Vai, se si definisce un nuovo tipo ad es .:Perché posso digitare le funzioni alias e usarle senza eseguire il cast?

type MyInt int 

Non si può quindi passare un MyInt a una funzione in attesa di un int, o viceversa:

func test(i MyInt) { 
    //do something with i 
} 

func main() { 
    anInt := 0 
    test(anInt) //doesn't work, int is not of type MyInt 
} 

fine. Ma perché è allora che lo stesso non si applica alle funzioni? es .:

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 
} 

Ora, non mi lamento perché consente di risparmiare me dover gettato esplicitamente newfunc digitare MyFunc, come avrei dovuto fare nel primo esempio; sembra solo incoerente. Sono sicuro che c'è una buona ragione per questo; qualcuno può illuminarmi?

Il motivo che mi chiedo è soprattutto perché vorrei accorciare alcuni dei miei tipi di funzione piuttosto lunghi in questo modo, ma voglio fare in modo ci si aspetta ed accettabile per fare questo :)

+3

** In Vai, non v'è alcuna cosa come un 'tipo alias'. ** Il' type' parola chiave introduce nuovi tipi di nome. Non sono alias. (Questo è uno dei punti di forza di Go rispetto a vari altri linguaggi) –

+0

@ Rick-777 C'è qualcosa come alias di tipo, ad esempio 'byte' è alias di' uint8' e 'rune' è alias di' int32', ma è vero che la parola chiave 'type' non crea alias ma nuovi tipi. – icza

+0

Sì, grazie per averlo indicato - ci sono due casi speciali: byte e rune. Questi * sono * alias, ma non è possibile creare nuovi alias. https://golang.org/ref/spec#Numeric_types –

risposta

107

scopre, questo è un equivoco che ho avuto su come Go affrontato i tipi, che può essere risolto con la lettura la parte rilevante della specifica:

http://golang.org/ref/spec#Type_identity

la distinzione rilevante che non conoscevo era quella di nome e tipi senza nome.

I tipi sono tipi con un nome, ad esempio int, int64, float, stringa, bool. Inoltre, qualsiasi tipo che crei usando 'type' è un tipo con nome.

I tipi senza nome sono quelli come [] stringa, mappa [stringa] stringa, [4] int. Non hanno un nome, semplicemente una descrizione corrispondente al modo in cui devono essere strutturati.

Se si confrontano due tipi nominati, i nomi devono corrispondere affinché siano intercambiabili. Se confronti un nome e un tipo senza nome, quindi finché la rappresentazione sottostante corrisponde a, sei a posto!

ad es. date le seguenti tipologie:

type MyInt int 
type MyMap map[int]int 
type MySlice []int 
type MyFunc func(int) 

il seguente non è valido:

var i int = 2 
var i2 MyInt = 4 
i = i2 //both named (int and MyInt) and names don't match, so invalid 

il seguente va bene:

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) 

io sono un po 'sventrato non sapevo che prima, quindi spero che chiarisca un po 'il tipo di allodola per qualcun altro! E significa molto meno casting di quanto avessi inizialmente pensato :)

+0

questo link aiuta anche: http://golang.org/ref/spec#Type_declarations –

10

Sia la domanda che la risposta sono piuttosto illuminanti. Tuttavia, vorrei fare una distinzione che non è chiara nella risposta di Lytnus.

  • Chiamato Tipo è diverso da Senza nome Type.

  • variabile di Chiamato tipo è assegnabile alla variabile di Senza nome Tipo, viceversa.

  • Variabile di diverso Il tipo con nome non è assegnabile tra loro.

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 
} 
Problemi correlati