Struct types
March 9, 2023
Structs. Now we’re getting to some meaty stuff!
Let’s start simple. What is a struct?
Struct types
A struct is a sequence of named elements, called fields, each of which has a name and a type. … Within a struct, non-blank field names must be unique.
Forget about blank field names for now. I’ll talk about that tomorrow.
I’m also postponing the EBNF description of structs for a while, because there are actually several subtleties to how structs work in Go, which can get into the weeds very quickly. For today, let’s just consider a few examples.
type Person struct {
Name string
Age int
}
This simply defines a struct type named Person
, with two fields, Name
and Age
, of types string
and int
respectively.
Notice that in this example, the type Person
, as well as its fields, Name
and Age
, all begin with a capital letter, and therefore are exported identifiers. But unexported fields and types are also possible, and in many combinations.
type Person struct {
Name string
Age int
password string
}
Now we’ve added the notably unexported field, password
, to the same struct.
Let’s round out the day with one final example that may seem counter-intuitive, but can actually make a lot of sense:
type person struct {
Name string
Age int
}
Notice now that the fields themselves, Name
, and Age
, are exported, but person
is not. How could this ever be useful, you might be wondering.
It’s useful any time you will only ever create instances of person
within the same package, but you need other packages to be able to access the fields.
When would you ever want that?
Quite frequently, actually. A very common example is when marshaling or unmarshaling JSON (or YAML, or XML, or many other formats). Because these (un)marshaling capabilities are handled by another package, the only way they can access these fields of a private struct type, is if the fields are exported.
type person struct {
Name string
Age int
}
input := []byte(`{"Name":"Bob","Age":29}`)
var p person
_ = json.Unmarshal(input, &p)
fmt.Println(p) // Prints: {Bob 29}
See it in the playground.
Quotes from The Go Programming Language Specification Version of December 15, 2022
Related Content

Empty structs
We finally we have enough knowledge for the EBNF format not to seem completely foreign, so let’s jump back and take a look at that, with the examples provided in the spec… Struct types … StructType = "struct" "{" { FieldDecl ";" } "}" . FieldDecl = (IdentifierList Type | EmbeddedField) [ Tag ] . EmbeddedField = [ "*" ] TypeName [ TypeArgs ] . Tag = string_lit . // An empty struct.

Struct tags
Struct types … A field declaration may be followed by an optional string literal tag, which becomes an attribute for all the fields in the corresponding field declaration. An empty tag string is equivalent to an absent tag. The tags are made visible through a reflection interface and take part in type identity for structs but are otherwise ignored. struct { x, y float64 "" // an empty tag string is like an absent tag name string "any string is permitted as a tag" _ [4]byte "ceci n'est pas un champ de structure" } // A struct corresponding to a TimeStamp protocol buffer.

Struct method promotion
Yesterday we saw an example of struct field promotion. But methods (which we haven’t really discussed yet) can also be promoted. Struct types … Given a struct type S and a named type T, promoted methods are included in the method set of the struct as follows: If S contains an embedded field T, the method sets of S and *S both include promoted methods with receiver T. The method set of *S also includes promoted methods with receiver *T.