Video Coming Soon...
13: Error Handling
WARNING This exercise is in DRAFT status, so there may be errors. If you find any, please email me at help@learncodethehardway.com so I can fix them.
Go's error handling mostly involves dealing with a special return value from functions. There's another style called "panic/recover" but it's so bad I don't think I'll bother teaching it to you until it's needed later for some reason. In the normal Go error handling you do this:
- Call function.
- Get 2 return values a result and an
error
. - Create a
defer
for the first if needed. - Handle the error however is necessary.
Functions Can Have Multiple Returns
For this to work you need to learn that functions can return more than one value. Here's the classic example of this feature:
func swap(a int, b int) (int, int) {
return b, a
}
func main() {
x := 1
y := 2
x, y = swap(x, y)
}
In this example I have a function swap
that takes two int
named a
and b
, but the return is return b, a
. This will swap them around so you can reassign their values to do the swap. Study this for a bit before continuing on.
Returning a Value and Error
With that we can then make a function that returns a value and an error:
func MustOpen(filename string) (os.File, error) {
the_file, err := os.Open(filename)
return the_file, err
}
When you call MustOpen
it will call the os.Open()
function, which return a file and a possible error. We don't do anything with this and simply return both again, but we can handle it instead.
Detecting and Handling Errors
To handle an error you check if it is equal to nil
. The nil
value represents "not set" or "nothing." If there IS an error then the err
will be set to something that you have to handle. If this IS NOT an error then it will be set to nil
and you can ignore it. Let's handle the os.Open()
error:
func MustOpen(filename string) os.File {
the_file, err := os.Open(filename)
if err != nil { log.Fatal("failed to open")
return the_file
}
It's common for functions starting with Must
to cause the program to exit if there's any failure. Typically you want this in programs that run once to do something, but not in servers. From the defer
exercise you know that log.Fatal
causes programs to exit immediately, so this code will now exit the program if there are any errors opening the file.
NOTE I'm skipping over what
os.File
is until a later exercise in the second module. Just know that's what a file is in Go.
The Code
Now we can look at this code:
View Source file ex13/main.go Only
package main
import (
"fmt"
)
func ReadName() string {
fmt.Print("What's your name? ")
var name string
_, err := fmt.Scan(&name)
if err != nil { panic("WRONG!") }
return name
}
func main() {
name := ReadName()
fmt.Println("Thank you for your service citizen", name)
}
The Breakdown
I'll explain every line just like normal, but obiously I'll skip things you should already know like }
ends a block.
func ReadName() string {
--fmt.Print("What's your name? ")
--var name string
--_, err := fmt.Scan(&name)
--if err != nil { panic("WRONG!") }
--return name
--func main() {
--name := ReadName()
--fmt.Println("Thank you for your service citizen", name)
--
The Practice
- Break It -- Try causing and handling different errors, getting return values wrong, and anything else that messes with error handling.
- Change It -- You've seen
fmt.Scan
so can you do more with that? Can you combine it withif
orswitch
? Can you repeatedly ask for a name until you get a valid one? - Remake It -- As usual, write a description the recreate it from memory using the description. The more you do this, the better you'll get.
Study Drills
- Write a few different functions that handle or return errors in different ways.
- Find the documentation for the
log
function on Go's website and try to use it. - Is it better to use
log.Fatal
or to do your own error and exit handling? Why?
Register for Learn Go the Hard Way
Register today for the course and get the all currently available videos and lessons, plus all future modules for no extra charge.