Go Operators
Introduction
Operators are special symbols that tell the compiler to perform specific mathematical, relational, or logical operations. Go provides a rich set of operators to manipulate variables and values. Understanding operators is fundamental to writing effective Go code as they form the building blocks of expressions and statements.
In this tutorial, we'll explore the various operators available in Go, learn how to use them, and see practical examples of their applications in real-world scenarios.
Types of Operators in Go
Go supports several types of operators:
- Arithmetic Operators
- Comparison (Relational) Operators
- Logical Operators
- Bitwise Operators
- Assignment Operators
- Miscellaneous Operators
Let's dive into each category.
Arithmetic Operators
Arithmetic operators are used to perform mathematical operations like addition, subtraction, multiplication, and division.
Operator | Description | Example |
---|---|---|
+ | Addition | a + b |
- | Subtraction | a - b |
* | Multiplication | a * b |
/ | Division | a / b |
% | Modulus (remainder) | a % b |
++ | Increment | a++ |
-- | Decrement | a-- |
Example: Arithmetic Operators
package main
import "fmt"
func main() {
a := 15
b := 4
// Addition
fmt.Printf("%d + %d = %d", a, b, a+b)
// Subtraction
fmt.Printf("%d - %d = %d", a, b, a-b)
// Multiplication
fmt.Printf("%d * %d = %d", a, b, a*b)
// Division
fmt.Printf("%d / %d = %d", a, b, a/b)
// Modulus
fmt.Printf("%d %% %d = %d", a, b, a%b)
// Increment
c := a
c++
fmt.Printf("%d++ = %d", a, c)
// Decrement
d := a
d--
fmt.Printf("%d-- = %d", a, d)
}
Output:
15 + 4 = 19
15 - 4 = 11
15 * 4 = 60
15 / 4 = 3
15 % 4 = 3
15++ = 16
15-- = 14
In Go, ++
and --
are statements, not expressions. This means you cannot use them in expressions like a = b++
or a = ++b
. They must be used as standalone statements: a++
or b--
.
Integer Division vs. Floating-Point Division
When dividing two integers in Go, the result is also an integer, with any decimal part truncated.
package main
import "fmt"
func main() {
// Integer division
fmt.Println("5 / 2 =", 5/2) // Outputs: 2
// Floating-point division
fmt.Println("5.0 / 2.0 =", 5.0/2.0) // Outputs: 2.5
}
Output:
5 / 2 = 2
5.0 / 2.0 = 2.5
Comparison Operators
Comparison operators are used to compare two values. They return a boolean result (true
or false
).
Operator | Description | Example |
---|---|---|
== | Equal to | a == b |
!= | Not equal to | a != b |
< | Less than | a < b |
> | Greater than | a > b |
<= | Less than or equal to | a <= b |
>= | Greater than or equal to | a >= b |
Example: Comparison Operators
package main
import "fmt"
func main() {
a := 10
b := 20
fmt.Printf("%d == %d: %t", a, b, a == b)
fmt.Printf("%d != %d: %t", a, b, a != b)
fmt.Printf("%d < %d: %t", a, b, a < b)
fmt.Printf("%d > %d: %t", a, b, a > b)
fmt.Printf("%d <= %d: %t", a, b, a <= b)
fmt.Printf("%d >= %d: %t", a, b, a >= b)
}
Output:
10 == 20: false
10 != 20: true
10 < 20: true
10 > 20: false
10 <= 20: true
10 >= 20: false
Logical Operators
Logical operators are used to combine conditional statements.
Operator | Description | Example |
---|---|---|
&& | Logical AND | a && b |
|| | Logical OR | a || b |
! | Logical NOT | !a |
Example: Logical Operators
package main
import "fmt"
func main() {
a := true
b := false
// Logical AND
fmt.Printf("%t && %t = %t", a, b, a && b)
// Logical OR
fmt.Printf("%t || %t = %t", a, b, a || b)
// Logical NOT
fmt.Printf("!%t = %t", a, !a)
fmt.Printf("!%t = %t", b, !b)
}
Output:
true && false = false
true || false = true
!true = false
!false = true
Short-Circuit Evaluation
Go uses short-circuit evaluation for logical operators. This means that in an expression like a && b
, if a
is false
, b
is not evaluated because the result is already determined.
package main
import "fmt"
func main() {
// Short-circuit with &&
x := 10
if x > 20 && x/0 == 0 { // The second condition won't be evaluated
fmt.Println("This won't execute")
} else {
fmt.Println("Short-circuit prevented division by zero")
}
// Short-circuit with ||
y := 30
if y > 20 || y/0 == 0 { // The second condition won't be evaluated
fmt.Println("y is greater than 20")
}
}
Output:
Short-circuit prevented division by zero
y is greater than 20
Bitwise Operators
Bitwise operators perform operations on the binary representations of numbers.
Operator | Description | Example |
---|---|---|
& | Bitwise AND | a & b |
| | Bitwise OR | a | b |
^ | Bitwise XOR | a ^ b |
&^ | Bit clear (AND NOT) | a &^ b |
<< | Left shift | a << n |
>> | Right shift | a >> n |
Example: Bitwise Operators
package main
import "fmt"
func main() {
a := 60 // 00111100 in binary
b := 13 // 00001101 in binary
fmt.Printf("a = %d (%08b)", a, a)
fmt.Printf("b = %d (%08b)", b, b)
// Bitwise AND
fmt.Printf("a & b = %d (%08b)", a&b, a&b)
// Bitwise OR
fmt.Printf("a | b = %d (%08b)", a|b, a|b)
// Bitwise XOR
fmt.Printf("a ^ b = %d (%08b)", a^b, a^b)
// Bitwise AND NOT (bit clear)
fmt.Printf("a &^ b = %d (%08b)", a&^b, a&^b)
// Left shift
fmt.Printf("a << 2 = %d (%08b)", a<<2, a<<2)
// Right shift
fmt.Printf("a >> 2 = %d (%08b)", a>>2, a>>2)
}
Output:
a = 60 (00111100)
b = 13 (00001101)
a & b = 12 (00001100)
a | b = 61 (00111101)
a ^ b = 49 (00110001)
a &^ b = 48 (00110000)
a << 2 = 240 (11110000)
a >> 2 = 15 (00001111)
Practical Uses of Bitwise Operators
Bitwise operators are often used for:
- Flag manipulation: Setting, checking, and clearing flags in a single integer.
- Permissions: Managing access permissions (read, write, execute).
- Color manipulation: Extracting RGB components from color values.
- Performance optimization: Faster calculations for certain operations.
Example: Using Bitwise Operators for Flags
package main
import "fmt"
const (
READ = 1 << 0 // 001 in binary
WRITE = 1 << 1 // 010 in binary
EXECUTE = 1 << 2 // 100 in binary
)
func main() {
// Create permission
var permission byte = READ | WRITE // 011 in binary
// Check permissions
fmt.Printf("Permission: %08b", permission)
fmt.Printf("Has READ: %v", (permission & READ) != 0)
fmt.Printf("Has WRITE: %v", (permission & WRITE) != 0)
fmt.Printf("Has EXECUTE: %v", (permission & EXECUTE) != 0)
// Add execute permission
permission = permission | EXECUTE
fmt.Printf("After adding EXECUTE: %08b", permission)
// Remove write permission
permission = permission &^ WRITE
fmt.Printf("After removing WRITE: %08b", permission)
}
Output:
Permission: 00000011
Has READ: true
Has WRITE: true
Has EXECUTE: false
After adding EXECUTE: 00000111
After removing WRITE: 00000101
Assignment Operators
Assignment operators are used to assign values to variables.
Operator | Description | Example | Equivalent to |
---|---|---|---|
= | Simple assignment | a = b | a = b |
+= | Add and assign | a += b | a = a + b |
-= | Subtract and assign | a -= b | a = a - b |
*= | Multiply and assign | a *= b | a = a * b |
/= | Divide and assign | a /= b | a = a / b |
%= | Modulus and assign | a %= b | a = a % b |
<<= | Left shift and assign | a <<= b | a = a << b |
>>= | Right shift and assign | a >>= b | a = a >> b |
&= | Bitwise AND and assign | a &= b | a = a & b |
^= | Bitwise XOR and assign | a ^= b | a = a ^ b |
|= | Bitwise OR and assign | a |= b | a = a | b |
Example: Assignment Operators
package main
import "fmt"
func main() {
a := 10
// Simple assignment
b := a
fmt.Printf("b = a: %d", b)
// Add and assign
a += 5
fmt.Printf("a += 5: %d", a)
// Subtract and assign
a -= 3
fmt.Printf("a -= 3: %d", a)
// Multiply and assign
a *= 2
fmt.Printf("a *= 2: %d", a)
// Divide and assign
a /= 4
fmt.Printf("a /= 4: %d", a)
// Modulus and assign
a %= 2
fmt.Printf("a %%= 2: %d", a)
}
Output:
b = a: 10
a += 5: 15
a -= 3: 12
a *= 2: 24
a /= 4: 6
a %= 2: 0
Miscellaneous Operators
Go also provides a few other operators that don't fit into the categories above.
Operator | Description | Example |
---|---|---|
& | Address operator (returns the memory address) | &a |
* | Pointer operator (dereferences a pointer) | *a |
<- | Channel receive operator | x <- ch |
Example: Address and Pointer Operators
package main
import "fmt"
func main() {
a := 10
// Get the memory address of a
ptr := &a
fmt.Printf("Address of a: %p", ptr)
// Access the value using the pointer
fmt.Printf("Value at address %p: %d", ptr, *ptr)
// Modify the value using the pointer
*ptr = 20
fmt.Printf("After modification, a = %d", a)
}
Output:
Address of a: 0xc000018030
Value at address 0xc000018030: 10
After modification, a = 20
Operator Precedence
Operators in Go follow a specific precedence order, which determines the order of evaluation in expressions.
Precedence | Operators |
---|---|
5 (highest) | * , / , % , << , >> , & , &^ |
4 | + , - , | , ^ |
3 | == , != , < , <= , > , >= |
2 | && |
1 (lowest) | || |
Example: Operator Precedence
package main
import "fmt"
func main() {
// Expression: 10 + 5 * 2
result1 := 10 + 5*2
// Multiplication (*) has higher precedence than addition (+)
// So it's evaluated as: 10 + (5 * 2) = 10 + 10 = 20
fmt.Printf("10 + 5 * 2 = %d", result1)
// Using parentheses to change precedence
result2 := (10 + 5) * 2
// Now it's evaluated as: (10 + 5) * 2 = 15 * 2 = 30
fmt.Printf("(10 + 5) * 2 = %d", result2)
// Complex expression
result3 := 5 + 10*2 - 5/2 > 10 && 6%3 == 0
fmt.Printf("5 + 10*2 - 5/2 > 10 && 6%%3 == 0 = %t", result3)
}
Output:
10 + 5 * 2 = 20
(10 + 5) * 2 = 30
5 + 10*2 - 5/2 > 10 && 6%3 == 0 = true
Real-World Examples
Example 1: Calculating Sales Tax
package main
import "fmt"
func main() {
// Calculate sales tax on a purchase
itemPrice := 49.99
taxRate := 0.07 // 7%
taxAmount := itemPrice * taxRate
totalPrice := itemPrice + taxAmount
fmt.Printf("Item price: $%.2f", itemPrice)
fmt.Printf("Tax rate: %.0f%%", taxRate*100)
fmt.Printf("Tax amount: $%.2f", taxAmount)
fmt.Printf("Total price: $%.2f", totalPrice)
}
Output:
Item price: $49.99
Tax rate: 7%
Tax amount: $3.50
Total price: $53.49
Example 2: Temperature Conversion
package main
import "fmt"
func main() {
// Convert between Celsius and Fahrenheit
celsius := 25.0
fahrenheit := (celsius * 9/5) + 32
fmt.Printf("%.1f°C = %.1f°F", celsius, fahrenheit)
// Convert back to Celsius
newCelsius := (fahrenheit - 32) * 5/9
fmt.Printf("%.1f°F = %.1f°C", fahrenheit, newCelsius)
}
Output:
25.0°C = 77.0°F
77.0°F = 25.0°C
Example 3: Bit Manipulation for RGB Colors
package main
import "fmt"
func main() {
// Store RGB color in a single integer (0xRRGGBB)
// Red: 255 (0xFF), Green: 128 (0x80), Blue: 64 (0x40)
rgb := (255 << 16) | (128 << 8) | 64
fmt.Printf("RGB Color: 0x%06X", rgb)
// Extract individual components
red := (rgb >> 16) & 0xFF
green := (rgb >> 8) & 0xFF
blue := rgb & 0xFF
fmt.Printf("Red: %d (0x%02X)", red, red)
fmt.Printf("Green: %d (0x%02X)", green, green)
fmt.Printf("Blue: %d (0x%02X)", blue, blue)
// Modify just the green component
newGreen := 200
rgb = (rgb & 0xFF00FF) | (newGreen << 8)
fmt.Printf("New RGB Color: 0x%06X", rgb)
}
Output:
RGB Color: 0xFF8040
Red: 255 (0xFF)
Green: 128 (0x80)
Blue: 64 (0x40)
New RGB Color: 0xFFC840
Common Mistakes and Best Practices
Pitfall 1: Integer Division
One common mistake is forgetting that division between integers in Go results in an integer.
package main
import "fmt"
func main() {
// This will truncate the decimal part
result := 5 / 2
fmt.Println("5 / 2 =", result) // Outputs: 2
// To get a floating-point result, at least one operand must be a float
correctResult := 5.0 / 2
fmt.Println("5.0 / 2 =", correctResult) // Outputs: 2.5
}
Pitfall 2: Pre/Post Increment/Decrement
Go only has post-increment and post-decrement, not pre-increment or pre-decrement.
package main
import "fmt"
func main() {
a := 5
// This works
a++
fmt.Println("After a++:", a)
// This doesn't work in Go
// ++a // Syntax error: unexpected ++, expecting expression
// Also, increment and decrement are statements, not expressions
// b := a++ // Error: a++ used as value
}
Pitfall 3: Short-Circuit Evaluation Side Effects
Be careful when relying on short-circuit evaluation for side effects.
package main
import "fmt"
func main() {
x := 5
y := 10
// This condition modifies x only if y > 5
if y <= 5 || (x = x + 5) > 0 {
fmt.Println("Condition met")
}
// x might not be modified due to short-circuit evaluation
fmt.Println("x =", x)
}
Operator Cheat Sheet
Type | Operators | Description |
---|---|---|
Arithmetic | + | Addition |
- | Subtraction | |
* | Multiplication | |
/ | Division | |
% | Modulus (remainder) | |
++ | Increment | |
-- | Decrement | |
Comparison | == | Equal to |
!= | Not equal to | |
< | Less than | |
> | Greater than | |
<= | Less than or equal to | |
>= | Greater than or equal to | |
Logical | && | Logical AND |
|| | Logical OR | |
! | Logical NOT | |
Bitwise | & | Bitwise AND |
| | Bitwise OR | |
^ | Bitwise XOR | |
&^ | Bit clear (AND NOT) | |
<< | Left shift | |
>> | Right shift | |
Assignment | = | Simple assignment |
+= | Add and assign | |
-= | Subtract and assign | |
*= | Multiply and assign | |
/= | Divide and assign | |
%= | Modulus and assign | |
<<= | Left shift and assign | |
>>= | Right shift and assign | |
&= | Bitwise AND and assign | |
^= | Bitwise XOR and assign | |
|= | Bitwise OR and assign | |
Miscellaneous | & | Address operator |
* | Pointer operator | |
<- | Channel receive/send |
Summary
In this tutorial, we explored the various operators in Go:
- Arithmetic operators perform mathematical operations like addition, subtraction, multiplication, and division.
- Comparison operators compare values and return boolean results.
- Logical operators combine conditional statements.
- Bitwise operators manipulate the binary representations of numbers.
- Assignment operators assign values to variables, sometimes performing operations first.
- Miscellaneous operators include address, pointer, and channel operations.
We also learned about operator precedence, which determines the order of evaluation in expressions, and explored real-world applications of Go operators.
Understanding operators is fundamental to writing effective Go code, as they form the building blocks of expressions and statements. By mastering operators, you'll be able to write more concise, efficient, and powerful Go programs.
Exercises
To solidify your understanding of Go operators, try these exercises:
-
Write a program that takes two integers as input and displays the results of all arithmetic operations on them.
-
Create a function that converts a temperature from Celsius to Fahrenheit and vice versa using the formula:
F = (C × 9/5) + 32
. -
Write a program that calculates the total price of items in a shopping cart, including sales tax.
-
Create a bitmap using bitwise operators to represent a set of permissions (read, write, execute) and write functions to set, clear, and check permissions.
-
Write a program that uses bitwise operations to pack three single-digit numbers into a single integer and then extract them.
Additional Resources
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)