Go Operators
Go - Operators
Section titled “Go - Operators”An operator is a symbol that tells the compiler to perform specific mathematical, logical, or bitwise manipulations. Go is equipped with a rich set of built-in operators, categorized as follows:
- Arithmetic Operators
- Relational Operators
- Logical Operators
- Bitwise Operators
- Assignment Operators
- Miscellaneous Operators (like address-of & dereference)
This tutorial will guide you through each category of operators in Go.
Arithmetic Operators
Section titled “Arithmetic Operators”These operators perform mathematical calculations. Assume variable a holds 10 and variable b holds 20:
Example Code:
package main
import "fmt"
func main() { a := 10 b := 20 var result int
result = a + b fmt.Printf("a + b = %d\n", result) // Output: a + b = 30
result = a - b fmt.Printf("a - b = %d\n", result) // Output: a - b = -10
result = a * b fmt.Printf("a * b = %d\n", result) // Output: a * b = 200
result = b / a fmt.Printf("b / a = %d\n", result) // Output: b / a = 2 (Integer division)
result = b % a fmt.Printf("b %% a = %d\n", result) // Output: b % a = 0
// Go does not have ++/-- as expressions, only as statements. a++ // Increment a by 1 (a becomes 11) fmt.Printf("After a++, a = %d\n", a) // Output: After a++, a = 11
a-- // Decrement a by 1 (a becomes 10) fmt.Printf("After a--, a = %d\n", a) // Output: After a--, a = 10}| Operator | Description | Example (a=10, b=20) |
|---|---|---|
| + | Adds two operands. | a + b results in 30 |
| - | Subtracts the second operand from the first. | a - b results in -10 |
| * | Multiplies both operands. | a * b results in 200 |
| / | Divides the numerator by the denominator. Result is integer if both operands are integers. | b / a results in 2 |
| % | Modulus operator; returns the remainder of an integer division. | b % a results in 0 |
| ++ | Increment statement; increases an integer value by one. Not an expression. | a++ changes a to 11 |
| — | Decrement statement; decreases an integer value by one. Not an expression. | a-- changes a to 9 (if initial a=10) |
Note: ++ and -- in Go are statements, not expressions. You cannot write c := a++.
Relational Operators
Section titled “Relational Operators”These operators compare two operands and return a boolean value (true or false). Assume a holds 10 and b holds 20:
Example Code:
package main
import "fmt"
func main() { a := 10 b := 20
fmt.Printf("a == b: %t\n", a == b) // Output: a == b: false fmt.Printf("a != b: %t\n", a != b) // Output: a != b: true fmt.Printf("a > b: %t\n", a > b) // Output: a > b: false fmt.Printf("a < b: %t\n", a < b) // Output: a < b: true fmt.Printf("a >= b: %t\n", a >= b) // Output: a >= b: false fmt.Printf("a <= b: %t\n", a <= b) // Output: a <= b: true}| Operator | Description | Example (a=10, b=20) |
|---|---|---|
| == | Checks if the values of two operands are equal. Returns true if they are. | (a == b) is false. |
| != | Checks if the values of two operands are not equal. Returns true if they are not equal. | (a != b) is true. |
| > | Checks if the value of the left operand is greater than the value of the right operand. | (a > b) is false. |
| < | Checks if the value of the left operand is less than the value of the right operand. | (a < b) is true. |
| >= | Checks if the value of the left operand is greater than or equal to the value of the right operand. | (a >= b) is false. |
| <= | Checks if the value of the left operand is less than or equal to the value of the right operand. | (a <= b) is true. |
Logical Operators
Section titled “Logical Operators”These operators work on boolean operands. Assume a is true and b is false:
Example Code:
package main
import "fmt"
func main() { a := true b := false
fmt.Printf("a && b: %t\n", a && b) // Output: a && b: false fmt.Printf("a || b: %t\n", a || b) // Output: a || b: true fmt.Printf("!a: %t\n", !a) // Output: !a: false fmt.Printf("!(a && b): %t\n", !(a && b)) // Output: !(a && b): true}| Operator | Description | Example (a=true, b=false) |
|---|---|---|
| && | Logical AND. Returns true if both operands are true. | (a && b) is false. |
| || | Logical OR. Returns true if at least one of the operands is true. | (a || b) is true. |
| ! | Logical NOT. Reverses the logical state of its operand. If a is true, !a is false. | !(a && b) is true. |
Bitwise Operators
Section titled “Bitwise Operators”Bitwise operators perform operations on integer types at the binary level. Consider the truth tables for AND (&), OR (|), and XOR (^):
| p | q | p & q | p | q | p ^ q |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 1 | 0 | 1 | 1 |
| 1 | 1 | 1 | 1 | 0 |
| 1 | 0 | 0 | 1 | 1 |
Assume a = 60 (binary 0011 1100) and b = 13 (binary 0000 1101):
a = 0011 1100b = 0000 1101-----------------a & b = 0000 1100 (12)a | b = 0011 1101 (61)a ^ b = 0011 0001 (49)a &^ b = 0011 0000 (48) (Bit Clear)The bitwise NOT (^) operator in Go is actually XOR. To perform a bitwise complement (like C’s ~), you XOR with a mask (e.g., m = a ^ 0xFFFFFFFF for 32-bit). A simpler way for unsigned integers is often ^a if the context implies the bit width, or using math.MaxUintXX.
Example Code:
package main
import "fmt"
func main() { var a uint = 60 // 0011 1100 var b uint = 13 // 0000 1101 var result uint
result = a & b fmt.Printf("a & b = %d (binary %08b)\n", result, result) // Output: a & b = 12 (binary 00001100)
result = a | b fmt.Printf("a | b = %d (binary %08b)\n", result, result) // Output: a | b = 61 (binary 00111101)
result = a ^ b fmt.Printf("a ^ b = %d (binary %08b)\n", result, result) // Output: a ^ b = 49 (binary 00110001)
result = a << 2 fmt.Printf("a << 2 = %d (binary %08b)\n", result, result) // Output: a << 2 = 240 (binary 11110000)
result = a >> 2 fmt.Printf("a >> 2 = %d (binary %08b)\n", result, result) // Output: a >> 2 = 15 (binary 00001111)
// Bit Clear (AND NOT) result = a &^ b // Clears bits in 'a' that are set in 'b' fmt.Printf("a &^ b = %d (binary %08b)\n", result, result) // Output: a &^ b = 48 (binary 00110000)}| Operator | Description | Example (a=60, b=13, unsigned) |
|---|---|---|
| & | Bitwise AND: Sets a bit to 1 if it exists in both operands. | a & b results in 12 (0000 1100) |
| | | Bitwise OR: Sets a bit to 1 if it exists in either operand. | a | b results in 61 (0011 1101) |
| ^ | Bitwise XOR: Sets a bit to 1 if it is set in one operand but not both. | a ^ b results in 49 (0011 0001) |
| << | Left Shift: Moves the bits of the left operand left by the number of positions specified by the right operand. Fills with zeros. | a << 2 results in 240 (1111 0000) |
| >> | Right Shift: Moves the bits of the left operand right by the number of positions specified by the right operand. Behavior depends on signed/unsigned type (arithmetic vs logical shift). | a >> 2 results in 15 (0000 1111 for unsigned a) |
| &^ | Bit Clear (AND NOT): Clears bits in the left operand that are set in the right operand (a & (^b)). | a &^ b results in 48 (0011 0000) |
Assignment Operators
Section titled “Assignment Operators”These operators assign values to variables, often combining an arithmetic or bitwise operation with assignment.
Example Code:
package main
import "fmt"
func main() { a := 10 c := 5
c += a // c = c + a = 5 + 10 = 15 fmt.Printf("c += a -> c = %d\n", c)
c = 5 // Reset c c -= a // c = c - a = 5 - 10 = -5 fmt.Printf("c -= a -> c = %d\n", c)
c = 5 // Reset c c *= a // c = c * a = 5 * 10 = 50 fmt.Printf("c *= a -> c = %d\n", c)
c = 50 // Reset c c /= a // c = c / a = 50 / 10 = 5 fmt.Printf("c /= a -> c = %d\n", c)
c = 51 // Reset c c %= a // c = c % a = 51 % 10 = 1 fmt.Printf("c %%= a -> c = %d\n", c)
// Similar examples for bitwise assignment operators (<<=, >>=, &=, ^=, |=, &^=) d := uint(60) // Use uint for bitwise ops d <<= 2 // d = d << 2 fmt.Printf("d <<= 2 -> d = %d\n", d)}| Operator | Description | Example |
|---|---|---|
| = | Simple assignment: Assigns the value from the right side to the left side operand. | c = a + b assigns the value of a + b to c. |
| += | Add AND assignment: Adds the right operand to the left operand and assigns the result to the left operand. | c += a is equivalent to c = c + a. |
| -= | Subtract AND assignment: Subtracts the right operand from the left operand and assigns the result to the left operand. | c -= a is equivalent to c = c - a. |
| *= | Multiply AND assignment: Multiplies the right operand with the left operand and assigns the result to the left operand. | c *= a is equivalent to c = c * a. |
| /= | Divide AND assignment: Divides the left operand by the right operand and assigns the result to the left operand. | c /= a is equivalent to c = c / a. |
| %= | Modulus AND assignment: Takes the modulus using two operands and assigns the result to the left operand. | c %= a is equivalent to c = c % a. |
| <<= | Left shift AND assignment. | c <<= 2 is equivalent to c = c << 2. |
| >>= | Right shift AND assignment. | c >>= 2 is equivalent to c = c >> 2. |
| &= | Bitwise AND assignment. | c &= 2 is equivalent to c = c & 2. |
| ^= | Bitwise exclusive OR AND assignment. | c ^= 2 is equivalent to c = c ^ 2. |
| |= | Bitwise inclusive OR AND assignment. | c |= 2 is equivalent to c = c | 2. |
| &^= | Bit clear AND assignment. | c &^= 2 is equivalent to c = c &^ 2. |
Miscellaneous Operators
Section titled “Miscellaneous Operators”Go includes operators related to memory addresses and pointers:
Example Code:
package main
import "fmt"
func main() { a := 100 var ptr *int // Declare a pointer to an integer
ptr = &a // Assign the memory address of 'a' to 'ptr' fmt.Printf("Address of a: %p\n", &a) // Output: Address of a: 0x... (actual address) fmt.Printf("Value stored in ptr: %p\n", ptr) // Output: Value stored in ptr: 0x... (same address)
// Dereference the pointer to get the value fmt.Printf("Value pointed to by ptr (*ptr): %d\n", *ptr) // Output: Value pointed to by ptr (*ptr): 100}| Operator | Description | Example |
|---|---|---|
| & | Address-of operator: Returns the memory address of a variable. | &a gives the actual memory address of the variable a. |
| * | Dereference operator (when used with a pointer): Accesses the value stored at the memory address held by the pointer. | *ptr gives the value stored at the address ptr points to. |
Note: Go does not have a ternary operator (? :) like C or Java. You must use standard if-else statements.
The sizeof concept is handled by the unsafe.Sizeof function from the unsafe package, but its use is generally discouraged unless dealing with low-level operations or interoperability.
Operator Precedence in Go
Section titled “Operator Precedence in Go”Operator precedence defines the order in which operations are performed in an expression. Operators with higher precedence are evaluated first. For example, multiplication has higher precedence than addition.
Example: x := 7 + 3 * 2. Here, 3 * 2 (6) is evaluated first due to higher precedence of *, then 7 + 6 is evaluated. So, x becomes 13, not 20.
Operators at the same precedence level are typically evaluated from left to right (check associativity). Parentheses () can be used to override precedence.
Go Operator Precedence (Highest to Lowest):
| Category | Operators | Associativity |
|---|---|---|
| Unary | + - ! ^ * & <- (Unary operators, pointer ops, channel receive) | N/A (Highest) |
| Multiplicative | * / % << >> & &^ | Left to right |
| Additive | + - | ^ | Left to right |
| Comparison | == != < <= > >= | Left to right |
| Logical AND | && | Left to right |
| Logical OR | || | Left to right |
Note: Assignment operations happen after evaluating the right-hand side. The precedence table above is simplified; for full details, refer to the official Go language specification.