defer
: Delays execution until the end of the current function- Execution is guaranteed (== finally{})
import "os"
func main() {
file, err := os.Create("/tmp/hello")
if err != nil {
fmt.Printf("error: %v", err)
return
}
defer file.Close()
file.WriteString("Hello World\n")
}
- Error as a return value
if err != nil {
return nil, err
}
- Enrich an error with contextual information
- Get a stack trace, allowing follow the call stack of an error
package main
import "fmt"
import "github.com/pkg/errors"
func main() {
err := errors.New("error")
err = errors.Wrap(err, "open failed")
err = errors.Wrap(err, "read config failed")
fmt.Println(err) // read config failed: open failed: error
}
In some cases it can be useful to return specific error types (if you want to check which error occured for example).
Usually this happens using global variables of type error
.
See https://golang.org/pkg/io/#pkg-variables
Alternatives:
https://dave.cheney.net/2016/04/27/dont-just-check-errors-handle-them-gracefully
https://www.youtube.com/watch?v=lsBF58Q-DnY
panic
: Causes a panic (something like an exception)recover
: Catches a panic
func travel() {
defer func() {
if r := recover(); r != nil {
fmt.Println(r, "..don't panic!")
}
}()
panic("I lost my towel")
}
In go types can be converted into compatible types. This happens explicitly to avoid invisible bugs.
i := 42
f := float64(i)
u := uint(f)
This also can be done with custom types
s := "string"
type myString string
var ms myString
ms = myString(s)
- Entspricht
Object
in Java odervoid *
in C. - Variablen vom Typ
interface{}
können beliebige Werte aufnehmen
Auf den konkreten Wert einer interface{}
Variablen kann über eine Type Assertion zugegriffen werden.
var o interface{} = 42
i := o.(int)
i++
Wenn eine Type Assertion fehl schlägt wir ein panic()
ausgelöst.
Um ein Panic zum umgehen kann eine Type Assertion inkl. Test ausgeführt werden:
i, ok := o.(int)
interface{}
entspricht dem generischen Typ (Object bzw. void*).- Mit type switches lässt sich elegant in einem Schritt prüfen und konvertieren.
untypedList := []interface{}{"Hallo", 42, false}
for _, item := range untypedList {
switch i := item.(type) {
case string:
fmt.Println("String: " + i)
case int:
i++
fmt.Println("Int: " + strconv.Itoa(i))
default:
fmt.Println(i)
}
}