Formatting your code is an important way of enhancing its readability, consistency, and reusability. Properly formatted code is easier to understand, modify, and maintain.

One of Go’s great features is its well-defined formatting conventions. You can use the built-in format package, and the go fmt command, to automatically format your code. This will help to ensure that other Go programmers can read it as easily as possible.

The Format Package and the fmt Command

The format package implements standard formatting for the Go source code. The package interoperates with the go format command line tool for flexibility in formatting Go code.

The format package is a submodule in the go package. Here’s how you can import it:

        import "go/format"

You can browse the documentation of the go fmt command by specifying the help command before the fmt command:

        go help fmt
    

Specify a file name after the fmt command to format that file. This will adjust your code’s whitespace and indentation to conform to Go standards.

        go fmt main.go

Behind the scenes, go fmt is an alias for the gofmt command, specifically:

        gofmt -l -w
    

Those flags cause gofmt to write any changes to each file you supply and list the names of the files it changes.

You can add the -x flag to the fmt command. The -x flag helps write changes from the formatter to the original file.

        go fmt -x main.go

The -n flag works similarly to -x, but it doesn’t make changes. Instead, it displays the commands that go fmt would run without the -n:

        go fmt -n main.go

The flag tells the formatter to show changes, which allows you to review them first before you apply them.

Here’s a simple Go program that loops through integers from zero to five and prints the string “Hello World!".

        // formatting a file named main.go as shown in the example above 

package main
import "fmt"
func main() {
  var x int=5
  for i:=0;i<x;i++{
    fmt.Println("Hello World!")
  }
}

Formatting Go Source Code

The format package contains a Source function for formatting Go files from programs. You’ll have to read the file and pass the contents as arguments to the Source function.

The Source function will return the formatted file content you can write to the file or a new one.

You can read files with the ReadFile function of the ioutil package. The ReadFile function takes in the file name and returns the file content and an error for handling.

        fileContent, err := ioutil.ReadFile("main.go")

if err != nil {
  log.Fatalln("There was an error reading the file", err)
}

Passing the file content to the Source function returns the formatted file content and an error for handling.

        formatted, err := format.Source(fileContent)

if err != nil {
  log.Fatalln("There was a formatting error with the source function", err)
}

You can write the formatted file content to the file with the WriteFile function of the ioutil package. The WriteFile function takes in the file name, contents, and file permission mode, returning any error(s). The permission mode is only relevant if the file doesn’t exist, in which case WriteFile will create it.

The 0644 file permission mode gives:

  • The file owner read and write permissions.
  • Read permissions to other users in the same group as the owner.
  • No permissions to other users.
        err = ioutil.WriteFile("main.go", formatted, 0644)

if err != nil {
  log.Fatalln("There was an error writing the file", err)
}

Alternatively, you can pass Go source code to the Source function for formatting. You can specify the code in a byte slice using ticks (`):

        package main

import (
  "fmt"
  "go/format"
)

func main() {
  // simple program that calculates the area of a triangle with the math
  // function
  formatted, err := format.Source([]byte(`
package main
import(
  "fmt"
  "math"
)
func main(){
var a float64=3
var b float64=4
var c float64=5
var s float64=(a+b+c)/2
var area float64=math.Sqrt(s*(s-a)*(s-b)*(s-c))
fmt.Println("The area of the triangle is: ",area)
}
`))

  if err != nil {
    log.Fatalln("There was a formatting error with the source function", err)
  } else {
    fmt.Println(string(formatted))
  }
}

On formatting, you’ll need to convert the byte slice to string with the string function. Here’s the formatted source code.

result of a format operation

Customizing the Formatting Process

You can customize the formatting process with the format package’s Config struct. The Config struct contains fields where you can specify format options on instantiation.

        import "go/format"

config := &format.Config{
  // Tabwidth sets the number of spaces per tab.
  Tabwidth: 8,

  // UseTabs indicates whether the formatter should use tabs instead of
  // spaces.
  UseTabs: false,

  // TabIndent is used to determine if the initial indentation should be
  // done using tabs or spaces.
  TabIndent: true,

  // NoFinalTab specifies whether a final tab should be removed from
  // lines before they are formatted.
  NoFinalTab: true,

  // Spaces specifies whether spaces should be used for alignment.
  Spaces: true,

  // NoTrimTrailingSpace specifies whether trailing white space should
  // be trimmed from lines before they are formatted.
  NoTrimTrailingSpace: false,
}

You can use the fields to customize the behavior of your formatter by setting the options based on your requirements.

You can then use this struct’s Source method to format a byte slice based on your configuration.

        func main() {
  fileContent, err := ioutil.ReadFile("main.go")

  // note that this is a Source method of the `config` type, not from the
  // `format` package itself although the functionality is the same, you'll
  // need to adhere to this if you need to configure the formatter
  formatted, err := config.Source(fileContent)

  if err != nil {
    log.Fatalln("There was a formatting error with the config type", err)
  }

  ioutil.WriteFile("main.go", formatted, 0644)
}

Calling the config.Source() function like this formats the contents of the main.go file using the configuration options. It returns the formatted contents as a byte slice and an error.

You Can Format and Manipulate String in Go

The format package and go fmt command can help you automate your code formatting process.

Go also provides a fmt package for string formatting and a strings package for string manipulation.

The fmt package implements simpler formatted I/O with functions analogous to C's printf and scanf functions. The strings function implements simple functions to manipulate UTF-8 encoded strings.