When I define a custom type, it seems that the type of the underlying type makes a difference about whether I can pass it to a function as is or I need to convert it.
Question is:
Why does RuneFunc
and StringMap
work, but not Integer
?
https://play.golang.org/p/buKNkrg5y-
package main
type RuneFunc func(rune) rune
type Integer int
type StringMap map[string]string
func main() {
//m := make(StringMap)
//mf(m)
var i Integer = 5
nf(i)
//var f func(rune) rune
//ff(f)
}
func mf(i map[string]string) {
}
func ff(i func(rune)rune) {
}
func nf(i int) {
}
Here, when I run this function called nf
with Integer
it complains although int
is the underlying type. But when I call mf
or ff
they run successfully.
Integer
and int
int
and your new type Integer
are 2 different, distinct types. Where Integer
is expected, you have to pass a value of type Integer
.
If you have an Integer
value, you may use a simple type conversion to make it a value of type int
, because the underlying type of Integer
is int
:
var i Integer = 5
nf(int(i))
What may be confusing and interesting at the same time is that you are allowed to pass an untyped constant without conversion:
nf(5)
Try these on the Go Playground.
The reason for this is in the Spec: Assignability:
A value
x
is assignable to a variable of typeT
("x
is assignable toT
") in any of these cases:[...]
x
is an untyped constant representable by a value of typeT
.
5
is an untyped constant which is representable by a value of type int
because the untyped constant 5
has a default type int
, so it is representable by a value of type Integer
(which has the same default type).
If you check the other assignability rules (not included in above quotation), none of them match the case where you attempt to pass a value of Integer
for the parameter of type int
, so that's not allowed.
See related question: Golang: Creating a Constant Type and Restricting the Type's Values
RuneFunc
and func(rune) rune
The difference between this case and the previous one (Integer
and int
) is that int
is a named type and func(rune) rune
is not.
And there's an assignability rule which allows this:
x
's typeV
andT
have identical underlying types and at least one ofV
orT
is not a named type.
So in this case:
var f RuneFunc
ff(f)
f
is a named type, but the parameter type of ff()
is func(rune) rune
which is unnamed, so the assignment is allowed.
Go has a strict type system. Just because your type is merely an alias for int doesn't mean you can interchange the two freely, you'll still have to do a type conversion. Below is a working version of your main, here's the code on play ground: https://play.golang.org/p/BDTXnnG9Lg
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