Skip to content
Theory · First program · lesson 2 of 8

Compile errors

In the previous lesson the compiler was a strict proofreader who keeps a recipe with a mistake out of the kitchen. Now let's see how it reports what it found, and which rules Go checks more strictly than other languages.

Go does not build a program that declares a variable inside a function and never uses it. The line n := 10 creates a variable n—a name that holds the value 10—but the program never reads it afterward:

GO
package main

import "fmt"

func main() {
    n := 10 // ✗
    fmt.Println("ok")
}
TEXT
declared and not used: n

This is a compile error: the compiler refused to translate the text, so the program never ran. The word ok is not printed either, even though its line is written correctly. The proofreader sent back the whole recipe, and the kitchen followed none of its steps, not even the correct ones.

The compiler's message

A proofreader returns a manuscript with notes in the margins: where the mistake is and what is wrong. The compiler does the same. The full message looks like this: ./main.go:6:5: declared and not used: n.

Let's take it apart, left to right:

  1. ./main.go is the file name.
  2. 6 is the line number.
  3. 5 is the character number within that line: on the sixth line, n stands after four spaces of indentation.
  4. declared and not used: n—after the last colon, the compiler says exactly which rule is broken.

If there are several errors, the compiler lists them one per line. Fix them from top to bottom: the later ones in the list sometimes disappear together with the first.

Two build commands

You can build a program with two commands. They treat the result differently, so let's look at each on its own.

go build: build only

The command go build main.go has three parts:

  • go is the tool that is installed together with the language;
  • build is the action "build";
  • main.go is the file with the program.

Without errors, the command creates a finished program in the folder you ran it from. The file is named after the source file without .go: main.go gives main, and on Windows main.exe.

You run the program separately, as many times as you like, without compiling it again. On a compile error, no program file is created.

go run: build and run

The command go run main.go compiles the program the same way as go build and runs the result right away. No finished program file appears in the folder.

This command is handy while you are writing a program and checking what it prints: one step instead of two. On a compile error, it runs nothing.

Errors, not warnings

In many languages, the compiler issues warnings besides errors: a program with warnings builds, but the suspicious spot is marked. That is like a proofreader who writes "check this" in the margin and sends the text to print anyway.

Go's proofreader never does that: Go has no warnings, and everything the compiler finds is an error. An unused variable is one of those errors. It often reveals the author's slip: a value was computed but never printed or passed on.

Interviewers like to ask: what happens if you declare a variable and never read it? Here are the three answers you usually hear:

  • "the program does not compile"—right;
  • "it prints a warning"—wrong: Go has no warnings;
  • "it fails at run time"—wrong: it never gets as far as running.

Two ways to fix it

You can fix an unused variable in two ways. The choice depends on whether the program needs its value.

Read the variable

If the value is needed, you use it—for example, print it:

GO
package main

import "fmt"

func main() {
    n := 10
    fmt.Println(n) // 10
}

Now n is used: fmt.Println(n) reads the variable and prints 10. The compiler has nothing left to object to, and the program runs.

Delete the line

If the value is not needed, you delete the line n := 10 entirely. In the first example, only fmt.Println("ok") is then left, and the program prints ok.

Common mistake

The same rule applies to imports: a package that is imported but never used stops the build. This happens when the last call to fmt.Println is removed from a program but the import stays:

GO
package main

import "fmt" // ✗

func main() {
}
TEXT
"fmt" imported and not used

The fix is to delete the line import "fmt": no call to the package fmt is left in the program.

Key points

  • A compile error stops the build: the program does not run, and not a single line executes.
  • The message names the file, the line and the character, and after the last colon the broken rule.
  • Go has no warnings: an unused variable inside a function and an unused import are errors.
  • go build only compiles a program, while go run compiles it and runs it right away.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way