Golang Anonymous Struct: Inline Structs, JSON, Methods, and Return Values

Tech reviewed: Deepak Prasad
Golang Anonymous Struct: Inline Structs, JSON, Methods, and Return Values

This page is for Go developers who want a compact type for data that only matters in one place: tests, JSON envelopes, or a function that returns a small bundle of fields. It explains how anonymous (inline / unnamed) struct literals work, how they compare to named types, how they interact with JSON, and what people mean when they search for an anonymous struct with a method (spoiler: you need a named type or a helper, not a receiver on the literal type). For broader struct topics, see structs in Go; for JSON decoding patterns, see JSON unmarshal in Go and parse JSON in Go. For methods and receivers in general, see methods in Go and methods vs functions.

Tested with Go 1.24 on Linux.


Quick answer: unnamed struct types

An anonymous struct is a struct type declared inline as struct { ... } without a separate type name. People also call it an inline struct or unnamed struct. You use it for one-off shapes; the compiler still checks field names and types exactly like a named struct.


What is an anonymous struct?

A named struct is introduced at package scope, for example type Person struct { Name string }. An anonymous struct spells the same field list next to a value or in a signature: struct { Name string }{Name: "Ada"}. The type exists only where it is written; two anonymous literals with identical fields in different places are still distinct types for assignment purposes unless you unify them with a named type.

Named vs anonymous

Named struct Anonymous struct
Declaration type T struct { ... } struct { ... }{...} or var v struct{...}
Reuse Same T everywhere Repeat literal or switch to type
Methods func (t T) M() or func (t *T) M() at package level No stable type name for a receiver

Syntax: declare, initialize, zero values

The type and value can appear together. Fields follow the usual struct rules (exported names start with an uppercase letter if other packages must see them).

go
package main

import "fmt"

func main() {
	person := struct {
		name string
		age  int
	}{
		name: "John Doe",
		age:  30,
	}
	fmt.Println(person.name, person.age)

	var empty struct{ ID int; OK bool }
	fmt.Printf("zero: %#v\n", empty)
}
Output

You should see John Doe 30 and a zero struct line with ID:0 and OK:false.


When to use anonymous structs

Good fits: one-off locals, table-driven test tables, small JSON request or response bodies you only decode once, and temporary grouping inside a function. Poor fits: the same field layout copied in many files, large nested APIs, or anything that needs a clear exported contract—in those cases introduce a named type.

Table-driven style without a top-level type

The struct { ... } form is common in tests; the same idea works in main for small tables:

go
package main

import "fmt"

func main() {
	cases := []struct {
		name string
		n    int
		want int
	}{
		{"square of three", 3, 9},
		{"square of zero", 0, 0},
	}
	for _, tc := range cases {
		got := tc.n * tc.n
		fmt.Println(tc.name, got == tc.want)
	}
}
Output

You should see two lines ending in true.

JSON and small API shapes

Anonymous structs work with encoding/json tags the same way named types do—useful when you only care about a subset of fields. For larger models, prefer a named type.

go
package main

import (
	"encoding/json"
	"fmt"
)

func main() {
	in := struct {
		ID   int    `json:"id"`
		Name string `json:"name"`
	}{1, "John Doe"}
	b, err := json.Marshal(in)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))

	var out struct {
		ID   int    `json:"id"`
		Name string `json:"name"`
	}
	if err := json.Unmarshal(b, &out); err != nil {
		panic(err)
	}
	fmt.Println(out.ID, out.Name)
}
Output

You should see one JSON object line, then 1 John Doe.

Slices and maps

Element types can be anonymous struct literals as long as every element uses the same shape:

go
package main

import "fmt"

func main() {
	people := []struct {
		ID   int
		Name string
	}{
		{1, "Alice"},
		{2, "Bob"},
	}
	fmt.Println(len(people), people[0].Name)

	m := map[string]struct {
		Age int
	}{
		"ada": {40},
	}
	fmt.Println(m["ada"].Age)
}
Output

You should see 2 Alice then 40.


Return an anonymous struct from a function

You can name the literal struct type in the function signature so callers get a precise shape without a package-level type alias. That is fine for private helpers; for exported APIs, a named type documents intent and stays stable when fields evolve.

go
package main

import "fmt"

func newPoint(x, y int) struct{ X, Y int } {
	return struct{ X, Y int }{X: x, Y: y}
}

func main() {
	p := newPoint(3, 4)
	fmt.Println(p.X, p.Y)
}
Output

