Blank field names

March 10, 2023

Yesterday we started talking about Go’s structs, and breezed over a phrase about non-blank field names. Wassat?

Struct types

… Within a struct, non-blank field names must be unique.

Go has a concept of a blank identifier. It looks like the underscore character (_), and is useful in many situations, and we’ll discuss more of them in due time. (It’s also decidedly not useful in some situations where it’s permitted, and I made a video about that a while ago)

For now, we’re only concerned with blank field names. Here’s what one might look like:

type Person struct {
	Name string
	Age  int
	_    int64
}

Okay. But why would you ever want that?

Honestly, you probably never do.

But before we dive into the few use cases I know for blank field names, let’s discuss what it actually does:

First off, it does actually affect the struct. The field does exist. And it does take up memory, and it does hold a value:

	var x struct {
		Name string
	}
	var y struct {
		Name string
		_    int64
	}
	fmt.Println(x, y)                               // Prints: {} { 0}
	fmt.Println(unsafe.Sizeof(x), unsafe.Sizeof(y)) // Prints: 16 24

However, that blank-named field, which definitely does exist, and does take up memory… can never be accessed. You can’t set it to anything other than the default, zero value. The only way to access it is via reflection (which is what fmt.Println does under the hood to display { 0} above.)

So when is it useful?

One case where it’s useful is when using CGO, and mapping C structures to Go, when not all of the data in the C structure is useable by Go. By using the blank identifier, one can effectivly “skip” some of the in-memory representation of a struct. This is discussed briefly in this old GitHub issue. Mere mortals need not bother with this frequently.

There are two other places where I’ve seen a blank field name used as well. Although arguably, any unexported field would work for either of these cases:

  • To prevent the use of implicit field names in struct declaration. This requires a short explanation. Normally there are two, equivalent ways of declaring a struct instance:

    x := Person{Name: "Bob", Age: 29}
    y := Person{"Alice", 27}
    

    The latter, shorter, version requires that all field values are present, and in the proper order. By including an unexported field name (including with the blank identifier) in your struct definition, this short hand becomes impossible. Some people feel it is desirable to prevent this short-hand, and may do so with a blank field name, typically of type struct{}, which consumes no memory.

  • To make structs incomparable. As with the last example, a blank field name is not the only way to do this. Any struct element that is not comparable renders the entire struct incomparable. But this can be done with a blank field name as well. One example from the standard library is in the net/http package, where a blank field name of type [0]func() is used to render the struct incomparable (this works because functions are not comparable).

Do you know of any use for a blank field name in Go? Let me know!

Quotes from The Go Programming Language Specification Version of December 15, 2022


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


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 field promotion

Yesterday we learned that structs can have embedded fields. Although we didn’t really learn about any of the special powers this gives us. Today we’ll have a look at those powers. One advantage to using an embedded type is that the implicit field name (the one derrived from the type, Person, in our example) can be omitted. This is the result of “promotion”. For example: var e Employee e.Name = "Bob" // equivalent to e.


Embedded struct fields

When I introduced structs last week, I skipped over one sentence. Today I’m going to address that. Struct types A struct is a sequence of named elements, called fields, each of which has a name and a type. Field names may be specified explicitly (IdentifierList) or implicitly (EmbeddedField). Within a struct, non-blank field names must be unique. We already saw how field names are expressed explicitly. But what is an embedded field?