How to fix the "tag is not aligned, should be: (...) (tagalign)"

Crash course in fixing a "tagalign" Golang linter issue

Golang Tag Alignment

Tag Alignment is way more easier subject than the Field Alignment and structure size optimization that I've covered in the previous post.

You can use tags for additional functionalities on the struct's fields, commonly used by the encoders.

[1] Go offers struct tags which are discoverable via reflection. These enjoy a wide range of use in the standard library in the JSON/XML and other encoding packages.

Tagged struct can look as follows:

// Tags not aligned and not sorted.
type Address struct {
    Name    string `yaml:"name" json:"name" xml:"name"`
    Street  string `yaml:"street" json:"street" xml:"street"`
    ZipCode string `yaml:"zipCode" json:"zipCode" xml:"zipCode"`
    City    string `yaml:"city" json:"city" xml:"city"`
}

Such a struct is totally valid and compiles successfully, however tags (yaml, json and xml) are not sorted and not aligned, thus it might be harder to read.

What's the golangci-lint outcome on that file?

Problem

When running a linter you can see errors that might look like these:

golangci-lint run ./...
tags.go:4:17: tag is not aligned, should be: json:"name"    xml:"name"    yaml:"name" (tagalign)
    Name    string `yaml:"name" json:"name" xml:"name"`
                   ^
tags.go:5:17: tag is not aligned, should be: json:"street"  xml:"street"  yaml:"street" (tagalign)
    Street  string `yaml:"street" json:"street" xml:"street"`
                   ^
tags.go:6:17: tag is not aligned, should be: json:"zipCode" xml:"zipCode" yaml:"zipCode" (tagalign)
    ZipCode string `yaml:"zipCode" json:"zipCode" xml:"zipCode"`
                   ^
tags.go:7:17: tag is not aligned, should be: json:"city"    xml:"city"    yaml:"city" (tagalign)
    City    string `yaml:"city" json:"city" xml:"city"`

tagalign command that is being used by the golangci-lint to detect these issues reports where the error is and how it should looks like when fixed (that's a way more better output than from the govet).

Solution

The solution comes also from the tagalign package:

[2] TagAlign is used to align and sort tags in Go struct. It can make the struct more readable and easier to maintain.

We can fix this in two ways:

  1. Using the --fix param for the golangci-lint command (since the version v1.53):

     golangci-lint run --fix ./...
    
  2. Using tagalign in the standalone mode.

     // Install tagalign.
     go install github.com/4meepo/tagalign/cmd/tagalign@latest
    
     // Align tags.
     tagalign -fix ./...
    
     // Align and sort tags.
     tagalign -fix -sort ./...
    

More details on additional params for tagalign you can find directly on the tagalign GH page.

How to configure tagalign with the golangci-lint please check the latter documentation.

Our sorted Address struct now looks as follows:

// Tags aligned and sorted.
type Address struct {
    Name    string `json:"name"    xml:"name"    yaml:"name"`
    Street  string `json:"street"  xml:"street"  yaml:"street"`
    ZipCode string `json:"zipCode" xml:"zipCode" yaml:"zipCode"`
    City    string `json:"city"    xml:"city"    yaml:"city"`
}

Sources

Docs:

Quotations: