Types


Types in Go are divided into 2 categories: named and unnamed. Besides predeclared types (such as int, rune, etc), you can also define named type yourself. E.g.:

  1. type mySlice []int

Unnamed types are defined by type literal. I.e., []int is an unnamed type.

According to Go spec, there is an underlying type of every type:

Each type T has an underlying type: If T is one of the predeclared boolean, numeric, or string types, or a type literal, the corresponding underlying type is T itself. Otherwise, T’s underlying type is the underlying type of the type to which T refers in its type declaration.

So, in above example, both named type mySlice and unnamed type []int have the same underlying type: []int.

Go has strict rules of assigning values of variables. For example:

  1. package main
  2. import "fmt"
  3. type mySlice1 []int
  4. type mySlice2 []int
  5. func main() {
  6. var s1 mySlice1
  7. var s2 mySlice2 = s1
  8. fmt.Println(s1, s2)
  9. }

The compilation will complain the following error:

  1. cannot use s1 (type mySlice1) as type mySlice2 in assignment

Although the underlying type of s1 and s2 are same: []int, but they belong to 2 different named types (mySlice1 and mySlice2), so they can’t assign values each other. But if you modify s2‘s type to []int, the compilation will be OK:

  1. package main
  2. import "fmt"
  3. type mySlice1 []int
  4. func main() {
  5. var s1 mySlice1
  6. var s2 []int = s1
  7. fmt.Println(s1, s2)
  8. }

The magic behind it is one rule of assignability:

x’s type V and T have identical underlying types and at least one of V or T is not a named type.

References:
Go spec;
Learning Go - Types;
Golang pop quiz.