Skip to content

Go Operators

Operators are symbols used to perform specific operations. Go provides rich operators including arithmetic, comparison, logical, bitwise, and assignment operators. This chapter will detail the usage and application scenarios of various operators.

🧮 Arithmetic Operators

Basic Arithmetic Operations

go
package main

import "fmt"

func main() {
    a, b := 15, 4
    
    fmt.Printf("a = %d, b = %d\n", a, b)
    fmt.Printf("Addition: %d + %d = %d\n", a, b, a+b)     // 19
    fmt.Printf("Subtraction: %d - %d = %d\n", a, b, a-b)     // 11
    fmt.Printf("Multiplication: %d * %d = %d\n", a, b, a*b)     // 60
    fmt.Printf("Division: %d / %d = %d\n", a, b, a/b)     // 3 (integer division)
    fmt.Printf("Modulo: %d %% %d = %d\n", a, b, a%b)    // 3
    
    // Floating-point operations
    x, y := 15.0, 4.0
    fmt.Printf("\nFloating-point operations:\n")
    fmt.Printf("%.1f / %.1f = %.2f\n", x, y, x/y)    // 3.75
    
    // Unary operators
    fmt.Printf("\nUnary operators:\n")
    fmt.Printf("+a = %d\n", +a)    // 15 (positive sign)
    fmt.Printf("-a = %d\n", -a)    // -15 (negative sign)
}

Integer Division and Modulo

go
func main() {
    // Integer division (truncating division)
    fmt.Println("Integer division:")
    fmt.Printf("7 / 3 = %d\n", 7/3)      // 2
    fmt.Printf("7 / -3 = %d\n", 7/-3)    // -2
    fmt.Printf("-7 / 3 = %d\n", -7/3)    // -2
    fmt.Printf("-7 / -3 = %d\n", -7/-3)  // 2
    
    // Modulo operations
    fmt.Println("\nModulo operations:")
    fmt.Printf("7 %% 3 = %d\n", 7%3)     // 1
    fmt.Printf("7 %% -3 = %d\n", 7%-3)   // 1
    fmt.Printf("-7 %% 3 = %d\n", -7%3)   // -1
    fmt.Printf("-7 %% -3 = %d\n", -7%-3) // -1
    
    // Application: check even/odd
    numbers := []int{1, 2, 3, 4, 5, 6}
    for _, num := range numbers {
        if num%2 == 0 {
            fmt.Printf("%d is even\n", num)
        } else {
            fmt.Printf("%d is odd\n", num)
        }
    }
}

Increment and Decrement Operators

go
func main() {
    // Postfix increment/decrement (Go only has postfix form)
    i := 5
    fmt.Printf("Initial value: i = %d\n", i)
    
    i++  // Equivalent to i = i + 1
    fmt.Printf("After i++: i = %d\n", i)  // 6
    
    i--  // Equivalent to i = i - 1
    fmt.Printf("After i--: i = %d\n", i)  // 5
    
    // Note: ++ and -- are statements, not expressions
    // x := i++  // Error! Cannot use this way
    // y := ++i  // Error! Go has no prefix increment
    
    // Correct usage
    j := i
    i++
    fmt.Printf("j = %d, i = %d\n", j, i)
    
    // Common usage in loops
    fmt.Println("Counting loop:")
    for count := 0; count < 5; count++ {
        fmt.Printf("Count: %d\n", count)
    }
}

⚖️ Comparison Operators

Basic Comparison Operations

