

Nillability and zero-values in go
source link: https://nilsmagnus.github.io/post/nillability-in-go/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Nillability and zero-values in go
November 06, 2018Beeing a long time java-developer, I am obsessed with null-checking and handling null values.
In golang, the story is somewhat different. In this post I will try to describe how nil
and zero-values
are used in golang.
non-nillable and nillable types
Types can be either nillable or non-nillable in go. The non-nillable types can never be nil
and will never cause you a nil-panic
(the java equivalent of nullpointerexception) But when
are dealing with the nillable types, we have to take a bit of caution although not as
much as in java(or other languages with nillable types).
The non-nillables basic types
In go, the basic types are not nillable. A statement like
var a int = nil
does not compile because an int
can never be nil. The default value of an unassigned int
type is 0.
Running the statement
var a int // default value of int, cannot be nil
fmt.Println(a) // 0
will output the default value of int
; “0
”. We call this the zero-value of the type.
The same way int
defaults to 0, these are the other basic types with their zero-values:
Types Zero value
int, int8, int16, int32, int64 0
uint, uint8, uint16, uint32, uint64 0
uintptr 0
float32, float64 0.0
byte 0
rune 0
string "” (empty string)
complex64, complex128 (0,0i)
arrays of non-nillable types array of zero-values
arrays of nillable types array of nil-values
Non-nillable structs
Composed struct
types are also non-nillable, and the default value of a struct will contain
the default value for all its fields.
Consider the code with the struct type Person,
type Person struct {
Name string
Age int
}
var p Person // zero-value of type Person
fmt.Printf("[%#v]\n", p)
will print [main.Person{Name:"", Age:0}]
when run in main. You can test this on this snippet on The Go Playground.
The nillable types
More advanced types are nillable and can cause panic if they are not initialized.
The nillable types are functions, channels, slices, maps, interface-types and pointers.
However, nil-slices and nil-maps can still be used and does not have to be initialized before we start using them.
nil-maps
Maps will always return the zero-value of the value if it is nil, the same behaviour as if the key of the map is non-existent. The code
var p map[int]string // nil map
fmt.Printf(" %#v length %d \n", p[99], len(p))
simply prints "" length 0
, the extracted value for key 99 is the zero value of string
.
Assigning values to a nil-map, will however cause panic:
var p map[string]int // nil map
p["nils"] = 19 // panic: assignment to entry in nil map
nil-slices
Refering to out-of-bounds on slices will cause panic, but operations like len()
and cap()
will not panic. They will simply return 0
, since both capacity and length is zero
for an uninitialized slice. Append can be safely called on the nil-slice. So the code
var p []string // nil slice
fmt.Printf("uninitialized -> %d, %d\n", len(p), cap(p))
p1 := append(p, "nils") // create a new slice p1 from p
fmt.Printf("after append -> %d, %d %#v\n", len(p1), cap(p1), p1)
Will print
uninitialized -> 0, 0
after append -> 1, 1 []string{"nils"}
Play with this example on the playground.
nillable pointers, functions and interface-types can cause panic
Pointers and interface-types are however nillable. Whenever dealing with these types, we have to consider if they are nil or not to avoid panics. These code-snippets for instance, will cause a panic:
var p *int // pointer to an int
*p++ // panic: runtime error: invalid memory address or nil pointer dereference
// p is an address to nothing, and therefore is nil
var p error // nil-value of type error
error.Error() // panic: runtime error: invalid memory address or nil pointer dereference
var f func(string) // nil-function
f("oh oh") // panic: runtime error: invalid memory address or nil pointer dereference
nil channels blocks forever
Trying to read from a nil-channel or write to a nil-channel will block forever. Closing a nil-channel will cause panic.
Wrapup
nil
is well defined in go. Knowing what can be nil and how to handle nil values of the different
types increases your understanding of whats happening and can help you write better go-code.
Recommend
-
71
As you might’ve noticed from other blog post entries I’m suddenly all intodirectory services. This happens b/c that’s what I’m currently working on...
-
10
Hi, it’s Wojtek bringing you the latest changes summary from Ruby on Rails codebase. Add values_at method to Active Record S...
-
7
Function types and values yourbasic.org/golang Function types and function values can be used and passed around just like other values: type Operator func(x float64) float64 // Map applies op to...
-
15
Get slices of keys and values from a map · YourBasic GoGet slices of keys and values from a map yourbasic.org/golang You can use a range statement to extract slices of keys and values from a
-
10
Default zero values for all Go types yourbasic.org/golang Variables declared without an initial value are set to t...
-
6
ES proposal: Object.entries() and Object.values() Dec 19, 2016 • Yehonathan Sharvit This article is an interactive version of
-
8
Generating time_t values without touching mktime and TZ Back in March, I wrote that "time handling is garbage", specifically referring to the hoop-jumping which is require...
-
9
Blank Zero Values in .NET Number Format Strings ...
-
5
Technical Articles
-
10
Pandas | Count non-zero values in Dataframe Column This article will discuss how to count the number of non-zero values in one or more Dataframe columns in Pandas. Let’s first create a Dataframe from a...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK