I wonder why this code compiles in go. I expected a compiler error as I would with e.g. string:
package main
import (
"fmt"
)
type myMap map[string]int
type mySlice []int
type myChan chan int
type myString string
func main() {
var mm myMap
var m map[string]int
m = mm // fine, but expected compiler error
var ms mySlice
var s []int
s = ms // same with slices
var mc myChan
var c chan int
c = mc // or channels
var mstr myString
var str string
// str = mstr // error, as expected
fmt.Printf("%T %T %T %T %T %T %T %T\n", mm, m, ms, s, mc, c, mstr, str)
}
Playground
Why don't I get a type mismatch error with those special "reference types" map, slice and chan?
You get no compile-time error in the first 2 cases because those assignments are allowed by the language spec.
In assignments, each value must be assignable to the type of the operand to which it is assigned...
A value
x
is assignable to a variable of typeT
("x
is assignable toT
") if one of the following conditions applies:
x
's type is identical toT
.x
's typeV
andT
have identical underlying types and at least one ofV
orT
is not a defined type.T
is an interface type andx
implementsT
.x
is a bidirectional channel value,T
is a channel type,x
's typeV
andT
have identical element types, and at least one ofV
orT
is not a defined type.x
is the predeclared identifiernil
andT
is a pointer, function, slice, map, channel, or interface type.x
is an untyped constant representable by a value of typeT
.
The emphasized rule applies to your first 2 cases. It however does not apply to your last case, because both string
and myString
are defined types. None of the rules apply in your last case.