Go's Zero Value and Practical Examples

Introduction

Go has a concept called “Zero Value”, which means all variables are automatically initialized to their type’s zero value when declared. Below are examples for various types:

var i int // 0
var f float64 // 0.0
var b bool // false
var s string // ""
var p *int // nil
var s []int
s = append(s, 1, 2, 3) // nil slice append is legal because it will allocate the underlying array automatically
var m map[string]int
m["key"] = 1 // panic!nil map cannot be written to; maps must be initialized with make

Compared to C where reading an uninitialized variable can cause security vulnerabilities or crashes, or dynamic languages like JavaScript, Go automatically assigns well-defined values to avoid errors and let values be usable immediately after creation. Specifically, tags used in JSON reflection such as omitempty leverage the Zero Value concept to decide whether to omit fields:

type Response struct {
ID int `json:"id"`
Message string `json:"message,omitempty"` // omitted when empty string
Error string `json:"error,omitempty"` // omitted when empty string
}

The reflect package provides IsZero() to check for zero values:

import "reflect"
func isZeroValue(v any) bool {
return reflect.ValueOf(v).IsZero()
}
fmt.Println(isZeroValue(0)) // true
fmt.Println(isZeroValue("")) // true
fmt.Println(isZeroValue(false)) // true
fmt.Println(isZeroValue(42)) // false
fmt.Println(isZeroValue("hello")) // false

Practical optional-value issue

For example, the following request definition cannot distinguish between the states “false” and “not provided”:

type ConfigRequest struct {
IsEnabled bool `json:"isEnabled"`
}

This means {"isEnabled": false} and {} are equivalent, and omitting the field may unintentionally set isEnabled to its Zero Value.

One approach is to use *bool to represent an absent value; if the field is not present it will be nil, and you can explicitly check and apply the provided value:

type ConfigRequest struct {
IsEnabled *bool `json:"isEnabled"`
}
if req.IsEnabled != nil {
config.IsEnabled = *req.IsEnabled
}

Further reading