Go (Golang)
Useful stuff you should know about Go when moving from another language.
Resources
Concepts
These are the things I picked up (over time) while learning Go.
Loops over iterator abstractions
- Obsesses over loops, and has no iterator abstractions like
.map()
,.filter()
and.find()
that you see in most languages.
// Variant 1
for i := 1 ; i < len(collection) ; i++ {
log.Println(collection[i])
}
// Variant 2
for item := range collection {
log.Println(item)
}
Multiple return values
- Allows for multiple return values and does not have concept of
throw
// Definition
func getFloat(input string) (float32, error) {
result, err := strconv.ParseFloat(input, 32)
if err != nil {
return 0, err
}
return float32(result), nil
}
// Invoke
result, err := getFloat("15")
if err != nil {
log.Printf("unable to parse %v to float.\n", input)
}
log.Printf("Successfully parsed into %v (float32).\n", result)
Defer
- Has
defer
concept, which allows running something after the function ends.
func save(filePath string, canvas *canvas.Canvas, window fyne.Window) {
fileHandle, err := os.Create(filePath)
defer func() {
err := fileHandle.Close()
if err != nil {
dialog.ShowError(err, window)
}
}()
if err != nil {
dialog.ShowError(err, window)
return
}
err = png.Encode(fileHandle, canvas.PixelData)
if err != nil {
dialog.ShowError(err, window)
return
}
}
Goroutines
- Has
goroutines
concept, invoked by usinggo
keyword. Makes it very easy to work with channels, operate on that channel and also return that channel immediately.
func pipeline[I any, O any](inputChannel <-chan I, processFn func(I) O) <-chan O {
out := make(chan O)
go func() {
for input := range inputChannel {
out <- processFn(input)
}
close(out)
}()
return out
}
- Goroutines have the added benefit that the language will decide between using threads and concurrency, without you having to configure anything.
Type embedding
- Uses type embedding (which is pretty cool!)
// Here Hits embeds the sync.Mutex type
type Hits struct {
count int
sync.Mutex
}
// In the `sync` library there are methods that looks like:
func (m *Mutex) Lock() {}
func (m *Mutex) Unlock() {}