go
func main() {
    a, b := 10, 20
    
    fmt.Printf("a = %d, b = %d\n", a, b)
    fmt.Printf("a == b: %t\n", a == b)  // false (equal)
    fmt.Printf("a != b: %t\n", a != b)  // true  (not equal)
    fmt.Printf("a < b:  %t\n", a < b)   // true  (less than)
    fmt.Printf("a <= b: %t\n", a <= b)  // true  (less than or equal)
    fmt.Printf("a > b:  %t\n", a > b)   // false (greater than)
    fmt.Printf("a >= b: %t\n", a >= b)  // false (greater than or equal)
    
    // String comparison (lexicographic order)
    str1, str2 := "apple", "banana"
    fmt.Printf("\nString comparison:\n")
    fmt.Printf("\"%s\" < \"%s\": %t\n", str1, str2, str1 < str2)
    fmt.Printf("\"%s\" == \"%s\": %t\n", str1, str1, str1 == str1)
}

Comparison of Different Types

go
import "math"

func main() {
    // Floating-point comparison requires attention to precision
    f1 := 0.1 + 0.2
    f2 := 0.3
    
    fmt.Printf("0.1 + 0.2 = %.17f\n", f1)
    fmt.Printf("0.3 = %.17f\n", f2)
    fmt.Printf("f1 == f2: %t\n", f1 == f2)  // false!
    
    // Correct way to compare floating-point
    epsilon := 1e-9
    isEqual := math.Abs(f1-f2) < epsilon
    fmt.Printf("Using precision comparison: %t\n", isEqual)  // true
    
    // Special floating-point values
    fmt.Printf("\nSpecial floating-point value comparison:\n")
    fmt.Printf("NaN == NaN: %t\n", math.NaN() == math.NaN())  // false
    fmt.Printf("Inf == Inf: %t\n", math.Inf(1) == math.Inf(1))  // true
    
    // Boolean comparison
    fmt.Printf("\nBoolean comparison:\n")
    fmt.Printf("true == true: %t\n", true == true)    // true
    fmt.Printf("true != false: %t\n", true != false)  // true
}

🧠 Logical Operators

Basic Logical Operations

go
func main() {
    a, b := true, false
    
    fmt.Printf("a = %t, b = %t\n", a, b)
    fmt.Printf("a && b: %t\n", a && b)  // false (logical AND)
    fmt.Printf("a || b: %t\n", a || b)  // true  (logical OR)
    fmt.Printf("!a: %t\n", !a)          // false (logical NOT)
    fmt.Printf("!b: %t\n", !b)          // true  (logical NOT)
    
    // Compound logical expressions
    x, y, z := true, false, true
    result1 := x && y || z      // (x && y) || z = false || true = true
    result2 := x && (y || z)    // x && (y || z) = true && true = true
    
    fmt.Printf("\nCompound expressions:\n")
    fmt.Printf("x && y || z: %t\n", result1)
    fmt.Printf("x && (y || z): %t\n", result2)
}

Short-Circuit Evaluation

go
func main() {
    // Short-circuit evaluation for logical AND
    fmt.Println("Logical AND short-circuit evaluation:")
    if false && expensiveFunction() {
        fmt.Println("Will not execute")
    }
    
    // Short-circuit evaluation for logical OR
    fmt.Println("Logical OR short-circuit evaluation:")
    if true || expensiveFunction() {
        fmt.Println("Will execute, but expensiveFunction won't be called")
    }
    
    // Practical application: safety checks
    var ptr *int
    if ptr != nil && *ptr > 0 {
        fmt.Println("Pointer is valid and value is positive")
    } else {
        fmt.Println("Pointer is nil or value is not positive")
    }
}

func expensiveFunction() bool {
    fmt.Println("Expensive function was called")
    return true
}

🔢 Bit Operators

Basic Bit Operations

