Go is statically typed programming language. The set of values allowed to store in variable is determined by the variable’s type. Because of that arbitrary data can’t be just assigned as in dynamically typed language like Python. The rule which is used to govern what is permitted is called assignability.

Having variable left of type T, there are 6 cases when value right can be assigned to left.

1. Identical types

First one is obvious. If right’s type is identical to T then assignment is completely valid. More on this in “Identical types in Go”.

2. Identical underlying types

Each type in Go has an underlying type. For boolean, numeric, string or type literal underlying type is the same as type. Otherwise underlying type is the one from type declaration:

type X map[string]int var x X // underlying type is map[string]int

2nd case of assignability is about having identical underlying type:

type X map[string]int var x X

var y map[string]int

x = y

Having two named types won’t work though:

type X map[string]int

type Y map[string]int var x X

var y Y

x = y // cannot use y (type Y) as type X in assignment

It’s additionally required that at least one type is not a named type…

Types in Go can be either named or unnamed. Unnamed types are the ones specified using a type literal:

var a [10]string

var b struct{ field string}

var c map[string]int

3. Assigning to interface type T value implementing T

If variable implements interface T then we can assign it to variable of interface type T.

type Callable interface {

f() int

} type T int func (t T) f() int {

return int(t)

} var c Callable

var t T

c = t

More on interface types in language spec.

4. Assigning bidirectional channel to variable with identical element types

type T chan<- map[string]int var c1 T

var c2 chan map[string]int

c1 = c2

c2 = c1 // cannot use c1 (type T) as type chan map[string]int in assignment

As with with 2nd case (identical underlying types) at least one channel type must be unnamed type:

type T chan<- map[string]int

type T2 chan map[string]int var c1 T

var c2 T2

c1 = c2 // cannot use c2 (type T2) as type T in assignment

5. Assigning nil

It’s allowed to assign nil to variable which is a pointer, function, slice, map, channel or interface type.

var a *int

var b func(int) int

var c []int

var d map[string]int

var e chan int

var f interface{} a, b, c, d, e, f = nil, nil, nil, nil, nil, nil var g [10]int

g = nil // cannot use nil as type [10]int in assignment

6. Untyped constants

Great in-depth introduction to Go constants can be found on official blog.

Untyped constant can be set to variable of type T if constant is representable by value of type T.

var a float32

var b float64

var c int32

var d int64 const untyped = 1

a = untyped

b = untyped

c = untyped

d = untyped

Resources