08. Comments and notes to yourself
You met comments briefly in Chapter 07: text Go ignores when it compiles the file. They let you leave notes for the most forgetful programmer you will ever work with — yourself, next week. Good comments turn a wall of code back into something you can read.
As in Chapter 07, short examples show only the lines that go inside
main.
The two kinds of comment
A single-line comment starts with //.
Everything from there to the end of the line is ignored:
// This whole line is a note for a human.
fmt.Println("Hi") // A note can also sit after some code.For a multi-line block of notes, use several
// lines in a row, or use a block comment.
A block comment starts with /* and ends with
*/, and Go ignores everything between them:
/*
This is a longer note. It can run for several lines.
Go ignores all of it.
*/
fmt.Println("Still runs.")Use single // lines for short notes and for commenting
out single lines of code. Use /* */ blocks for a paragraph
at the top of a file or any longer explanation.
Open exercises/08/01-comment-styles.go. It has three
fmt.Println calls. Add a single-line //
comment above the first, an end-of-line comment after the second, and a
/* */ block at the top explaining the file. Run it — the
output should not change.
Comment why, not what
The most common beginner mistake is comments that just repeat the code:
fmt.Println("Score:", 0) // print the score, 0
fmt.Println("Bonus:", 10) // print the bonus, 10Those comments add nothing — the code already says what it does. A useful comment explains why, or warns about something surprising:
fmt.Println("Score:", 0) // players always start a round on zero
fmt.Println("Bonus:", 10) // bonus for finishing under parA good rule: if the comment and the code say the same thing, delete the comment. Save them for the why, the gotcha, and the not obvious.
Commenting out code
Comments have a second job: switching code off without deleting it — one of the most useful debugging tricks around.
Suppose a program misbehaves and you suspect one line. Put
// in front of it and run again:
fmt.Println("Step 1")
// fmt.Println("Step 2")
fmt.Println("Step 3")Now "Step 2" never prints. If the problem goes away, you found your
culprit. To switch the line back on, delete the // — faster
and safer than deleting and retyping it later.
To switch off a whole block, put // in front of each
line, or wrap it in a /* */ block:
/*
fmt.Println("These three")
fmt.Println("lines are")
fmt.Println("all switched off")
*/
fmt.Println("Only this line runs.")A block comment ends at the first */ Go sees, and blocks
do not nest. Whatever follows that first */ is treated as
code again, which usually gives a syntax error. If you
forget the closing */ altogether, Go stops with
comment not terminated. Keep the closing */ on
its own line at the end.
When commenting out stops the program compiling
This is a rule many other languages do not have: Go refuses to compile a file that imports a package and does not use it.
So commenting out code can itself cause an error. Say
hello.go in your go-work folder has one
fmt.Println and you comment it out:
package main
import "fmt"
func main() {
// fmt.Println("Hi")
}Run go run hello.go and you get:
# command-line-arguments
.\hello.go:3:8: "fmt" imported and not used
The error points at line 3, the import, not at the
comment. Commenting out the last line that uses fmt left
nothing using it. There are two ways out: keep at least one line that
uses fmt, or comment out the import as well:
package main
// import "fmt"
func main() {
// fmt.Println("Hi")
}That version compiles, and prints nothing. Variables follow the same rule, as Chapter 10 shows.
The Go extension for VS Code may remove an unused import
line by itself when you save. If so, you will not see this error, and
the import "fmt" line will have gone from the file. When
you use fmt again, the extension adds the line back on the
next save, or you can type it yourself.
A header for every file
A habit worth building: start each file with a short comment block saying what it is for. Future-you will thank present-you.
/*
Greeting program.
Asks for nothing; just prints a friendly welcome banner.
Written while learning Chapter 08.
*/
package main
import "fmt"
func main() {
fmt.Println("Welcome!")
}Homework
Homework files are in exercises/08/homework/. Every file
must still compile after your changes, so keep at least one line that
uses fmt switched on.
Problem 1 — Annotate a program
Open exercises/08/homework/01-annotate.go. It has a few
lines of working code with no comments. Add a /* */ or
// header saying what the file does, plus at least two
single-line // comments explaining why a line is
there (not what it does). The output must not change.
Problem 2 — Find the bug by commenting out
Open exercises/08/homework/02-comment-out.go. One of its
fmt.Println lines produces output that should not be there.
Comment out exactly one line so the program prints only:
start
end
Do it by adding //, not by deleting the line.
Problem 3 — Switch off a block
Open exercises/08/homework/03-block-off.go. Using a
single /* */ block comment, switch off the three middle
fmt.Println lines so only the first and last lines print.
Run it to confirm.
Challenge — Why, not what
Open exercises/08/homework/04-why-not-what.go. It is
full of useless comments that just repeat the code. Rewrite each so it
explains why the line exists, or delete it if nothing useful
can be said. Aim for fewer, better comments.
Stuck or finished? Open the homework solutions page.