Go has a distinct set of idioms that make code more readable and idiomatic. This guide covers the most common patterns found in the Learn Go course materials, drawn from thousands of examples.
// Use for local variablesname := "Pablo Picasso"age := 95// Multiple assignmentname, age := "Pablo Picasso", 95// In loopsfor i := 0; i < 10; i++ { // i is scoped to the loop}
The := operator is idiomatic for local variables. Use var only when you need the zero value or explicit typing.
var counter int // 0var name string // ""var ready bool // falsevar items []string // nil// Zero values are ready to usecounter++ // counter is now 1items = append(items, "first")
// When you know the sizeitems := make([]string, 0, 100)// Reduces allocationsfor i := 0; i < 100; i++ { items = append(items, fmt.Sprintf("item-%d", i))}
// By runes (proper Unicode handling)for i, r := range str { fmt.Printf("position %d: rune %c\n", i, r)}// By bytesfor i := 0; i < len(str); i++ { fmt.Printf("byte %d: %x\n", i, str[i])}
// For multiple concatenations, use strings.Buildervar builder strings.Builderfor _, word := range words { builder.WriteString(word) builder.WriteString(" ")}result := builder.String()
Strings are immutable. Use strings.Builder for efficient string concatenation in loops.
type Address struct { Street string City string}type Person struct { Name string Address // Embedded}// Access embedded fields directlyp := Person{Name: "Alice"}p.Street = "123 Main St" // Not p.Address.Street
// Use pointer receiver when:// - Method modifies the receiver// - Receiver is large// - Consistency (if any method needs pointer, all should use it)func (p *Person) SetAge(age int) { p.age = age // Modifies original}// Use value receiver when:// - Method doesn't modify receiver// - Receiver is small (primitives, small structs)func (p Person) Age() int { return p.age // Safe to use value}