Understanding Basic Types in Go: A Comprehensive Guide
Intro
Go provides a rich set of basic types that form the foundation of its type system. Let's explore each category in detail with practical examples.
Numeric Types
Integers
Go offers both signed and unsigned integers of various sizes:
// Signed integers
var (
num8 int8 = 127 // -128 to 127
num16 int16 = 32767 // -32768 to 32767
num32 int32 = 2147483647 // -2147483648 to 2147483647
num64 int64 = 9223372036854775807
)
// Unsigned integers
var (
unum8 uint8 = 255 // 0 to 255
unum16 uint16 = 65535 // 0 to 65535
unum32 uint32 = 4294967295 // 0 to 4294967295
unum64 uint64 = 18446744073709551615
)
// Architecture-dependent types
var (
num int = 42 // 32 or 64 bits depending on system
unum uint = 42 // 32 or 64 bits depending on system
)
Floating-Point Numbers
Go provides two floating-point types:
// Float types
var (
f32 float32 = 3.14159265359 // Approximately 6 decimal digits of precision
f64 float64 = 3.14159265359 // Approximately 15 decimal digits of precision
)
// Scientific notation
var (
avogadro float64 = 6.02214e23
plancksConst float64 = 6.62607015e-34
)
Complex Numbers
Go has built-in support for complex numbers:
var (
c64 complex64 = 3 + 4i // Complex number with float32 real and imaginary parts
c128 complex128 = 5 + 7i // Complex number with float64 real and imaginary parts
)
// Working with complex numbers
func complexDemo() {
z := complex(3, 4) // Creating a complex number
fmt.Printf("z = %v\n", z)
fmt.Printf("Real part: %f\n", real(z))
fmt.Printf("Imaginary part: %f\n", imag(z))
fmt.Printf("Complex conjugate: %v\n", cmplx.Conj(z))
}
Text Types
Strings
Strings in Go are immutable sequences of bytes:
var (
name string = "Hello, 世界" // UTF-8 encoded string
rawStr string = `This is a
raw string literal
that preserves line breaks`
)
func stringDemo() {
// String operations
str := "Hello, World!"
fmt.Printf("Length: %d\n", len(str))
fmt.Printf("Character at index 0: %c\n", str[0])
fmt.Printf("Substring: %s\n", str[0:5])
// String concatenation
first := "Hello"
second := "World"
combined := first + " " + second
fmt.Println(combined)
}
Runes
Runes represent Unicode code points:
func runeDemo() {
// Rune literal
var r rune = '世'
fmt.Printf("Rune: %c, Unicode: %U, Value: %d\n", r, r, r)
// Iterating over string runes
str := "Hello, 世界"
for i, r := range str {
fmt.Printf("Position %d: %c\n", i, r)
}
}
Boolean Type
Go's boolean type can be either true
or false
:
func booleanDemo() {
var (
isActive bool = true
isValid bool = false
)
// Boolean operators
fmt.Printf("AND: %v\n", isActive && isValid)
fmt.Printf("OR: %v\n", isActive || isValid)
fmt.Printf("NOT: %v\n", !isActive)
// Conditional statements
if isActive {
fmt.Println("Active")
}
}
Zero Values
Every type in Go has a zero value. Variables declared without an explicit initial value are set to their zero value:
func zeroValues() {
var (
i int
f float64
b bool
s string
r rune
)
fmt.Printf("Integer zero value: %d\n", i) // 0
fmt.Printf("Float zero value: %f\n", f) // 0.0
fmt.Printf("Boolean zero value: %v\n", b) // false
fmt.Printf("String zero value: %q\n", s) // ""
fmt.Printf("Rune zero value: %d\n", r) // 0
}
Type Conversions
Go requires explicit type conversions between different types:
func typeConversions() {
// Numeric conversions
var i int32 = 100
var j int64 = int64(i)
var f float64 = float64(i)
// String conversions
var num int = 42
str := strconv.Itoa(num) // Integer to string
num2, err := strconv.Atoi(str) // String to integer
// Float to string with precision
pi := 3.14159
piStr := fmt.Sprintf("%.2f", pi)
fmt.Printf("j: %d, f: %f, str: %s, num2: %d, piStr: %s\n",
j, f, str, num2, piStr)
}
Type Inference
Go can infer types using the short declaration syntax:
func typeInference() {
// Type inference using :=
name := "John" // string
age := 25 // int
height := 1.75 // float64
isStudent := true // bool
fmt.Printf("Types - name: %T, age: %T, height: %T, isStudent: %T\n",
name, age, height, isStudent)
}
Best Practices
Use the most appropriate type for your needs:
int
for general integer valuesfloat64
for floating-point calculationsstring
for textrune
for Unicode characters
Consider memory usage when choosing numeric types:
Use smaller integer types when you know the value range
Use
float32
only when memory is critical; preferfloat64
Be careful with floating-point comparisons:
func floatingPointComparison() {
a := 0.1
b := 0.2
c := 0.3
fmt.Printf("%.20f + %.20f = %.20f\n", a, b, a+b)
fmt.Printf("%.20f = %.20f is %v\n", a+b, c, a+b == c)
// Better comparison using tolerance
tolerance := 0.0000001
diff := math.Abs((a + b) - c)
fmt.Printf("Equal within tolerance: %v\n", diff < tolerance)
}
This overview covers the fundamental types in Go. Each type has its specific use cases and characteristics, and understanding them well is crucial for writing effective Go programs.
Subscribe to my newsletter
Read articles from Enock Omondi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Enock Omondi
Enock Omondi
Software Engineer