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