An expression computes a value by applying operators and functions to operands (spec: Expressions).
Expression = UnaryExpr | Expression binary_op Expression .
UnaryExpr = PrimaryExpr | unary_op UnaryExpr .
binary_op = "||" | "&&" | rel_op | add_op | mul_op .
rel_op = "==" | "!=" | "<" | "<=" | ">" | ">=" .
add_op = "+" | "-" | "|" | "^" .
mul_op = "*" | "/" | "%" | "<<" | ">>" | "&" | "&^" .
unary_op = "+" | "-" | "!" | "^" | "*" | "&" | "<-" .
PrimaryExpr = Operand |
Conversion |
MethodExpr |
PrimaryExpr Selector |
PrimaryExpr Index |
PrimaryExpr Slice |
PrimaryExpr TypeAssertion |
PrimaryExpr Arguments .
Selector = "." identifier .
Index = "[" Expression [ "," ] "]" .
Slice = "[" [ Expression ] ":" [ Expression ] "]" |
"[" [ Expression ] ":" Expression ":" Expression "]" .
TypeAssertion = "." "(" Type ")" .
Arguments = "(" [ ( ExpressionList | Type [ "," ExpressionList ] ) [ "..." ] [ "," ] ] ")" .
Operands
Operand = Literal | OperandName [ TypeArgs ] | "(" Expression ")" .
Literal = BasicLit | CompositeLit | FunctionLit .
BasicLit = int_lit | float_lit | imaginary_lit | rune_lit | string_lit .
OperandName = identifier | QualifiedIdent .
QualifiedIdent = PackageName "." identifier .
An operand is a literal, a non-blank identifier denoting a constant, variable or function
(possibly qualified with a package name), or a parenthesised expression. A generic function
name may be followed by type arguments. The blank identifier may appear as an operand only
on the left of an assignment. A qualified identifier such as math.Sin reaches
an exported name in an imported package.
Composite literals
CompositeLit = LiteralType LiteralValue .
LiteralType = StructType | ArrayType | "[" "..." "]" ElementType |
SliceType | MapType | TypeName [ TypeArgs ] .
LiteralValue = "{" [ ElementList [ "," ] ] "}" .
ElementList = KeyedElement { "," KeyedElement } .
KeyedElement = [ Key ":" ] Element .
Key = FieldName | Expression | LiteralValue .
FieldName = identifier .
Element = Expression | LiteralValue .
A composite literal constructs a new struct, array, slice or map value each time it is evaluated. Its type must have one of those as its underlying type; for a type parameter, every type in the type set must have the same valid underlying type. Elements must be assignable to the field, element or key types, with no extra conversion. It is an error to give two elements the same field name or constant key. An empty literal is the zero value of its type.
| Type | Keys | Rules |
|---|---|---|
| Struct, no keys | None | One element for every field, in declaration order |
| Struct, with keys | Field selectors | Every element has a key. Omitted fields get zero values. See below |
| Array or slice | Optional integer index | Key is a non-negative constant representable by int; if typed, an integer type. A keyless element follows the previous index; the first is 0 |
| Map | Required | Every element has a key |
In a struct literal with keys, each key must be a valid field selector for a possibly promoted field of the struct (Go 1.27; earlier versions required a top-level field name). Embedded fields passed through on the way to a key must not be pointer types. A key must not name a promoted field inside an embedded struct if that struct is also given by another key. Specifying a non-exported field of a struct from another package is an error.
type Object struct{ name, color string }
type Point3D struct {
Object
x, y, z float64
}
type Line struct {
Object
p, q Point3D
}
origin := Point3D{} // zero value for Point3D
line1 := Line{Object{}, origin, Point3D{y: -4, z: 12.3}} // zero value for line1.q.x
line2 := Line{name: "diagonal", q: Point3D{1, 1, 1}} // Go 1.27: name is promoted from Object
obj := Object{"edge", "black"}
line3 := Line{Object: obj, name: "diagonal"} // invalid: name is inside Object
buffer := [10]string{} // len(buffer) == 10
intSet := [6]int{1, 2, 3, 5} // len(intSet) == 6
days := [...]string{"Sat", "Sun"} // len(days) == 2
vowels := [128]bool{'a': true, 'e': true, 'i': true, 'o': true, 'u': true, 'y': true}
filter := [10]float32{-1, 4: -0.1, -0.1, 9: -1}
m := map[string]int{"one": 1, "two": 2}
... sets the array length from the largest indexA slice literal describes a whole underlying array: its length and capacity are the
largest index plus one. Taking the address of a composite literal, &T{…},
generates a pointer to a new variable holding the value. new([]int) gives a
pointer to a nil slice, but &[]int{} a pointer to an empty, non-nil one.
Inside array, slice and map literals, elements and map keys that are composite literals
may elide their type if it is identical to the element or key type (spec: Elision of
element types); similarly &T may be elided when the element type is
*T.
[][]int{{1, 2, 3}, {4, 5}} // same as [][]int{[]int{1, 2, 3}, []int{4, 5}}
[]*Point{{1.5, -3.5}, {}} // same as []*Point{&Point{1.5, -3.5}, &Point{}}
map[Point]string{{0, 0}: "orig"} // same as map[Point]string{Point{0, 0}: "orig"}
A composite literal using a type name as an operand of an if, for
or switch header, outside parentheses, brackets or braces, would be read as the
start of the statement’s block. It must be parenthesised:
if x == (T{a, b}) { … }.
Function literals
FunctionLit = "func" Signature FunctionBody .
A function literal is an anonymous function; it cannot declare type parameters. It may be assigned to a variable or called directly. Function literals are closures: they may refer to variables of the surrounding function, which are then shared with the literal and survive as long as they are accessible. See Functions and methods.
Selectors
For an expression x that is not a package name, x.f denotes the
field or method f of x (or sometimes of *x). The
selector f must not be blank. A selector may reach through embedded fields; the
number of embedded fields traversed is its depth (spec: Selectors).
- For a value of type
Tor*T, whereTis not a pointer or interface type,x.fdenotes the field or method at the shallowest depth where one exists. If there is not exactly one at that depth, the selector is illegal. - For a value of interface type
I,x.fdenotes the actual method of the dynamic value;fmust be in the method set ofI. - If
xhas a defined pointer type and(*x).fis a valid selector of a field (not a method),x.fis shorthand for(*x).f. - In all other cases
x.fis illegal. - If
xis a nil pointer andx.fdenotes a struct field, evaluating or assigning to it panics. - If
xis a nil interface, calling or evaluating the methodx.fpanics.
Selectors also underlie method values and method expressions.
Index expressions
a[x] indexes an array, pointer to array, slice, string or map (spec: Index
expressions). Outside maps, the index must be an untyped constant or of integer type, and a
constant index must be non-negative and representable by int.
| Operand | Result | Out of range |
|---|---|---|
| Array | The element; a constant index must be in range | Panic at run time |
| Pointer to array | Shorthand for (*a)[x] | Panic |
| Slice | The element | Panic |
| String | The non-constant byte at that index; may not be assigned to | Panic |
| Map | The element for that key, or the zero value if missing or the map is nil. x must be assignable to the key type | Not applicable |
A map index used in a two-value assignment, v, ok := a[x], also yields an
untyped boolean saying whether the key is present. Assigning to an element of a nil map
panics. For a type parameter operand the operation must be valid for every type in its type
set, and their element types must be identical (see
Generics).
Slice expressions
Slice expressions build a substring or slice from a string, array, pointer to array or slice. The result shares its underlying data with the operand.
| Form | Length | Capacity | Operands |
|---|---|---|---|
a[low : high] | high - low | The rest of the array | String, array, pointer to array, slice |
a[low : high : max] | high - low | max - low | Array, pointer to array, slice (not a string) |
- In the simple form, a missing
lowdefaults to 0 and a missinghightolen(a). In the full form onlylowmay be omitted. - For arrays and strings the indices must satisfy
0 <= low <= high <= len(a); for slices the upper bound iscap(a). For the full form,0 <= low <= high <= max <= cap(a). Out-of-range indices panic at run time; constant indices that break these are compile errors. - An array operand must be addressable. Slicing a nil slice gives a nil slice.
a := [5]int{1, 2, 3, 4, 5}
s := a[1:4] // len 3, cap 4, elements 2, 3, 4
t := a[1:3:5] // len 2, cap 4, elements 2, 3
a2 := a[2:] // same as a[2 : len(a)]
a3 := a[:3] // same as a[0 : 3]
a4 := a[:] // same as a[0 : len(a)]
Type assertions
For an expression x of interface type (but not a type parameter),
x.(T) asserts that x is not nil and that its stored value has type
T (spec: Type assertions).
- If
Tis not an interface type, the dynamic type ofxmust be identical toT, andTmust implement the type ofx, or the assertion is invalid. - If
Tis an interface type, the dynamic type ofxmust implementT. - If the assertion is false, a run-time panic occurs.
Used in a two-value assignment or initialisation, v, ok := x.(T) yields an
additional untyped boolean and does not panic; on failure v is the zero value of
T. See also type
switches.
var x any = 7 // x has dynamic type int and value 7
i := x.(int) // i has type int and value 7
n, ok := x.(string) // n == "", ok == false; no panic
r, ok := x.(io.Reader) // ok reports whether the dynamic type implements io.Reader
Calls
f(a1, a2, … an) calls f. Arguments must be single-valued
expressions assignable to the parameter types and are evaluated before the call. They are
then passed, which means assigned to the corresponding parameters (spec: Calls).
- A call of a nil function value panics.
- If
fis generic, it must be instantiated before it can be called. - A method call
x.m()needsmin the method set of the type ofx. Ifxis addressable and&x’s method set hasm,x.m()is shorthand for(&x).m(). - As a special case, the multi-value result of a call can be passed straight to another
function if it is the only argument and the values fit the parameters:
f(g()). A final...parameter takes what remains. - See variadic functions for
calls with
....
Operators and precedence
Unary operators have the highest precedence. There are five precedence levels for binary
operators, and binary operators of the same precedence associate from left to right. The
statements x++ and x-- are outside this hierarchy, so
*p++ is (*p)++ (spec: Operator precedence).
| Precedence | Operators | Associativity |
|---|---|---|
| Unary (highest) | + - ! ^ * & <- | Right to left |
| 5 | * / % << >> & &^ | Left to right |
| 4 | + - | ^ | Left to right |
| 3 | == != < <= > >= | Left to right |
| 2 | && | Left to right |
| 1 | || | Left to right |
x / y * z // (x / y) * z
42 + a - b // (42 + a) - b
23 + 3*x[i] // 23 + (3 * x[i])
^a >> b // (^a) >> b
x == y+1 && <-chanInt > 0 // (x == (y+1)) && ((<-chanInt) > 0)
For binary operators other than comparisons, the operand types must be identical, unless the operation involves shifts or untyped constants. If one operand is an untyped constant and the other is not, the constant is converted to the other operand’s type, except in shifts.
Arithmetic operators
| Operator | Name | Operands |
|---|---|---|
+ | Sum, concatenation | Integers, floats, complex values, strings |
- | Difference | Integers, floats, complex values |
* | Product | Integers, floats, complex values |
/ | Quotient | Integers, floats, complex values |
% | Remainder | Integers |
& | Bitwise AND | Integers |
| | Bitwise OR | Integers |
^ | Bitwise XOR; unary: complement | Integers |
&^ | Bit clear (AND NOT) | Integers |
<< | Left shift | integer << non-negative integer |
>> | Right shift | integer >> non-negative integer |
- Integer division truncates towards zero.
-5 / 3is-1and-5 % 3is-2. For a negative dividend the remainder is negative or zero. If the dividend is the most negative value of its type,x / -1isxand the remainder is 0. - A constant divisor must not be zero. A zero divisor at run time panics.
- Shifts are arithmetic for signed left operands and logical for unsigned
ones. There is no upper limit on the count. The right operand must be of integer type
(a signed type since Go 1.13) or an untyped constant representable by
uint. A negative count at run time panics. If the left operand of a non-constant shift is an untyped constant, it takes the type it would have if the shift were replaced by the left operand alone. - Unary
-xis0 - x;^xism ^ x, withmall ones for unsignedxand-1for signed. - Overflow. Unsigned
+,-,*and<<are computed modulo 2n. Signed+,-,*,/and<<may overflow legally: the result is defined by two’s complement and no panic occurs. A compiler may not assume overflow never happens. - Floating-point. The result of division by zero is not specified beyond IEEE 754, and whether a panic occurs is implementation-specific. An implementation may combine several floating-point operations into one fused operation, possibly across statements (Go 1.9). An explicit conversion to a floating-point type rounds to that precision and prevents fusion across it.
- Strings.
+and+=create a new string by concatenation.
Comparison operators
Comparison yields an untyped boolean. In any comparison the first operand must be assignable to the type of the second, or the other way round. Equality operators need comparable operands; ordering operators need ordered ones (spec: Comparison operators).
| Type | Comparable | Ordered | Two values are equal if |
|---|---|---|---|
| Boolean | Yes | No | Both true or both false |
| Integer | Yes | Yes | The usual way |
| Floating-point | Yes | Yes | As defined by IEEE 754; NaN is not equal to itself |
| Complex | Yes | No | Real and imaginary parts are both equal |
| String | Yes | Yes | Lexically byte-wise |
| Pointer | Yes | No | They point to the same variable, or are both nil. Pointers to distinct zero-size variables may or may not be equal |
| Channel | Yes | No | Made by the same call to make, or both nil |
| Interface | Yes, unless a type parameter | No | Identical dynamic types and equal dynamic values, or both nil |
| Struct | If all fields are | No | Non-blank fields are equal, compared in source order, stopping at the first difference |
| Array | If elements are | No | Elements are equal, compared in ascending index order, stopping at the first difference |
| Slice, map, function | Only to nil | No | Not comparable except to nil |
- A value of non-interface type
Xcan be compared with a value of interface typeTifXis comparable and implementsT. - Comparing two interface values with identical dynamic types panics if that type is not comparable. This also applies inside arrays of interfaces and structs with interface fields.
- A type is strictly comparable if it is comparable and is not an interface or composed of interfaces. Comparing strictly comparable values cannot panic. See comparable.
Logical operators
&&, || and ! apply to booleans and yield
a result of the operands’ type. The left operand is evaluated, then the right only if
needed: p && q is “if p then q else false”.
Address operators
&x gives a pointer to x, which must be addressable:
a variable, a pointer indirection, a slice index, a field selector of an addressable struct,
or an index of an addressable array. A composite literal is also allowed, as an exception.
*x denotes the variable x points to, and panics if x
is nil. Map elements and most function results are not addressable.
Receive operator
<-ch receives a value from a channel and blocks until one is available. A
two-value form, x, ok := <-ch, reports whether the value came from a send.
Details are on the Concurrency page.
Constant expressions
Constant expressions have only constant operands and are evaluated at compile time, exactly (spec: Constant expressions).
- A constant comparison gives an untyped boolean constant. A constant shift with an untyped left operand gives an integer constant.
- Any other operation on untyped constants gives an untyped constant of the same kind. If the operands are of different kinds, the result takes the kind appearing later in the list: integer, rune, floating-point, complex.
- Values of typed constants must be representable by their type:
uint(-1)andint(3.14)are errors, and so isFour * 300ifFouris anint8. - The divisor of a constant division or remainder must not be zero.
lenandcapmay be constant; see Built-ins.
const a = 2 + 3.0 // a == 5.0 (untyped floating-point constant)
const b = 15 / 4 // b == 3 (untyped integer constant)
const c = 15 / 4.0 // c == 3.75 (untyped floating-point constant)
const Θ float64 = 3/2 // Θ == 1.0 (type float64, 3/2 is integer division)
const d = 1 << 3.0 // d == 8 (untyped integer constant)
const e = 1.0 << 3 // e == 8 (untyped integer constant)
const h = "foo" > "bar" // h == true (untyped boolean constant)
const k = 'w' + 1 // k == 'x' (untyped rune constant)
const Huge = 1 << 100 // Huge == 1267650600228229401496703205376
const Four int8 = Huge >> 98 // Four == 4 (type int8)
Order of evaluation
At package level, initialisation dependencies determine the order of initialisation expressions. Elsewhere, when evaluating the operands of an expression, assignment or return statement, function calls, method calls, receive operations and binary logical operations happen in lexical left-to-right order. The order of other operations relative to those, such as reading a variable, is not specified (spec: Order of evaluation).
y[f()], ok = g(z || h(), i()+x[j()], <-c), k()
// calls and communication happen in the order
// f(), h() (if z is false), i(), j(), <-c, g(), k()
a := 1
f := func() int { a++; return a }
x := []int{a, f()} // x may be [1, 2] or [2, 2]
m := map[int]int{a: 1, a: 2} // m may be {2: 1} or {2: 2}
n := map[int]int{a: f()} // n may be {2: 3} or {3: 3}
Floating-point operations in a single expression are evaluated according to the
associativity of the operators; parentheses override it, so x + (y + z) computes
y + z first. Assignments have their own two-phase rule:
Assignment statements.