go
func main() {
    a, b := uint8(60), uint8(13)  // 60 = 0011 1100, 13 = 0000 1101
    
    fmt.Printf("a = %d (binary: %08b)\n", a, a)
    fmt.Printf("b = %d (binary: %08b)\n", b, b)
    
    fmt.Printf("\nBit operation results:\n")
    fmt.Printf("a & b = %d (binary: %08b)\n", a&b, a&b)   // Bitwise AND: 12 = 0000 1100
    fmt.Printf("a | b = %d (binary: %08b)\n", a|b, a|b)   // Bitwise OR: 61 = 0011 1101
    fmt.Printf("a ^ b = %d (binary: %08b)\n", a^b, a^b)   // Bitwise XOR: 49 = 0011 0001
    fmt.Printf("^a = %d (binary: %08b)\n", ^a, ^a)        // Bitwise NOT: 195 = 1100 0011
    
    // Bit shift operations
    fmt.Printf("\nBit shift operations:\n")
    fmt.Printf("a << 2 = %d (binary: %08b)\n", a<<2, a<<2) // Left shift: 240 = 1111 0000
    fmt.Printf("a >> 2 = %d (binary: %08b)\n", a>>2, a>>2) // Right shift: 15 = 0000 1111
}

Bit Operation Applications

Permission Management

go
func main() {
    // Use bit flags to represent permissions
    const (
        PermissionRead   = 1 << iota  // 1 = 0001
        PermissionWrite               // 2 = 0010
        PermissionExecute             // 4 = 0100
        PermissionDelete              // 8 = 1000
    )
    
    // Set permissions
    userPermissions := PermissionRead | PermissionWrite  // 3 = 0011
    
    fmt.Printf("User permissions: %d (binary: %04b)\n", userPermissions, userPermissions)
    
    // Check permissions
    hasRead := userPermissions&PermissionRead != 0
    hasWrite := userPermissions&PermissionWrite != 0
    hasExecute := userPermissions&PermissionExecute != 0
    hasDelete := userPermissions&PermissionDelete != 0
    
    fmt.Printf("Read permission: %t\n", hasRead)
    fmt.Printf("Write permission: %t\n", hasWrite)
    fmt.Printf("Execute permission: %t\n", hasExecute)
    fmt.Printf("Delete permission: %t\n", hasDelete)
    
    // Add permission
    userPermissions |= PermissionExecute
    fmt.Printf("After adding execute permission: %d (binary: %04b)\n", userPermissions, userPermissions)
    
    // Remove permission
    userPermissions &^= PermissionWrite  // Bit clear operator
    fmt.Printf("After removing write permission: %d (binary: %04b)\n", userPermissions, userPermissions)
}

Fast Math Operations

go
func main() {
    // Use bit operations for fast calculations
    n := 16
    
    // Check if power of 2
    isPowerOfTwo := n > 0 && (n&(n-1)) == 0
    fmt.Printf("%d is power of 2: %t\n", n, isPowerOfTwo)
    
    // Multiply by power of 2 (left shift)
    fmt.Printf("%d * 4 = %d (using %d << 2)\n", n, n<<2, n)
    fmt.Printf("%d * 8 = %d (using %d << 3)\n", n, n<<3, n)
    
    // Divide by power of 2 (right shift)
    fmt.Printf("%d / 4 = %d (using %d >> 2)\n", n, n>>2, n)
    fmt.Printf("%d / 8 = %d (using %d >> 3)\n", n, n>>3, n)
    
    // Get lowest set bit
    lowestBit := n & (-n)
    fmt.Printf("Lowest set bit of %d: %d\n", n, lowestBit)
    
    // Count number of 1s in binary (Hamming weight)
    count := popCount(uint(n))
    fmt.Printf("Number of 1s in binary of %d: %d\n", n, count)
}

func popCount(x uint) int {
    count := 0
    for x != 0 {
        count++
        x &= x - 1  // Clear lowest set bit
    }
    return count
}

📝 Assignment Operators

Basic Assignment

go
func main() {
    var x int
    
    // Basic assignment
    x = 10
    fmt.Printf("x = %d\n", x)
    
    // Compound assignment operators
    x += 5   // x = x + 5
    fmt.Printf("x += 5: %d\n", x)  // 15
    
    x -= 3   // x = x - 3
    fmt.Printf("x -= 3: %d\n", x)  // 12
    
    x *= 2   // x = x * 2
    fmt.Printf("x *= 2: %d\n", x)  // 24
    
    x /= 4   // x = x / 4
    fmt.Printf("x /= 4: %d\n", x)  // 6
    
    x %= 5   // x = x % 5
    fmt.Printf("x %%= 5: %d\n", x) // 1
}

