How to Check for an Empty Struct in Golang [4 Ways]

Here are four ways to check for an empty struct in Go:

  1. Comparing with a zero-value composite literal
  2. Using the reflect.DeepEqual() function
  3. Comparing the struct pointer to the nil
  4. Using the isZero() function

Method 1: Comparing with a zero-value composite literal

package main

import "fmt"

type Student struct {
  Name string
  Age int
}

func main() {
  var s1 Student
  s2 := Student{}
  s3 := Student{Name: "Krunal", Age: 30}

  fmt.Println(isZero(s1))
  fmt.Println(isZero(s2))
  fmt.Println(isZero(s3))
}

func isZero(s Student) bool {
  return s == Student{}
}

Output

true
true
false

If the struct contains fields that are slices, maps, or pointers, the zero value for these fields will be nil. But a nil slice and an empty (but initialized) slice are different. Similarly, a nil map and an empty (but initialized) map differ.

If you need to check for truly empty values in such cases, you will need to add additional logic.

Comparing large structs in this way might not be very efficient.

If performance is a concern, you might want to maintain a bool flag or use other techniques to track the “emptiness” of the struct.

Method 2: Using the reflect.DeepEqual() function

The built-in comparison using == doesn’t work for structs containing non-comparable fields like slices, maps, or functions. In such cases, it will give a compilation error.

Instead, you can use the DeepEqual() function from the reflect package to compare such structs. This function will recursively compare the contents of the struct, including non-comparable fields.

package main

import (
  "fmt"
  "reflect"
)

type Data struct {
  Numbers []int
  Lookup map[string]int
}

func main() {
  var d1 Data
  d2 := Data{}
  d3 := Data{Numbers: []int{1, 2, 3}, Lookup: map[string]int{"one": 1}}

  fmt.Println(isZero(d1))
  fmt.Println(isZero(d2))
  fmt.Println(isZero(d3))
}

func isZero(d Data) bool {
  return reflect.DeepEqual(d, Data{})
}

Output

true
true
false

Method 3: Comparing the struct pointer to the nil

To check if a struct’s pointer is zero, we can compare it to nil or the zero-value composite literal.

When you have a pointer to a struct, there are two aspects of “zero-ness” to consider:

  1. Pointer itself being nil: This means the pointer doesn’t point to any memory address.
  2. The value the pointer points to is the zero value for the struct type: This means that while the information is not nil, the struct it points to holds the zero values for all its fields.
package main

import (
  "fmt"
  "reflect"
)

type Person struct {
  Name string
  Age int
}

func main() {
  var p1 *Person // nil pointer
  p2 := &Person{} // pointer to zero value of Person
  p3 := &Person{"Alice", 25}

  fmt.Println(isNilOrZero(p1))
  fmt.Println(isNilOrZero(p2))
  fmt.Println(isNilOrZero(p3))
}

func isNilOrZero(p *Person) bool {
  if p == nil {
    return true
  }
  return reflect.DeepEqual(*p, Person{})
}

Output

true
true
false

Method 4: Using the isZero() function

The isZero() function can be reused to check if a struct (or its pointer) is “empty” or has zero value for its type.

Here’s how you can adapt the function to work for both direct structs and pointers to structs:

package main

import (
  "fmt"
  "reflect"
)

type Person struct {
  Name string
  Age int
}

func main() {
  var p1 Person
  p2 := Person{}
  p3 := Person{Name: "Alice", Age: 25}

  var pp1 *Person // nil pointer
  pp2 := &Person{} // pointer to zero value of Person
  pp3 := &Person{"Bob", 30}

  fmt.Println(isZero(p1))
  fmt.Println(isZero(p2))
  fmt.Println(isZero(p3))

  fmt.Println(isZero(pp1))
  fmt.Println(isZero(pp2))
  fmt.Println(isZero(pp3))
}

func isZero(i interface{}) bool {
  v := reflect.ValueOf(i)

  // If it's a pointer, dereference it
  if v.Kind() == reflect.Ptr {
    // Check if the pointer itself is nil
    if v.IsNil() {
      return true
    }
    v = v.Elem()
  }

  zeroValue := reflect.Zero(v.Type())
  return v.Interface() == zeroValue.Interface()
}

Output

true
true
false
true
true
false

That’s it!