# Operators

## Operators

Operators combine operands into expressions.

Nice. I love a concise description/definition. Especially after the confusion that was yesterday’s post about loose and exact unification.

``````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   = "+" | "-" | "!" | "^" | "*" | "&" | "<-" .
``````

Comparisons are discussed elsewhere.

Alright, so we’ll be talking about the non-comparison operators for now. Let’s just dive in with binary operators, why don’t we…

… For other binary operators, the operand types must be identical unless the operation involves shifts or untyped constants.

The identical type constraint means the following code is invalid

``````var a = bool(false)
type B bool
var b = B(true)
fmt.Println(a || b) // invalid operation: a || b (mismatched types bool and B)
``````

… For operations involving constants only, see the section on constant expressions.

Except for shift operations, if one operand is an untyped constant and the other operand is not, the constant is implicitly converted to the type of the other operand.

This means that the following code (only slighlty modified from the above example) is valid:

``````type B bool
var b = B(true)
fmt.Println(false || b) // the untyped constant `false` is implicitly converted to type B
``````

Quotes from The Go Programming Language Specification Version of August 2, 2023