04 Operators and Typecasting
- Arithmetic Operators
- Comparision Operators
- Logtical Operators
- Bitwise Operators
- Typecasting
1. Arithmetic Operators
Arithmetic operations in Go (Golang) are the basic mathematical operations you can perform on numbers. These include addition, subtraction, multiplication, division, and modulus (like most languages).
//Be careful about (:= or =) assignment operations
a := 10
b := 5
sum := a + b // sum is 15
diff := a - b // diff is 5
product := a * b // product is 50
//integer division
a := 10
b := 3
quotient := a / b // quotient is 3 (integer division)
//float division
x := 10.0
y := 3.0
floatQuotient := x / y // floatQuotient is 3.3333333 (float division)
//Modulus (remainder) operation
a := 10
b := 3
remainder := a % b // remainder is 1
package main
import "fmt"
func main() {
a := 15
b := 4
fmt.Println("Addition:", a+b) // 19
fmt.Println("Subtraction:", a-b) // 11
fmt.Println("Multiplication:", a*b) // 60
fmt.Println("Division:", a/b) // 3 (integer division)
fmt.Println("Modulus:", a%b) // 3
// For floating point division:
x := 15.0
y := 4.0
fmt.Println("Float Division:", x/y) // 3.75
}
2. Comparision Operators
Comparison operators in Go are used to compare two values and return a Boolean result (true or false). These operators are commonly used in conditions such as if statements or loops.
////Be careful about (:= or =) assignment operations
a := 5
b := 5
fmt.Println(a == b) // true
a := 5
b := 3
fmt.Println(a != b) // true
a := 7
b := 5
fmt.Println(a > b) // true
a := 7
b := 10
fmt.Println(a < b) // true
a := 7
b := 7
fmt.Println(a >= b) // true
a := 7
b := 7
fmt.Println(a <= b) // true
3. Logical operators
Logical operators in Go let you combine or invert Boolean expressions (true or false).
Operator | Name | Description |
---|---|---|
&& |
Logical AND | True if both operands are true |
|| |
Logical OR | True if atleast ONE operand is true |
! |
Logical NOT | Inverts the Boolean value |
An example
//Be careful about (:= or =) assignment operations
package main
import "fmt"
func main() {
a := true
b := false
fmt.Println("a && b:", a && b) // false
fmt.Println("a || b:", a || b) // true
fmt.Println("!a:", !a) // false
}
4. Bitwise operators
- Bitwise operators in Go allow you to perform operations directly on the binary representation of integers.
- These are very useful in systems programming, hardware control, flags, and performance-critical code.
Do not confuse with logical operators
- logical operators (&&, ||, !) operate on boolean data, wherease bitwise operators (&, | ) operate on bits
Operator | Name | Description |
---|---|---|
& |
AND | 1 if both bits are 1 \ |
| |
OR | |
^ |
XOR (binary) | 1 if bits are different |
^ |
NOT (unary) | Inverts all bits |
&^ |
AND NOT (bit clear) | Clears bits set in second operand |
<< |
Left Shift | Shifts bits to the left |
>> |
Right Shift | Shifts bits to the right |
An example
package main
import "fmt"
func main() {
a := 10 // binary: 00001010
b := 6 // binary: 00000110
fmt.Println("a & b:", a&b) // 2 -> 00001010 & 00000110 = 00000010 // Bitwise AND
fmt.Println("a | b:", a|b) // 14 -> 00001010 | 00000110 = 00001110 // Bitwise OR
fmt.Println("a ^ b:", a^b) // 12 -> 00001010 ^ 00000110 = 00001100 // Bitwise XOR
fmt.Println("^a :", ^a) // -11 -> ^00001010 = 11110101 // Bitwise NOT (inversion)
fmt.Println("a &^ b:", a&^b) // 8 -> 00001010 &^ 00000110 = 00001000 // Bit Clear (AND NOT)
fmt.Println("a << 1:", a<<1) // 20 -> 00001010 << 1 = 00010100 // Left Shift (×2)
fmt.Println("a >> 1:", a>>1) // 5 -> 00001010 >> 1 = 00000101 // Right Shift (÷2)
}
5. Typecasting (type conversion)
Typecasting (more properly called type conversion in Go) is the process of converting a value of one data type into another. This is useful when you want to assign a value from one type to a variable of a different type or perform operations that require matching types.
Implicit typecasting
Implicit typecasting (also called implicit conversion) is when a programming language automatically converts a value from one data type to another without you having to write extra code.
var a int = 42 // int literal 42 implicitly converted to int
var b float64 = 42 // int literal 42 implicitly converted to float64
var c byte = 42 // int literal 42 implicitly converted to byte
var x float32 = 3.14 // floating-point literal implicitly converted to float32
var y float64 = 3.14 // floating-point literal implicitly converted to float64
let x = 5; // integer
let y = 3.14;
#IMPORTANT
let z = x + y; // implicit conversion of x (int) to float for addition
Explicity typecasting
Explicit typecasting (or explicit type conversion) is when the programmer manually converts a value from one type to another by specifying the target type in the code.
syntax T(value)
Some pitfalls of typecasting
Here are some common pitfalls of explicit typecasting
-
Loss of Data: Converting from a larger or more precise type to a smaller or less precise type (e.g., float64 to int) truncates or loses information. Example: int(3.99) becomes 3, decimal part lost.
-
Overflow / Underflow: Converting a value that doesn't fit into the target type’s range can cause unexpected results. Example: Casting int(300) to byte results in overflow because byte is 0–255.
-
Silent Errors: Typecasting won’t raise errors or warnings when data loss or overflow occurs; it just happens silently.
-
Unexpected Sign Changes: Casting between signed and unsigned types can change the sign and produce surprising results.
-
Performance Overhead: Although generally small, unnecessary or excessive conversions can add performance cost.
-
Code Readability: Excessive explicit casting can make code harder to read and understand.
Finding type of a variable
In Go, there are two common ways to check or print the type of a variable:
- reflect.TypeOf(x)
- fmt.Printf("%T", x)
"reflect" pacakge
What is reflect package
The reflect package in Go provides runtime reflection, which means it allows a program to inspect and manipulate values, types, and even structures at runtime, even if you don’t know their exact types when writing the code.
Type Inference
package main
import (
"fmt"
"reflect"
)
const pi = 3.14
func main() {
var a float32 = pi
fmt.Println("Type of a (after assigning pi):", reflect.TypeOf(a)) // float32
var b float64 = pi
fmt.Println("Type of b (after assigning pi):", reflect.TypeOf(b)) // float64
var c complex128 = pi
fmt.Println("Type of c (after assigning pi):", reflect.TypeOf(c)) // complex128
}
package main
import "fmt"
const pi = 3.14
func main() {
var a float32 = pi
fmt.Printf("Type of a (after assigning pi): %T\n", a) // float32
var b float64 = pi
fmt.Printf("Type of b (after assigning pi): %T\n", b) // float64
var c complex128 = pi
fmt.Printf("Type of c (after assigning pi): %T\n", c) // complex128
}