What is a zero value? What zero values do the basic types have?
Zero value is the default value that Go automatically assigns to a variable when no initial value is specified at the time of its creation.
var count int
var name string
var active bool
fmt.Println(count) // 0
fmt.Println(name) // ""
fmt.Println(active) // falseIn Go, a variable always contains a valid value of its type. There are no uninitialized variables containing random data from memory.
Zero Values of the Main Types
| Type | Zero value |
|---|---|
bool | false |
int, uint, and other integer types | 0 |
float32, float64 | 0.0 |
complex64, complex128 | 0 + 0i |
string | "" |
pointer *T | nil |
slice []T | nil |
map map[K]V | nil |
channel chan T | nil |
function func | nil |
| interface | nil |
array [N]T | an array containing the zero values of type T |
| struct | a struct in which every field contains its own zero value |
These values are defined by the Go specification.
Example
type User struct {
Name string
Age int
Active bool
Tags []string
}
var user User
fmt.Println(user.Name) // ""
fmt.Println(user.Age) // 0
fmt.Println(user.Active) // false
fmt.Println(user.Tags) // []
fmt.Println(user.Tags == nil) // trueEvery field of a struct receives the zero value of its type.
Special Characteristics of Reference-Like Types
Slice
The zero value of a slice is nil. Its length and capacity are both zero, but range and append can still be used safely with it.
var numbers []int
fmt.Println(numbers == nil) // true
fmt.Println(len(numbers)) // 0
numbers = append(numbers, 10)
fmt.Println(numbers) // [10]A nil slice and an initialized empty slice are not the same:
var first []int
second := []int{}
fmt.Println(first == nil) // true
fmt.Println(second == nil) // falseHowever, both have a length of 0.
Map
The zero value of a map is nil.
Reading from a nil map is safe:
var users map[string]int
fmt.Println(users["Alice"]) // 0If the key does not exist, Go returns the zero value of the map’s value type:
age, exists := users["Alice"]
fmt.Println(age) // 0
fmt.Println(exists) // falseHowever, writing to a nil map causes a panic:
var users map[string]int
// users["Alice"] = 30 // panicThe map must be initialized before writing to it:
users = make(map[string]int)
users["Alice"] = 30Pointer
The zero value of a pointer is nil.
var pointer *int
fmt.Println(pointer == nil) // trueDereferencing a nil pointer causes a panic:
// fmt.Println(*pointer) // panicChannel
The zero value of a channel is nil.
var ch chan intSending data to or receiving data from a nil channel blocks forever because the channel is not ready to transfer data:
// ch <- 10
// value := <-chA usable channel is created with make:
ch := make(chan int)Function
The zero value of a function is nil.
var handler func()
fmt.Println(handler == nil) // trueCalling a nil function causes a panic:
// handler() // panicInterface
The zero value of an interface is nil.
var err error
fmt.Println(err == nil) // trueAn interface is equal to nil only when it contains neither a concrete type nor a value.
var pointer *MyError = nil
var err error = pointer
fmt.Println(err == nil) // falseIn this example, the interface contains the concrete type *MyError, so the interface itself is not equal to nil.
Arrays and Structs
In an array, every element receives the zero value of its type:
var numbers [3]int
var names [2]string
fmt.Println(numbers) // [0 0 0]
fmt.Println(names) // ["" ""]In a struct, every field receives its own zero value:
type Config struct {
Port int
Address string
Enabled bool
}
var config Config
// Config{
// Port: 0,
// Address: "",
// Enabled: false,
// }Conclusion
A zero value is the automatically assigned initial value of a type.
The main rules are:
bool → false
numbers → 0
string → ""
*T → nil
[]T → nil
map[K]V → nil
chan T → nil
func → nil
interface → nil
array → zero value of each element
struct → zero value of each field