This article describes a few methods for determining whether a struct in Go is empty. It includes structs having fields that are comparable and non-comparable. Keep in mind that in Go, an empty structure is one whose fields are all initialized with zero values.
Method 1: Compare to the zero value composite literal
In most circumstances, checking in Go for an empty struct is simple. We can use the operator == to its zero value composite literal. The use of == above applies to structs where all fields are comparable. It is necessary to compare each field to its zero value if the struct contains a non-comparable field (slice, map, or function).
In the if
statement, parentheses are required around the composite due to a parsing ambiguity.
package main
import (
"fmt"
)
type Book struct {
Name string
Author string
}
func main() {
var book1 Book
book2 := Book{
Name: "John John",
Author: "Author1",
}
fmt.Println("Book1 is empty?: ", book1 == Book{}) // true
fmt.Println("Book2 is empty?: ", book2 == Book{}) // false
}
Output:
Book1 is empty?: true
Book2 is empty?: false
Method 2: Compare the struct pointer to the nil
In the previous chapter, we already know that the zero value of a pointer is nil. So to check if a pointer of a struct is zero or not, we can compare it to nil
or to the zero value composite literal. The example below shows how we can do that in Golang:
package main
import "fmt"
type Book struct {
Name string
Author string
}
func main() {
var book1 *Book
book2 := &Book{}
book3 := &Book{Name: "Book1", Author: "author1"}
// compare to nil
if book1 == nil {
fmt.Println("Book1 is empty")
} else {
fmt.Println("Book1 is not empty")
}
// compare to composite literal
if *book2 == (Book{}) {
fmt.Println("Book2 is empty")
} else {
fmt.Println("Book2 is not empty")
}
if *book3 == (Book{}) {
fmt.Println("Book3 is empty")
} else {
fmt.Println("Book3 is not empty")
}
}
Output:
Book1 is empty
Book2 is empty
Book3 is not empty
Method 3: Using the reflect.DeepEqual() function
The preceding method will not work if the structure is a slice, map, or function, or if it has a non-comparable field. However, you can use the reflect package with the reflect.DeepEqual()
function instead as illustrated below:
package main
import (
"fmt"
"reflect"
)
type Book struct {
Name string
Author string
Version []string
}
func main() {
var book1 Book
book2 := Book{
Name: "John John",
Author: "Author1",
Version: []string{"V1.0", "V1.1"},
}
// error because can not use == for Version field
// fmt.Println("Book1 is empty?: ", book1 == Book{})
// fmt.Println("Book2 is empty?: ", book2 == Book{})
fmt.Println("Book1 is empty?: ", reflect.DeepEqual(book1, Book{}))
fmt.Println("Book2 is empty?: ", reflect.DeepEqual(book2, Book{}))
}
Output:
Book1 is empty?: true
Book2 is empty?: false
Note that if we use the ==
operator, the system will prompt the message "invalid operation: book1 == Book{} (struct containing []string cannot be compared"
Method 4: Using the isZero() function
With Go 1.13 it is possible to use the new isZero()
function:
func (v Value) IsZero() bool
: IsZero reports whether v is the zero value for its type. It panics if the argument is invalid.
The example below illustrates how we can use the isZero()
function to determine if the struct is empty or not:
package main
import (
"fmt"
"reflect"
)
type Book struct {
Name string
Author string
Version []string
}
func main() {
var book1 Book
book2 := Book{
Name: "John John",
Author: "Author1",
Version: []string{"V1.0", "V1.1"},
}
fmt.Println("Book1 is empty?: ", reflect.ValueOf(book1).IsZero())
fmt.Println("Book2 is empty?: ", reflect.ValueOf(book2).IsZero())
}
Output:
Book1 is empty?: true
Book2 is empty?: false
Method 5: Add an additional field to the struct
We can define our check if the struct has been populated or it is empty. For example, we can add the field "Id" to our Book struct, if this field is 0 or empty, we consider that struct is empty.
package main
import (
"fmt"
)
type Book struct {
Name string
Author string
Version []string
Id int
}
func main() {
var book1 Book
book2 := Book{
Name: "John John",
Author: "Author1",
Version: []string{"V1.0", "V1.1"},
}
book3 := Book{
Name: "Anna",
Author: "Anna",
Version: []string{"V1.0", "V1.1"},
Id: 1,
}
fmt.Println("Book1 is empty?: ", book1.Id != 0)
fmt.Println("Book2 is empty?: ", book2.Id != 0)
fmt.Println("Book3 is empty?: ", book3.Id != 0)
}
Output:
Book1 is empty?: false
Book2 is empty?: false
Book3 is empty?: true
Summary
In this tutorial we have explored different methods to check if struct is empty in golang. I hope this post has given you some insight into Go's empty struct detection. Please share any additional tips or strategies you may have in the following comments section.
References
https://go.dev/ref/spec#Composite_literals
https://pkg.go.dev/reflect
How to check for an empty struct? - Stack Overflow