Type identities of compound types

May 29, 2023

So we now know that types are either identical or different. let’s look at the details, with examples.

Type identity

… In detail:

  • Two array types are identical if they have identical element types and the same array length.

So given:

type (
	X = [10]int
	Y = X
	Z [10]int
)

Types X, Y, and [10]int are identical to each other, but not to [9]int or [10]int32. Type Z is also different from all the others, due to the fact that it is a named type.

Note that X and Y are not actually named types; the equal sign (=) indicates that they are aliases to the unnamed type [10]int.

  • Two slice types are identical if they have identical element types.

Given:

type(
	A0 = []string
	A1 = A0
	AZ []string
)

Types A0, A1 and []string are identical to each other, but not to []int or AZ.

  • Two struct types are identical if they have the same sequence of fields, and if corresponding fields have the same names, and identical types, and identical tags. Non-exported field names from different packages are always different.

Therefore:

  • struct{ Name string, Age int } is different from struct{ Age int, Name string } because the sequence of fields differs.
  • struct{ Name string, Age int } is different from struct{ Fullname string, Age int } because field names differ.
  • struct{ Name string, Age int } is different from struct{ Name string, Age uint } because field types differ.
  • struct{ Name string `json:"name"`, Age int } is different from struct{ Name string, Age int } because struct tags differ.
  • struct{ name string } defined in package foo is different from struct{ name string } defined in package bar.

And jumping out of order a bit…

  • Two map types are identical if they have identical key and element types.

Given:

type (
	M1 = map[string]any
	M2 = map[string]string
)

M1 and M2 are different. The empty interface is a distinct type, and does not act as a wildcard in compound types such as maps.

Quotes from The Go Programming Language Specification Version of December 15, 2022

Share this

Related Content

Composite keys

This week’s episode of the Cup o’ Go podcast is out! Keep up with the Go community in just 15 minutes per week! Have a listen! Composite literals … The key is interpreted as a field name for struct literals, an index for array and slice literals, and a key for map literals. For map literals, all elements must have a key. If you’ve written any Go code, you probably already know about keys in maps:

Assignability of composite components

Composite literals … The types of the elements and keys must be [assignable(https://go.dev/ref/spec#Assignability)] to the respective field, element, and key types of type T; there is no additional conversion. This shouldn’t be surprising, but let’s examine the implications just the same. type myStr string s := myStr("my string") var x = map[int]string{ 3: "oink", // Valid, untyped numeric constant 3 is assignable to an int. int(4): "quack", // Valid, int(4) is of type int int64(12): "moo", // Invalid, int64(12) is not converted to int 8: s, // Invalid, type myStr is type string 9: string(s), // Valid; explicit conversion to type string } Quotes from The Go Programming Language Specification Version of August 2, 2023

Composite literals

Earlier this year, near the beginning of this series on the Go spec, we went through literal representations of all of the basic types in Go: ints, strings, etc. If this were an Intro to Go style book, the very next section would have been on composite literals. But it’s not. So we had to wait nearly 6 months to get to that topic… But here we are, at long last!