BudiBadu Logo

Samplebadu

Code with Example
BudiBadu Logo
Samplebadu

Go by Example: Zero Values

Go 1.23

In Go, variables declared without an initial value are given their "zero value". This example explains what these values are for different types and demonstrates the "Make the zero value useful" proverb with structs like sync.Mutex.

Code

package main

import (
    "bytes"
    "fmt"
    "sync"
)

func main() {
    // 1. Basic Types
    // Variables declared without initialization get a default "zero value".
    var i int
    var f float64
    var b bool
    var s string
    
    // Prints: 0, 0, false, "" (empty string)
    fmt.Printf("int: %d, float: %f, bool: %t, string: %q\n", i, f, b, s)

    // 2. Pointers and Reference Types
    // The zero value is 'nil' for pointers, slices, maps, channels, interfaces, and functions.
    var ptr *int
    var slc []int
    var mp map[string]int
    
    fmt.Println("pointer is nil:", ptr == nil)
    fmt.Println("slice is nil:", slc == nil)
    fmt.Println("map is nil:", mp == nil)

    // 3. "Make the zero value useful"
    // Many Go types are designed to be used without explicit initialization.
    
    // Example A: sync.Mutex
    // A zero-value Mutex is an unlocked mutex. You don't need "NewMutex()".
    var mu sync.Mutex
    mu.Lock()
    fmt.Println("Mutex locked successfully")
    mu.Unlock()

    // Example B: bytes.Buffer
    // A zero-value Buffer is an empty buffer ready to write to.
    var buf bytes.Buffer
    buf.WriteString("Hello, Zero Value!")
    fmt.Println(buf.String())
    
    // Example C: Slices
    // A nil slice is functionally equivalent to an empty slice for most operations.
    // You can append to it without 'make'.
    var names []string
    names = append(names, "Alice")
    fmt.Println("Appended to nil slice:", names)
}

Explanation

In many languages, uninitialized variables contain random garbage data, leading to unpredictable bugs. Go solves this by guaranteeing that every variable declared without an explicit value is initialized to its zero value. This provides safety and determinism.

The zero values are: 0 for numeric types, false for booleans, "" (empty string) for strings, and nil for pointers, slices, maps, channels, functions, and interfaces. For structs, the zero value is a struct where every field is set to its respective zero value.

A famous Go proverb is "Make the zero value useful." This means designing your types so that they can be used immediately after declaration, without needing a constructor or initialization method. The standard library is full of examples: sync.Mutex is ready to lock, bytes.Buffer is ready to write, and a nil slice is ready to be appended to.

  • Safety: No uninitialized memory access.
  • Convenience: Reduces boilerplate (no need for Init() calls).
  • Nil Slices: Can be used with append, len, and cap safely.
  • Nil Maps: CAUTION: You can read from a nil map, but writing to it causes a panic.

Code Breakdown

12-15
Declaring variables without values. Go automatically assigns them 0, 0.0, false, and "" respectively. This behavior is guaranteed by the language spec.
35
Demonstrating a useful zero value. We declare 'mu' of type sync.Mutex and immediately call Lock(). We didn't need to call a constructor like 'NewMutex()'. The zero state (all fields 0) represents an unlocked mutex.
42
Similarly, bytes.Buffer is ready to use immediately. Its zero value represents an empty buffer. This pattern simplifies code significantly as you don't need to manage initialization state.
49-50
The 'nil' slice is a powerful feature. Even though 'names' is nil, 'append' handles it correctly by allocating a new underlying array. This avoids the need to check 'if slice == nil' before appending.