A type determines a set of values and the operations and methods on them (spec: Types). A type is written as a type name, if it has one, or built with a type literal from other types.
Type = TypeName [ TypeArgs ] | TypeLit | "(" Type ")" .
TypeName = identifier | QualifiedIdent .
TypeArgs = "[" TypeList [ "," ] "]" .
TypeList = Type { "," Type } .
TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
SliceType | MapType | ChannelType .
Predeclared types, defined types and type parameters are named types. An alias denotes a named type if the type given in the alias declaration is a named type. Composite types (array, struct, pointer, function, interface, slice, map and channel) are made with type literals.
The kinds of type
| Kind | Type literal or names | Zero value | Comparable |
|---|---|---|---|
| Boolean | bool | false | Yes |
| Numeric | int, uint8, float64, complex128… | 0 | Yes, and ordered (not complex) |
| String | string | "" | Yes, and ordered |
| Array | [n]T | All elements zero | If T is |
| Slice | []T | nil | Only to nil |
| Struct | struct{ … } | All fields zero | If all fields are |
| Pointer | *T | nil | Yes |
| Function | func(…) … | nil | Only to nil |
| Interface | interface{ … } | nil | Yes (may panic) |
| Map | map[K]V | nil | Only to nil |
| Channel | chan T, chan<- T, <-chan T | nil | Yes |
Boolean types
A boolean type holds the values denoted by the predeclared constants true
and false. The predeclared boolean type is bool, a defined
type.
Numeric types
| Type | Values |
|---|---|
uint8 | Unsigned 8-bit integers: 0 to 255 |
uint16 | Unsigned 16-bit integers: 0 to 65535 |
uint32 | Unsigned 32-bit integers: 0 to 4294967295 |
uint64 | Unsigned 64-bit integers: 0 to 18446744073709551615 |
int8 | Signed 8-bit integers: −128 to 127 |
int16 | Signed 16-bit integers: −32768 to 32767 |
int32 | Signed 32-bit integers: −2147483648 to 2147483647 |
int64 | Signed 64-bit integers: −9223372036854775808 to 9223372036854775807 |
float32 | IEEE 754 32-bit floating-point numbers |
float64 | IEEE 754 64-bit floating-point numbers |
complex64 | Complex numbers with float32 real and imaginary parts |
complex128 | Complex numbers with float64 real and imaginary parts |
byte | Alias for uint8 |
rune | Alias for int32 |
uint | Either 32 or 64 bits |
int | Same size as uint |
uintptr | An unsigned integer large enough to store the uninterpreted bits of a pointer value |
Integers use two’s complement. Numeric types are all distinct defined types except the
aliases byte and rune, so a mix of types needs an explicit
conversion, even between int32 and an int of the same width.
There are no implicit numeric conversions. Sizes of the sized types are guaranteed; the
size of int depends on the target, 64 bits on current 64-bit systems.
String types
A string is a possibly empty sequence of bytes, and is immutable: nothing can change
its contents once made. The predeclared string type is string. The length is
given by len(s) and is the number of bytes, a constant if the string is
constant. Indexing gives bytes, and &s[i] is invalid. Strings are not
required to be valid UTF-8; see String
literals and Conversions.
Array types
ArrayType = "[" ArrayLength "]" ElementType .
ArrayLength = Expression .
ElementType = Type .
An array is a numbered sequence of elements of one type. The length is part of the type
and must be a non-negative constant representable by an int. Arrays are
values, so assigning one or passing it as an argument copies all its elements. Arrays are
one-dimensional but compose: [3][5]int.
An array type T may not contain an element of type T, or of a
type containing T, directly or indirectly, if the containing types are only
arrays or structs: type T1 [10]T1 and type T2 [10]struct{ f T2 }
are invalid, but type T5 [10]*T5 is valid.
Slice types
SliceType = "[" "]" ElementType .
A slice is a descriptor for a contiguous part of an underlying array. It holds a reference to the array, a length and a capacity. The capacity is the length of the slice plus whatever remains of the array beyond it. Several slices may share one array, so writing an element through one changes it for all.
make([]T, length, capacity)allocates a new hidden array and returns a slice of it. It produces the same slice as allocating an array and slicing it, somake([]int, 50, 100)andnew([100]int)[0:50]are equivalent.appendreuses the array if there is capacity; otherwise it allocates a larger one and copies.- The zero value is
nil. A nil slice has length and capacity 0, andappendaccepts it. It is not the same as an initialised empty slice.
Struct types
StructType = "struct" "{" { FieldDecl ";" } "}" .
FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] .
EmbeddedField = [ "*" ] TypeName [ TypeArgs ] .
Tag = string_lit .
struct {
x, y int
u float32
_ float32 // padding
Name string `json:"name"`
*Node // embedded field named Node
sync.Mutex // embedded field named Mutex
}
- Non-blank field names must be unique within the struct.
- A field with a type but no name is embedded. It must be a type name
Tor a pointer to a non-interface type name*T, andTmay not be a pointer type or a type parameter. The unqualified type name acts as the field name. - A field or method
fof an embedded field is promoted ifx.fis a legal selector for it. Promoted fields act like ordinary fields. In a composite literal they can be named as keys since Go 1.27; before that they could not. - A field declaration may have a string tag, visible through reflection. Tags take part in type identity but are ignored for struct conversions (since Go 1.8). An empty tag is the same as no tag.
- A struct may not contain itself directly or through arrays and structs, by the same rule as for arrays. Through a pointer, function or slice it may.
Pointer types
PointerType = "*" BaseType .
BaseType = Type .
A pointer type denotes the set of all pointers to variables of a given type, its
base type. The zero value is nil. There is no pointer arithmetic;
the unsafe package provides
restricted facilities. *p dereferences; &x takes an address
(see Address operators).
Function types
FunctionType = "func" Signature .
Signature = Parameters [ Result ] .
Result = Parameters | Type .
Parameters = "(" [ ParameterList [ "," ] ] ")" .
ParameterList = ParameterDecl { "," ParameterDecl } .
ParameterDecl = [ IdentifierList ] [ "..." ] Type .
A function type denotes all functions with the same parameter and result types. Within
one list the names must be all present or all absent. If there is exactly one unnamed
result it may be written without parentheses. The final parameter may have a type prefixed
with ..., making the function variadic (see
Functions and methods).
Interface types
An interface type defines a type set. A variable of interface type can store a value of any type in that set, and holds a dynamic type and a dynamic value at run time. Interfaces, embedding and type elements are on the Interfaces page.
Map types
MapType = "map" "[" KeyType "]" ElementType .
KeyType = Type .
A map is an unordered collection of elements of one type, indexed by unique keys of
another type. Key values must be comparable: == and != must be
fully defined for the key type, so it cannot be a function, map or slice. A key that is an
interface may panic at run time if its dynamic type cannot be compared.
The zero value is nil. A nil map has no entries and is safe to read, but
assigning to one panics. Maps are made with
make or a
composite literal. Map
elements are not addressable.
Channel types
ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
| Type | Allows |
|---|---|
chan T | Sending and receiving |
chan<- T | Sending only |
<-chan T | Receiving only |
The <- binds to the leftmost chan possible, so
chan<- chan int is chan<- (chan int), and
chan<- <-chan int is chan<- (<-chan int). A channel
is unbuffered or buffered, as given to make. See
Concurrency.
Representation of values
Values of predeclared types, arrays and structs are self-contained: each value holds a complete copy of its data. Pointer, function, slice, map and channel values hold references to underlying data, which may be shared. An interface value may be self-contained or contain references, depending on its dynamic type (spec: Representation of values). When values share data, changing one may change another.
Assignment and argument passing copy the value only. For a reference type that means the reference is copied and the referenced data is not. See Assignment statements.
Underlying types
Each type has an underlying type. If T is a predeclared boolean,
numeric or string type, or a type literal, its underlying type is T itself.
Otherwise it is the underlying type of the type T refers to in its
declaration. For a type parameter it is the underlying type of its constraint, which is
always an interface.
type (
A1 = string
A2 = A1
)
type (
B1 string
B2 B1
B3 []B1
B4 B3
)
// The underlying type of string, A1, A2, B1 and B2 is string.
// The underlying type of []B1, B3 and B4 is []B1.
Method sets
The method set of a type is the set of methods that can be called on a value of that type (spec: Method sets).
| Type | Method set |
|---|---|
A defined type T | Methods declared with receiver T |
*T, where T is neither a pointer nor an interface | Methods declared with receiver *T or T |
| An interface type | The intersection of the method sets of the types in its type set; usually just its declared methods |
A struct with embedded field T | S and *S include promoted methods with receiver T. *S also includes promoted methods with receiver *T |
A struct with embedded field *T | S and *S include promoted methods with receiver T or *T |
| Any other type | Empty |
A type defined from another (type N T) does not inherit its methods, but the
method set of an interface type, or of a composite type’s elements, is unchanged. See
Type definitions.
Type identity
Two types are either identical or different. A named type is always different from any other type. Otherwise two types are identical if their underlying type literals are structurally equivalent (spec: Type identity):
- Arrays: identical element types and the same length.
- Slices: identical element types.
- Structs: the same sequence of fields, with the same names, identical types, identical tags, and matching embedded status. Non-exported field names from different packages are always different.
- Pointers: identical base types.
- Functions: the same number of parameters and results, identical corresponding types, and either both variadic or neither. Parameter and result names need not match.
- Interfaces: the same type set.
- Maps: identical key and element types.
- Channels: identical element types and the same direction.
- Instantiated types: identical defined types and all type arguments identical.
An alias and the type it denotes are the same type. type T []int and
[]int are different, since T is a new defined type.
Assignability
A value x of type V is assignable to a variable of type
T if one of these holds (spec: Assignability):
VandTare identical.VandThave identical underlying types but are not type parameters, and at least one is not a named type.VandTare channel types with identical element types,Vis bidirectional, and at least one is not a named type.Tis an interface type, not a type parameter, andximplementsT.xisnilandTis a pointer, function, slice, map, channel or interface type, not a type parameter.xis an untyped constant representable by a value ofT.
Type parameters add three more rules. nil, or a value of a type that is not
named, is assignable to a type parameter if it is assignable to each type in its type set.
A value of a type parameter is assignable to a type that is not named if values of each
type in its type set are.
Representability
A constant x is representable by a value of type T
(not a type parameter) if x is in the set of values of T; or
T is a floating-point type and x can be rounded to T’s
precision without overflow (rounding uses IEEE 754 round-to-even, with negative zero
simplified to zero); or T is complex and x’s real and imaginary
parts are representable. If T is a type parameter, x must be
representable by every type in its type set.
'a' // representable by byte: 97 is in the set of byte values
1024 // not representable by byte
1.1 // not representable by int
1e10 // representable by uint64
42.0 // representable by byte: it is the integer 42
-1 // not representable by uint16
1e1000 // not representable by float64: overflows to +Inf after rounding
Zero values
Storage allocated without an explicit initial value is set to the zero value for
its type, recursively: false for booleans, 0 for numeric types,
"" for strings, and nil for pointers, functions, interfaces,
slices, channels and maps. Every variable therefore always has a defined value (spec: The
zero value). var i int is the same as var i int = 0.
Conversions
Conversion = Type "(" Expression [ "," ] ")" .
T(x) converts x to type T. A type that starts with
* or <-, or with func and no result list, must be
parenthesised to avoid ambiguity: (*Point)(p), (<-chan int)(c),
(func())(x).
A constant can be converted to T if it is representable by T; the
result is a typed constant, unless T is a type parameter. A non-constant value
can be converted when one of these holds:
xis assignable toT.- Ignoring struct tags,
x’s type andThave identical underlying types and are not type parameters. - Ignoring struct tags, both are unnamed pointer types whose base types are not type parameters and have identical underlying types.
- Both are integer or floating-point types.
- Both are complex types.
xis an integer, or a slice of bytes or runes, andTis a string type.xis a string andTis a slice of bytes or runes.xis a slice andTis an array (Go 1.20) or a pointer to an array (Go 1.17), with identical element types.
With type parameters, a conversion is valid if it is valid for every type in the type set
or sets concerned. There is no language mechanism to convert between pointers and integers;
the unsafe package does this
under restricted circumstances.
Conversions between numeric types
| Conversion | Effect |
|---|---|
| Integer to integer | Sign-extended if signed, zero-extended otherwise, then truncated to the result’s size. Always a valid value, with no indication of overflow. uint32(int8(v)) with v := uint16(0x10F0) is 0xFFFFFFF0 |
| Floating-point to integer | The fraction is discarded, truncating towards zero |
| Integer or floating-point to floating-point, complex to complex | Rounded to the destination’s precision |
If a non-constant conversion involving floating-point or complex values cannot represent the value, the conversion still succeeds but the result is implementation-dependent.
Conversions to and from strings
| From | To | Result |
|---|---|---|
| Slice of bytes | String | The bytes, in order |
| Slice of runes | String | The concatenation of each rune as a string |
| String | Slice of bytes | A non-nil slice of its bytes |
| String | Slice of runes | The code points of the string |
| Integer | String | The UTF-8 of that code point. Out-of-range values give "�". Historical; go vet flags many cases and the specification says this form may eventually be removed |
Conversions to and from strings, and between numeric types, may change the representation and cost time at run time. All other conversions change only the type.
Conversions from slice to array or array pointer
Converting a slice to an array copies its elements; converting a slice to an array pointer gives a pointer to the slice’s underlying array. Either panics if the slice is shorter than the array.
s := make([]byte, 2, 4)
a2 := [2]byte(s) // a2[0] == s[0]
s2 := (*[2]byte)(s) // &s2[0] == &s[0]
a4 := [4]byte(s) // panics: len([4]byte) > len(s)
var t []string
t0 := [0]string(t) // ok for nil slice t
t1 := (*[0]string)(t) // t1 == nil