In Go, if you define a new type e.g.:
type MyInt int
You can't then pass a MyInt
to a function expecting 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 is it then that the same does not apply to functions? e.g.:
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'm not complaining because it saves me having to explicitly cast newfunc
to type MyFunc
, as I would have to do in the first example; it just seems inconsistent. I'm sure there is a good reason for it; can anyone enlighten me?
The reason I ask is mainly because I would like to shorten some of my rather long function types in this way, but I want to make sure it's expected and acceptable to do this :)
Type aliases provide alternative names for existing types. If the type name is too long you can introduce a different shorter name and use the new one instead.
In a project, we might declare variables of the same datatype multiple times like declaring a variable of Api response class type in Android or maybe using the same function again and again which might not make your code readable.
Type is the base interface for all data types in Go. This means that all other data types (such as int , float , or string ) implement the Type interface. Type is defined in the reflect header.
Turns out, this is a misunderstanding that I had about how Go dealt with types, which can be resolved by reading the relevant part of the spec:
http://golang.org/ref/spec#Type_identity
The relevant distinction that I was unaware of was that of named and unnamed types.
Named types are types with a name, such as int, int64, float, string, bool. In addition, any type you create using 'type' is a named type.
Unnamed types are those such as []string, map[string]string, [4]int. They have no name, simply a description corresponding to how they are to be structured.
If you compare two named types, the names must match in order for them to be interchangeable. If you compare a named and an unnamed type, then as long as the underlying representation matches, you're good to go!
e.g. given the following types:
type MyInt int type MyMap map[int]int type MySlice []int type MyFunc func(int)
the following is invalid:
var i int = 2 var i2 MyInt = 4 i = i2 //both named (int and MyInt) and names don't match, so invalid
the following is fine:
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 I didn't know that sooner, so I hope that clarifies the type lark a little for someone else! And means much less casting than I at first thought :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With