Lexical elements: Semicolons

January 11, 2023

Go’s use of semicolons is one area of confusion for newcomers to the language. It certainly was for me. But it’s more intuitive than it seems.

Here’s the formal explanation:

Semicolons

The formal syntax uses semicolons ";" as terminators in a number of productions. Go programs may omit most of these semicolons using the following two rules:

  1. When the input is broken into tokens, a semicolon is automatically inserted into the token stream immediately after a line’s final token if that token is

  2. To allow complex statements to occupy a single line, a semicolon may be omitted before a closing ")" or "}".

To reflect idiomatic use, code examples in this document elide semicolons using these rules.

What this means in practice is that Go “officially” uses semicolons, a lot like C/C++, kind of “all over the place.”

This is valid Go, which looks a lot like C:

package main;

import "fmt";

func main() {
	var x = 1;
	if (x > 0) {
		fmt.Println(x);
	};
};

But since the Go tokenization process adds most semicolons for you, based on the rules described, we can simplify this code when writing it, to be a bit less tedious:

package main

import "fmt"

func main() {
	var x = 1
	if x > 0 {
		fmt.Println(x)
	}
}

(This example also removes the unnecessary parentheses around the conditional expression, which we’ll get to later.)

So how do you know when it’s safe to remove a semicolon?

Well, you can memorize the rules above. But in practice, you can mostly just always omit them. As a general rule, the only times you need to explicitly type semicolons is when you want to put multiple statements on a single line. In other words, when you prefer a semicolon over a line break.

By convention, this is done in (small) number of cases, such as separating the if statement optional “simple statement” from the expression block:

if x := 1
x > y {
	return x
}

is more commonly expressed with a semicolon as:

if x := 1; x > y {
	return x
}

Quotes from The Go Programming Language Specification, Version of June 29, 2022