Everything I have learnt about Type Assertions in Go is Misleading

Aragorn Yang
2 min readFeb 3, 2021

Note: Go is new to me, so please correct me if I’m wrong.

This article is only about the return value of a type assertion rather than when the assertion holds.

I hadn’t started learning Go until 10 days ago. Since then I have followed through some great tutorials. All of them say the same thing about type assertions x.(T) that when the assertion holds it returns the underlying value. I tried some codes out, and something went wrong.

package main

import (
"fmt"
)

type Kid struct {
name string
}


type Child struct {
name string
}

func (t Kid) getName() string {
return t.name
}


func (c Child) getName() string {
return c.name
}

type Person interface{}

func main() {
var myKid interface{} = Kid{"John Doe"}
fmt.Printf("[%v %T]\n", myKid, myKid)
fmt.Printf("[%v %T]\n", myKid.(Kid), myKid.(Kid))
fmt.Printf("[%v %T]\n", myKid.(Person), myKid.(Person))
fmt.Println(myKid.(Kid).getName())
fmt.Println(myKid.(Child).getName())
//fmt.Println(myKid.(Person).getName())
}

go run:

$ go run demo.go
[{John Doe} main.Kid]
[{John Doe} main.Kid]
[{John Doe} main.Kid]
John Doe

Uncomment the last line in main(), go run:

$ go run demo.go
# command-line-arguments
./demo.go:23:28: myKid.(Person).getName undefined (type Person is interface with no methods)

From the first run, we could see that the underlying value of myKid.(Person) is of type Kid. Yet the second run told us that getName method is undefined for myKid.(Person).

I have reconstructed my understanding on types and type assertions as following.

Types in Go have two distinct categories: data types and interface types. Any non-interface type is a data type. A data type defines the data structure. A interface type defines which methods can be accessed.

A data value has two parts: the underlying value and its data type.

An interface value has two parts: the underlying data value and the interface type. Interface type, or access type, limits what methods we have access to. The underlying data value still have all its methods, but those that are not defined in the interface type are hidden under the surface/interface.

What a type assertion x.(T) returns when x is of type T, depends on which type category the type T belongs to. When T is a data type, x.(T) returns the underlying data value. When T is an interface type, x.(T) returns an interface value which has the same underlying data value as x but has T as its interface type.

I see no conflicts between these explanations and [the Go Spec on type assertions](https://golang.org/ref/spec#Type_assertions).

--

--