Bitwise Assignment

go
func main() {
    x := uint8(60)  // 0011 1100
    
    fmt.Printf("Initial x = %d (binary: %08b)\n", x, x)
    
    x &= 15   // x = x & 15 (0000 1111)
    fmt.Printf("x &= 15: %d (binary: %08b)\n", x, x)  // 12 (0000 1100)
    
    x |= 3    // x = x | 3 (0000 0011)
    fmt.Printf("x |= 3: %d (binary: %08b)\n", x, x)   // 15 (0000 1111)
    
    x ^= 5    // x = x ^ 5 (0000 0101)
    fmt.Printf("x ^= 5: %d (binary: %08b)\n", x, x)   // 10 (0000 1010)
    
    x <<= 1   // x = x << 1
    fmt.Printf("x <<= 1: %d (binary: %08b)\n", x, x)  // 20 (0001 0100)
    
    x >>= 2   // x = x >> 2
    fmt.Printf("x >>= 2: %d (binary: %08b)\n", x, x)  // 5 (0000 0101)
}

Multiple Assignment

go
func main() {
    // Multiple assignment
    a, b, c := 1, 2, 3
    fmt.Printf("Initial: a=%d, b=%d, c=%d\n", a, b, c)
    
    // Swap variables
    a, b = b, a
    fmt.Printf("Swap a and b: a=%d, b=%d, c=%d\n", a, b, c)
    
    // Function returning multiple values
    x, y := divmod(17, 5)
    fmt.Printf("17 divided by 5: quotient=%d, remainder=%d\n", x, y)
    
    // Ignore some values
    quotient, _ := divmod(20, 3)  // Ignore remainder
    fmt.Printf("Quotient of 20 divided by 3: %d\n", quotient)
    
    // Batch assignment
    var (
        name string
        age  int
        city string
    )
    name, age, city = "Zhang San", 25, "Beijing"
    fmt.Printf("Personal info: %s, %d years old, from %s\n", name, age, city)
}

func divmod(a, b int) (int, int) {
    return a / b, a % b
}

🎯 Operator Precedence

Precedence Table

go
func main() {
    // Go operator precedence (from high to low)
    
    // 1. Highest precedence: unary operators
    x := 5
    result1 := -x * 2    // -5 * 2 = -10
    fmt.Printf("-x * 2 = %d\n", result1)
    
    // 2. Multiplication, division, remainder, shift, bitwise AND
    result2 := 2 + 3 * 4        // 2 + 12 = 14
    result3 := 8 << 1 + 1       // 8 << 2 = 32
    result4 := 12 & 7 + 1       // 12 & 8 = 8
    fmt.Printf("2 + 3 * 4 = %d\n", result2)
    fmt.Printf("8 << 1 + 1 = %d\n", result3)
    fmt.Printf("12 & 7 + 1 = %d\n", result4)
    
    // 3. Addition, subtraction, bitwise OR, bitwise XOR
    result5 := 1 + 2 << 3       // 1 + (2 << 3) = 1 + 16 = 17
    result6 := 5 | 2 + 1        // 5 | 3 = 7
    fmt.Printf("1 + 2 << 3 = %d\n", result5)
    fmt.Printf("5 | 2 + 1 = %d\n", result6)
    
    // 4. Comparison operators
    result7 := 1 + 2 == 3       // true
    result8 := 2 * 3 > 5        // true
    fmt.Printf("1 + 2 == 3: %t\n", result7)
    fmt.Printf("2 * 3 > 5: %t\n", result8)
    
    // 5. Logical AND
    result9 := true && 2 > 1    // true
    fmt.Printf("true && 2 > 1: %t\n", result9)
    
    // 6. Logical OR
    result10 := false || 3 < 5   // true
    fmt.Printf("false || 3 < 5: %t\n", result10)
}

