Pourquoi est-ce que je peux taper des fonctions d’alias et les utiliser sans casting?

Dans Go, si vous définissez un nouveau type, par exemple:

type MyInt int 

Vous ne pouvez pas alors passer un object MyInt à une fonction qui attend un int, ou inversement:

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

Bien. Mais pourquoi est-ce alors que la même chose ne s’applique pas aux fonctions? par exemple:

 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 } 

Maintenant, je ne me plains pas parce que cela évite d’avoir à newfunc explicitement newfunc pour taper MyFunc , comme je devrais le faire dans le premier exemple; cela semble juste incohérent. Je suis sûr qu’il y a une bonne raison à cela. quelqu’un peut-il m’éclairer?

La raison pour laquelle je pose la question est principalement parce que je voudrais raccourcir certains de mes types de fonction plutôt longs de cette manière, mais je veux m’assurer que cela est attendu et acceptable pour cela 🙂

Il s’agit d’un malentendu sur la manière dont Go a traité les types, ce qui peut être résolu en lisant la partie pertinente de la spécification:

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

La distinction pertinente que je n’étais pas au courant était celle des types nommés et non nommés .

Les types nommés sont des types avec un nom, tels que int, int64, float, ssortingng, bool. De plus, tout type créé à l’aide de ‘type’ est un type nommé.

Les types sans nom sont ceux tels que [] ssortingng, map [ssortingng] ssortingng, [4] int. Ils n’ont pas de nom, simplement une description correspondant à la manière dont ils doivent être structurés.

Si vous comparez deux types nommés, les noms doivent correspondre pour qu’ils soient interchangeables. Si vous comparez un type nommé et un type non nommé, alors tant que la représentation sous-jacente correspond , vous êtes prêt à partir!

par exemple, étant donné les types suivants:

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

ce qui suit n’est pas valide:

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

ce qui suit va bien:

 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) 

Je suis un peu vidé, je ne le savais pas plus tôt, alors j’espère que cela clarifie un peu le type d’alouette pour quelqu’un d’autre! Et signifie beaucoup moins de casting que moi au premier abord 🙂

La question et la réponse sont toutes deux éclairantes. Cependant, je voudrais faire une distinction qui n’est pas claire dans la réponse de lytnus.

  • Type nommé est différent du type sans nom .

  • La variable de type nommé est assignable à la variable de type sans nom , vice versa.

  • La variable de type nommé différent ne peut pas être affectée.

http://play.golang.org/p/uaYHEnofT9

 import ( "fmt" "reflect" ) type T1 []ssortingng type T2 []ssortingng func main() { foo0 := []ssortingng{} foo1 := T1{} foo2 := T2{} fmt.Println(reflect.TypeOf(foo0)) fmt.Println(reflect.TypeOf(foo1)) fmt.Println(reflect.TypeOf(foo2)) // Output: // []ssortingng // 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 }