Why can I introduce alias functions and use them without casting?

In Go, if you define a new type, for example:

type MyInt int 

You cannot pass a MyInt to a function that expects an int, or vice versa:

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

Fine But why then the same does not apply to functions? eg:.

 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 } 

Now I am not complaining because it saves me from casting newfunc explicitly in order to dial MyFunc , as I would have done in the first example; it just seems inconsistent. I am sure there is a good reason for this; can anyone enlighten me?

The reason I'm asking for is mainly because I would like to shorten some of my rather long types of functions in this way, but I want to make sure that this is expected and acceptable for this :)

+57
casting types go
Oct 12 '13 at 13:07 on
source share
2 answers

It turns out that this is a misunderstanding that I had about how Go relates to types, which can be solved by reading the relevant part of the specification:

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

The corresponding distinction that I did not know about applies to types with and without a name .

Named types are types with a name such as int, int64, float, string, bool. In addition, any type that you create using "type" has a named type.

Types without are like [] string, map [string] string, [4] int. They do not have a name, just a description corresponding to how they should be structured.

If you are comparing two named types, the names must match so that they are interchangeable. If you are comparing a named and an unnamed type, then as long as the main view is consistent , you're good to go!

eg. given the following types:

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

the following is not allowed:

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

in order:

 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) 

I'm a bit gutted that I didn't know before, so I hope this clarifies the lark type for someone else! And it means much less casting than I thought at first :)

+104
Oct 12 '13 at 13:51
source share

Both questions and answers are quite enlightening. However, I would like to talk about the difference, which is not clear in Litnu's answer.

  • The named type is different from Untitled .

  • Variable A named type is assigned to an unnamed variable, vice versa.

  • A variable of a different named type is not assigned to each other.

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 } 
+9
Aug 16 '14 at 18:14
source share



All Articles