Operators
Expression binding order
Calls, member selection, indexing, and slicing bind to their target before prefix operators. Prefix !, +, -, ^, *, &, <-, go, and await bind before postfix assertions (as? T, as! T) and result propagation (?). Binary expressions then group by the table below. Parentheses override that order.
Binary precedence
From lowest to highest; every binary group is left-associative:
| Level | Operators | Operand summary |
|---|---|---|
| 1 | || | boolean |
| 2 | && | boolean |
| 3 | ==, !=, ===, !== | Compatible comparable values |
| 4 | <, <=, >, >= | Compatible ordered values |
| 5 | +, -, ` | , ^` |
| 6 | *, /, %, <<, >>, &, &^ | Numeric/integer as applicable |
The grouping follows the implemented Go-compatible bitwise precedence. a + b << c means a + (b << c); a | b + c means (a | b) + c.
Boolean and comparison operators
! accepts one boolean. && and || accept boolean operands, evaluate left to right, and short-circuit the right operand when the result is already known.
The two equality spellings are semantic aliases: == and === both perform typed equality, while != and !== both perform typed inequality. None performs JavaScript-style coercion. Operands must have compatible identical types and be comparable; slices, maps, and functions are not generally comparable. A concrete nil-capable or nullable counterpart is required when comparing with nil or null.
Ordering accepts two values of the same ordered type. Numeric widths and signedness are not mixed implicitly; strings use Go's byte-wise lexicographic order.
Numeric identity
Typed binary operands normally require identical numeric types. A representable untyped constant can combine with a typed operand. Operations preserve defined-type identity where Go does. No implicit signed/unsigned or width conversion occurs.
function combine(left: int, right: int32): int {
return left | right;
}Dynamic fixed-width arithmetic preserves Go overflow behavior. Statically known out-of-range constants are source diagnostics.
Unary + and - require numeric values. Binary +, -, *, and / require compatible numeric operands; % is integer-only. + also concatenates two compatible strings. Constant integer division or remainder by zero is rejected, while a data-dependent zero divisor retains Go's runtime panic behavior.
function divide(value: int): int {
value /= 0;
return value;
}Shifts and bitwise operators
&, |, ^, &^, <<, and >> require integers; unary ^ is integer complement. Shift operands need not share a type, and the result has the left operand's type.
Negative constant shifts and the compiler's constant-shift limit are rejected before generation. Dynamic negative shifts retain Go runtime panic behavior. Unary &value is address acquisition; binary left & right is bitwise AND.
function move(value: int): int {
return value << -1;
}For a nonconstant shift such as 1 << n, an untyped left operand takes its integer type from the destination or a typed peer. This also permits 1.0 << n in an integer context: the literal is exactly representable as an integer. Array indices, slice bounds and allocation sizes supply an int context.
import go fmt from "fmt";
function mask(n: uint): byte {
return 1 << n;
}
function main(): void {
const n: uint = 2;
const values = make[int[]](1.0 << n, 2.0 << n);
fmt.Println(mask(n), len(values), cap(values));
}The left operand must fit that type before shifting: 300 << n cannot produce a byte, even if a particular shift count would discard the high bits. A floating-point destination is invalid. Without an integer context, const value = 1.0 << n defaults to a floating-point type and is rejected. An already stored runtime value keeps its type; a later use cannot retroactively change the type of its initializer.
function mask(n: uint): byte {
return 300 << n;
}The numeric and bitwise recipe traces masks, complement, signed shift behavior, compound updates, and explicit width conversion in one runnable program.
Pointer operators
| Operator | Meaning |
|---|---|
&value | Address of an addressable value |
*pointer | Dereference a pointer |
Non-addressable temporaries are rejected. Nil pointer dereference preserves Go panic behavior.
struct Point {
public x: int;
}
function makePoint(): Point {
return Point { x: 1 };
}
function invalid(): *Point {
return &makePoint();
}Updates
Supported update statements:
+= -= *= /= %= &= |= ^= &^= <<= >>= ++ --Targets can be identifiers, writable fields/properties, assignable indexes, or pointer dereferences. Property updates require an accessible getter and setter and perform ordered read/modify/write calls, not atomic mutation. Generated compound assignment evaluates a selector/index/pointer target once. ++ and -- never produce a value.
Strings support only +=. Remainder and bitwise updates require integers. Map indexes are writable; string indexes, methods, constants, and non-addressable temporary fields/array indexes are not.
Assertions and conversions
as? Type performs a checked Go-interface or class downcast and returns value plus boolean. as! Type is forced and panics on failure. Both evaluate the source once.
Type-name calls such as int64(value) or UserID(text) are explicit conversions and follow representability, identity, and Go convertibility rules for the source/target pair.
Result propagation
Postfix ? accepts Result<T>, a compatible Go (T, error) result, or a single error inside a Result-returning function. It evaluates the operation once and returns early when the error is non-nil.
A non-void propagated value must directly initialize one binding; propagation cannot be buried in an arbitrary expression. A void or single-error operation may stand alone. Use Failures, Result, and exceptions for the full return and cleanup contract.