1. go
  2. /basics
  3. /operators

Understanding Operators in Go Programming

Go provides a comprehensive set of operators for performing various operations. This guide covers all the operators available in Go and how to use them effectively.

Arithmetic Operators

Basic Arithmetic

// Addition
sum := 5 + 3      // 8

// Subtraction
diff := 10 - 5    // 5

// Multiplication
product := 4 * 3  // 12

// Division
quotient := 15 / 3  // 5
quotient = 10 / 3   // 3 (integer division)

// Modulus (remainder)
remainder := 10 % 3  // 1

// Increment
x := 5
x++  // x is now 6

// Decrement
x--  // x is now 5

Compound Assignment

x := 10

// Add and assign
x += 5   // x = x + 5

// Subtract and assign
x -= 3   // x = x - 3

// Multiply and assign
x *= 2   // x = x * 2

// Divide and assign
x /= 4   // x = x / 4

// Modulus and assign
x %= 3   // x = x % 3

Comparison Operators

x, y := 10, 20

// Equal to
isEqual := x == y    // false

// Not equal to
notEqual := x != y   // true

// Greater than
isGreater := x > y   // false

// Less than
isLess := x < y      // true

// Greater than or equal to
isGreaterEqual := x >= y  // false

// Less than or equal to
isLessEqual := x <= y     // true

Logical Operators

p, q := true, false

// Logical AND
result := p && q    // false

// Logical OR
result = p || q     // true

// Logical NOT
result = !p         // false

// Short-circuit evaluation
if p && someExpensiveFunction() {
    // someExpensiveFunction is not called if p is false
}

if p || someExpensiveFunction() {
    // someExpensiveFunction is not called if p is true
}

Bitwise Operators

x, y := 12, 25  // 1100, 11001 in binary

// Bitwise AND
result := x & y   // 8  (1000)

// Bitwise OR
result = x | y    // 29 (11101)

// Bitwise XOR
result = x ^ y    // 21 (10101)

// Bitwise NOT
result = ^x       // -13 (complement)

// Left shift
result = x << 2   // 48 (110000)

// Right shift
result = x >> 2   // 3  (11)

Address Operators

// Address of operator
x := 42
ptr := &x    // Get address of x

// Dereference operator
value := *ptr  // Get value at address

// Example with pointers
func increment(ptr *int) {
    *ptr++  // Increment value at address
}

num := 10
increment(&num)  // Pass address of num

Channel Operators

// Channel send operator
ch := make(chan int)
ch <- 42  // Send value to channel

// Channel receive operator
value := <-ch  // Receive from channel

// Select with channel operations
select {
case v := <-ch1:
    // Handle value from ch1
case ch2 <- value:
    // Send value to ch2
default:
    // No channel ready
}

Operator Precedence

// Operator precedence (highest to lowest)
result := 5 + 3 * 2     // 11 (not 16)
result = (5 + 3) * 2    // 16

// Complex expressions
result = 15 - 3 * 2 + 4/2  // 11

// Bitwise operations
result = 5 | 3 & 2     // 7
result = (5 | 3) & 2   // 0

Best Practices

1. Clear Expressions

// Good: Clear and readable
result := (a + b) * (c + d)

// Avoid: Complex nested operations
result = a + b * c + d / e % f

2. Type Safety

// Good: Type-safe operations
var (
    i int     = 42
    f float64 = float64(i) * 2.5
)

// Avoid: Implicit conversions
f = i * 2.5  // Compilation error

3. Pointer Safety

// Good: Check for nil pointers
func process(ptr *int) {
    if ptr == nil {
        return
    }
    *ptr++
}

// Avoid: Unchecked pointer dereference
func unsafe(ptr *int) {
    *ptr++  // Panic if ptr is nil
}

Common Patterns

1. Bit Manipulation

// Set bit
flag := flag | (1 << position)

// Clear bit
flag := flag &^ (1 << position)

// Toggle bit
flag := flag ^ (1 << position)

// Check bit
isSet := (flag & (1 << position)) != 0

2. Integer Division

// Round towards zero (default)
result := 10 / 3  // 3

// Round up
result = (10 + 2) / 3  // 4

// Round down
result = 10 / 3  // 3

3. Safe Division

func safeDivide(x, y float64) (float64, error) {
    if y == 0 {
        return 0, errors.New("division by zero")
    }
    return x / y, nil
}

Performance Considerations

1. Arithmetic Operations

// Multiplication vs Shift
result := x * 2    // Less readable
result = x << 1    // More efficient

// Division vs Shift
result = x / 2     // Less readable
result = x >> 1    // More efficient (for positive numbers)

2. Boolean Operations

// Short-circuit evaluation
if expensive() && cheap() {  // Bad: expensive always runs
    // ...
}

if cheap() && expensive() {  // Good: expensive may be skipped
    // ...
}

Common Mistakes

1. Integer Overflow

// Wrong: Possible overflow
var x int32 = 2147483647
x++  // Overflow

// Right: Check for overflow
if x < math.MaxInt32 {
    x++
}

2. Division by Zero

// Wrong: Possible panic
result := x / y  // Panics if y is 0

// Right: Check for zero
if y != 0 {
    result = x / y
} else {
    // Handle division by zero
}

Next Steps

  1. Learn about control flow
  2. Explore functions
  3. Study error handling
  4. Practice with data types

Additional Resources