Using Parentheses to Clarify Precedence

go
func main() {
    // Without parentheses (relying on default precedence)
    result1 := 2 + 3 * 4 - 1    // 2 + 12 - 1 = 13
    
    // Use parentheses to clarify intent
    result2 := (2 + 3) * (4 - 1)  // 5 * 3 = 15
    result3 := 2 + (3 * 4) - 1    // Same as result1, but clearer
    
    fmt.Printf("Default precedence: 2 + 3 * 4 - 1 = %d\n", result1)
    fmt.Printf("Using parentheses: (2 + 3) * (4 - 1) = %d\n", result2)
    fmt.Printf("Explicit parentheses: 2 + (3 * 4) - 1 = %d\n", result3)
    
    // Complex expressions
    a, b, c := 2, 3, 4
    complex1 := a + b * c > 10 && a < b || c == 4
    complex2 := ((a + (b * c)) > 10) && (a < b) || (c == 4)
    
    fmt.Printf("Complex expression 1: %t\n", complex1)
    fmt.Printf("Complex expression 2: %t\n", complex2)
}

🎯 Practical Application Example

Mathematical Calculator

go
import "fmt"

func main() {
    // Simple calculator
    calculator := NewCalculator()
    
    // Basic operations
    fmt.Printf("10 + 5 = %.2f\n", calculator.Add(10, 5))
    fmt.Printf("10 - 5 = %.2f\n", calculator.Subtract(10, 5))
    fmt.Printf("10 * 5 = %.2f\n", calculator.Multiply(10, 5))
    fmt.Printf("10 / 5 = %.2f\n", calculator.Divide(10, 5))
    
    // Advanced operations
    fmt.Printf("2^8 = %.0f\n", calculator.Power(2, 8))
    fmt.Printf("√16 = %.2f\n", calculator.SquareRoot(16))
    fmt.Printf("10%% = %.2f\n", calculator.Percentage(10))
}

type Calculator struct{}

func NewCalculator() *Calculator {
    return &Calculator{}
}

func (c *Calculator) Add(a, b float64) float64 {
    return a + b
}

func (c *Calculator) Subtract(a, b float64) float64 {
    return a - b
}

func (c *Calculator) Multiply(a, b float64) float64 {
    return a * b
}

func (c *Calculator) Divide(a, b float64) float64 {
    if b == 0 {
        panic("Divisor cannot be zero")
    }
    return a / b
}

func (c *Calculator) Power(base, exp float64) float64 {
    result := 1.0
    for i := 0; i < int(exp); i++ {
        result *= base
    }
    return result
}

func (c *Calculator) SquareRoot(n float64) float64 {
    if n < 0 {
        panic("Negative numbers have no real square root")
    }
    // Newton's method for square root
    x := n
    for i := 0; i < 10; i++ {
        x = (x + n/x) / 2
    }
    return x
}

func (c *Calculator) Percentage(n float64) float64 {
    return n / 100
}

🎓 Summary

In this chapter, we comprehensively learned about Go operators:

  • Arithmetic Operators: +, -, *, /, %, ++, --
  • Comparison Operators: ==, !=, <, <=, >, >=
  • Logical Operators: &&, ||, !, short-circuit evaluation
  • Bit Operators: &, |, ^, <<, >>, &^
  • Assignment Operators: =, +=, -=, *=, /=, %=, etc.
  • Operator Precedence: priority rules and parentheses usage

Mastering the correct use of operators is the foundation of writing efficient Go code, especially bit operators which play an important role in systems programming and performance optimization.


Next, we will learn Go Conditional Statements to master program branch control.

Operator Usage Suggestions

  • Use parentheses to clarify operation order in complex expressions
  • Pay attention to precision issues when comparing floating-point numbers
  • Use bit operations for efficient flag operations
  • Use short-circuit evaluation to improve program performance

Content is for learning and research only.