Golang cheat sheet
Useful golang commands and constructs
Here’s basic Go program structure, error handling patterns and channels vs goroutines comparison.
Go Language Cheatsheet
Basic Syntax
Package Declaration
package main
Import Packages
import "fmt"
import (
"fmt"
"math"
)
Main Function
func main() {
// Your code here
}
Variables and Types
Variable Declaration
var name string
var age int = 25
x := 10 // Short declaration
Basic Types
- bool
- string
- int, int8, int16, int32, int64
- uint, uint8, uint16, uint32, uint64
- float32, float64
- complex64, complex128
Control Structures
If Statement
if x > 0 {
// code
} else if x < 0 {
// code
} else {
// code
}
For Loop
for i := 0; i < 10; i++ {
// code
}
Range Loop
for index, value := range collection {
// code
}
Switch Statement
switch variable {
case value1:
// code
case value2:
// code
default:
// code
}
Functions
Function Declaration
func functionName(param1 type1, param2 type2) returnType {
// code
return value
}
Multiple Return Values
func divideAndRemainder(x, y int) (int, int) {
return x / y, x % y
}
Data Structures
Arrays
var numbers int
numbers := int{1, 2, 3, 4, 5}
Slices
slice := []int{1, 2, 3}
slice := make([]int, 3, 5)
Maps
m := make(map[string]int)
m["key"] = value
Structs
type Person struct {
Name string
Age int
}
p := Person{Name: "Alice", Age: 30}
Methods
Method Declaration
func (r Rectangle) Area() float64 {
return r.width * r.height
}
Interfaces
Interface Declaration
type Shape interface {
Area() float64
}
Concurrency
Goroutines
go functionName()
Channels
ch := make(chan int)
ch <- value // Send
value := <-ch // Receive
Error Handling
Error Checking
if err != nil {
// Handle error
}
Defer
defer file.Close()
Testing
Test Function
func TestFunction(t *testing.T) {
// Test code
}
This cheatsheet covers the most essential Go language constructs and commands. It includes basic syntax, control structures, functions, data structures, methods, interfaces, concurrency primitives, and error handling. Remember that Go emphasizes simplicity and readability, so these constructs form the foundation for writing efficient and clear Go code.
Error handling in Go
Error handling in Go is straightforward and explicit, emphasizing clarity and robustness. Here are the key techniques for handling errors in Go:
- Return errors as values: Functions that can fail should return an error as their last return value. For example:
func Hello(name string) (string, error) {
if name == "" {
return "", errors.New("empty name")
}
message := fmt.Sprintf("Hi, %v. Welcome!", name)
return message, nil
}
- Always check for errors: After calling a function that returns an error, immediately check if the error is non-nil. For example:
result, err := SomeFunction()
if err != nil {
// Handle the error
log.Fatal(err)
}
- Use error wrapping: When propagating errors up the call stack, wrap them to add context using
fmt.Errorf()
with the%w
verb. For example:
f, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("open failed: %w", err)
}
-
Utilize
defer
for cleanup: Usedefer
to ensure resources are properly closed or cleaned up, even if an error occurs. -
Create custom error types: Implement the
error
interface for custom error types to provide more detailed error information. -
Use the
errors
package: Leverage functions likeerrors.New()
to create simple error messages, anderrors.Is()
orerrors.As()
for error type checking and conversion. -
Avoid using panic: Reserve
panic
for truly unrecoverable situations. Normal error handling should use return values. -
Provide explicit error information: Make error messages clear and informative to aid in debugging and troubleshooting.
By following these practices, you can create robust Go programs that handle errors effectively and maintain code clarity.
Best Practices for Goroutines and Channels in Go
Efficient Use of Goroutines
-
Avoid excessive goroutine creation: Spawn goroutines judiciously, considering the nature of the task and whether it benefits from parallel execution.
-
Proper synchronization: Use synchronization mechanisms like channels or wait groups to manage goroutines effectively and prevent resource wastage.
-
Consider task nature: Evaluate if a task truly benefits from concurrent execution before using goroutines.
Effective Channel Usage
-
Choose appropriate channel type: Use unbuffered channels for synchronization and buffered channels when you need to decouple sending and receiving operations.
-
Buffer capacity: When using buffered channels, carefully consider the buffer size to balance performance and resource usage.
-
Close channels properly: Ensure channels are closed when no more data will be sent to prevent deadlocks and resource leaks.
Concurrency Patterns
-
Worker pool pattern: Implement worker pools using goroutines and channels for efficient task distribution and result collection.
-
Producer-consumer pattern: Use goroutines as producers and consumers, with channels facilitating data flow between them.
Error Handling and Resource Management
-
Use defer for cleanup: Employ defer statements to ensure proper resource cleanup, even in the presence of errors.
-
Handle panics: Implement recover() in long-running goroutines to prevent the entire program from crashing due to a panic in a single goroutine.
Communication and Synchronization
-
Prefer channels over shared memory: Use channels for communication between goroutines to avoid race conditions and simplify synchronization.
-
Use select for multiple channels: Employ the select statement to handle multiple channel operations concurrently.
Performance Considerations
-
Limit concurrent operations: Use semaphores or worker pools to limit the number of concurrent operations and prevent resource exhaustion.
-
Avoid premature optimization: Profile your code to identify bottlenecks before applying concurrency optimizations.
Testing and Debugging
-
Use race detector: Regularly run your tests with the -race flag to detect data races.
-
Write concurrent tests: Create tests that specifically exercise your concurrent code paths to ensure reliability.
By following these best practices, you can effectively leverage Go’s concurrency model, making your programs more efficient, maintainable, and less prone to common concurrency-related issues.
See other tech blog articles.