Golang Anonymous Structs Usage & Examples

Golang Anonymous Struct Definition and Syntax

In our previous article, we gave an overview of Golang structure where we briefly covered Anonymous struct. Now to give you a brief overview, Anonymous struct types are defined without using a name. Go allows you to define anonymous fields: struct fields that have no name of their own, just a type.

A struct without a name is known as anonymous. As a result, we are unable to refer to the structure in other parts of the code. You can define temporary, ephemeral structures using anonymous structures.

Advertisement

Example syntax to create an anonymous structure is as shown:

variable_name := struct {
	// fields
}{field_values}

 

How to Create Anonymous Struct

The code shown below illustrates how to create an anonymous struct in Go.

package main

import "fmt"

func main() {
	// create anon struct
	person := struct {
		name, nationality string
		age               int
		score             float64
	}{
		name:        "Anna_Hurry",
		nationality: "England",
		age:         21,
		score:       9.5,
	}
	// print anon struct
	fmt.Println(person)
}

In the example above, we create an anonymous struct and create an instance of the struct immediately. The above code should print the struct as:

$ go run main.go
{Anna_Hurry England 21 9.5}

 

How Anonymous struct can be used to compare structs with different types

Structs that are entirely composed of comparable types are comparable; but a struct with slice or map fields are not comparable. Unlike in Python or Ruby, in Go there’s no magic method that can be overridden to redefine equality and make == and != work for incomparable structs. You can, of course, write your own function that you use to compare structs.

But Go does allow you to perform a type conversion from one struct type to another if the fields of both structs have the same names, order, and types. Let’s see what this means.

Here we have one struct

Advertisement
type firstPerson struct {
    name string
    age  int
}

We can use a type conversion to convert an instance of firstPerson to secondPerson, but we can’t use == to compare an instance of firstPerson and an instance of secondPerson, because they are different types:

type secondPerson struct {
    name string
    age  int
}

We can’t convert an instance of firstPerson to thirdPerson, because the fields are in a different order:

type thirdPerson struct {
    age  int
    name string
}

We can’t convert an instance of firstPerson to fourthPerson because the field names don’t match:

type fourthPerson struct {
    firstName string
    age       int
}

Finally, we can’t convert an instance of firstPerson to fifthPerson because there’s an additional field:

type fifthPerson struct {
    name          string
    age           int
    favoriteColor string
}

Anonymous structs add a small twist to this: if two struct variables are being compared and at least one of them has a type that’s an anonymous struct, you can compare them without a type conversion if the fields of both structs have the same names, order, and types. You can also assign between named and anonymous struct types if the fields of both structs have the same names, order, and types:

package main

import (
	"fmt"
)

type firstPerson struct {
	name string
	age  int
}

func main() {

	f := firstPerson{
		name: "Bob",
		age:  50,
	}
	var g struct {
		name string
		age  int
	}

	// compiles -- can use = and == between identical named and anonymous structs
	g = f
	fmt.Println(f == g)
}

Output:

$ go run main.go
true

 

Recommended cases to prefer an anonymous struct over a regular struct

The recommended 4 use cases listed here:

  • grouped global
  • template data
  • test tables
  • embedded lock

 

1. Grouped global

We use an anonymous struct to gather all configuration variables into one struct because we do not need to refer this struct anymore.

var config struct {
    Username string
    Password string
    APIKey      string
    OAuthConfig oauth.Config
}

 

2. Template data

An anonymous struct can be used as a data template.

data := struct {
    Title string
    Users []*User
}{
    title,
    users,
}

 

3. Test table

The code shown below demonstrate how to use an anonymous struct to create a test table

var testData = []struct {
    name    string
    age int
    score  float64
}{
    {"a A x", 12, 5.5},
    {"some_text=some_value", 10, 9.3},
    {"a", 12, 8.2},
    {"ab", 20, 6.7},
}
var testData = []struct {
    name    string
    age int
    score  float64
}{
    {"a A x", 12, 5.5},
    {"some_text=some_value", 10, 9.3},
    {"a", 12, 8.2},
    {"ab", 20, 6.7},
}
//do some test here

 

4. Embedded lock

Keeping the mutex close to the data it is intended to protect is excellent practice. It is quite convenient to add the mutex as a field to the struct if it is necessary to prevent concurrent access to its fields. It's known and used to a lesser extent, but it's also handy that you can "truly" embed a mutex in a struct, and you can call Lock() and Unlock() as if they would be part of the struct itself. It looks like this.

var hits struct {
    sync.Mutex
    n int
}

hits.Lock()
hits.n++
hits.Unlock()

 

Summary

An anonymous struct is just like a normal struct, but it is defined without a name and therefore cannot be referenced elsewhere in the code. The anonymous struct syntax is simple and we can easily create one anonymous struct. In some cases such as: grouping global variables, create a test data table,… we can use anonymous instead of regular struct.

Advertisement

 

References

https://go.dev/talks/2012/10things.slide#3
https://pkg.go.dev/sync#Mutex

 

Didn't find what you were looking for? Perform a quick search across GoLinuxCloud

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

Leave a Comment

X