You should see 3 4.


Anonymous struct with method (what works and what does not)

Searchers often ask whether a golang anonymous struct can have methods. Method declarations in Go must live at package scope and use a defined receiver type. You cannot attach func (s struct{...}) M() to a one-off anonymous struct literal as if it were its own class inside main.

Practical options:

  1. A package-level named type if you need real methods and recv.M() syntax.
  2. A plain function that takes the struct value or pointer and performs the operation.
  3. Embedding a named type that already has methods so those methods promote onto the anonymous struct literal’s value.

Helper function (no receiver)

go
package main

import "fmt"

func printPerson(p struct {
	Name string
	Age  int
}) {
	fmt.Printf("%s is %d\n", p.Name, p.Age)
}

func main() {
	printPerson(struct {
		Name string
		Age  int
	}{"John", 30})
}
Output

You should see John is 30.

Embed a named type with methods

Here the outer literal is still anonymous, but the behavior comes from a named embedded type:

go
package main

import "fmt"

type greeter struct{}

func (greeter) Hello() string { return "hi" }

func main() {
	v := struct {
		greeter
		Name string
	}{Name: "Ada"}
	fmt.Println(v.Hello(), v.Name)
}
Output

You should see hi Ada (promoted method from the embedded field).


Anonymous struct vs anonymous field

These phrases sound similar but mean different things:

Phrase Meaning
Anonymous struct The struct type has no type name; it is spelled inline.
Anonymous field (embedding) A struct field declared with only a type name, no field identifier—the promoted name is the type name.

An anonymous struct can contain embedded (anonymous) fields of named types, which is how the previous greeter example picked up Hello.


Mistakes to avoid

Pasting the same large anonymous struct literal in many functions instead of promoting one named type.

Deep nesting of anonymous structs—readability drops quickly; name inner shapes.

Expecting receiver methods on the literal type itself—declare a named type at package scope instead.

Using anonymous structs in exported APIs where callers depend on the exact field set—named types version more clearly.


Anonymous struct cheat sheet

Situation Better choice
One-time local shape Anonymous struct
Table-driven cases Slice of anonymous structs
Small JSON body used once Tagged anonymous struct
Reused layout across packages Named struct
Public API surface Named struct
Need methods on the receiver Named struct
One-off behavior Function taking the struct
Want promoted methods on a literal Embed a named type
Deep nested JSON Named types for sub-objects

Summary

Anonymous structs in Go are inline struct types: struct { fields }{values}, also called unnamed or inline structs. They shine in table-driven tests, compact JSON decode shapes, and small return bundles. Returning struct{...} from a function is legal but named types read better at package boundaries. For golang anonymous struct with method expectations, remember that methods bind to defined receiver types at package scope—use helpers, embedding, or a named type instead of a method on the literal itself. Embedding is about anonymous fields, not anonymous struct names. When the same shape repeats or the API is exported, switch to a named struct.


References


Frequently Asked Questions

1. What is an anonymous struct in Go?

A struct type written inline as struct { fields } without a top-level type name; you bind it to a variable or use it in a function signature for a one-off shape.

2. Can an anonymous struct have methods?

A method receiver must be a type name T or *T; an anonymous struct literal is not a type name, so you cannot declare methods on it—use a named type, a helper function, or embed a named type that already has methods.

3. How do I return an anonymous struct from a function?

Write the full struct { ... } type in the function signature and return a matching literal, or return a literal and let the caller use := with inferred type—prefer a named type for exported APIs.

4. Are anonymous structs good for JSON?

Yes for small one-off decode or encode shapes with struct tags; for models shared across packages, use a named type.

5. What is the difference between an anonymous struct and an anonymous field?

Anonymous struct means the struct type itself has no name. Anonymous field means embedding without a field name—the promoted name is the type name.

6. When should I use a named struct instead?

When the layout is reused, appears in exported APIs, grows deep, or needs methods declared on a stable receiver type.
Tuan Nguyen

Data Scientist

Proficient in Golang, Python, Java, MongoDB, Selenium, Spring Boot, Kubernetes, Scrapy, API development, Docker, Data Scraping, PrimeFaces, Linux, Data Structures, and Data Mining. With expertise spanning these technologies, he develops …

  • Deep Learning with TensorFlow
  • Machine Learning with Python
  • Go (programming language)
  • Python (programming language)
  • Java (programming language)
  • MongoDB