Irbisa · Cheatsheet
Structs, Methods & Interfaces
Structs, embedding, method sets, implicit interfaces, type switches
How does Go do OOP without classes: what does it use for encapsulation, inheritance and polymorphism?
What is the difference between a keyed struct literal
T{Name: v}and a positional oneT{v1, v2}, and which should you write?package geo import "net" type Point struct{ X, Y int }…Why can't you add a method to
time.Timeorint, and what do you do instead?package temp import ( "fmt" "time")…Which structs can you compare with
==or use as a map key, and what changes when you add a[]stringfield?package keys type Point struct{ X, Y int } type Loose struct{ Tags []string }…What is the empty struct
struct{}used for in Go?package sig import "fmt" type noopLogger struct{} // no state, only methods…What is an interface in Go, and how does implicit satisfaction differ from
implementsin Java?package shapes import ( "fmt" "math")…What is the empty interface
any, when is it the right type, and when should you use generics instead?package pick import "cmp" // any: the caller gets any back and must assert; nothing is checked.func MaxAny(xs []any) any {…What is the difference between a type assertion
v.(T)and a type switch, and what happens when an assertion fails with and withoutok?package tsw import ( "fmt" "net/http")…What is
fmt.Stringer, and why doesfmt.Sprintf("%v", u)insidefunc (u User) String() stringoverflow the stack?package user import "fmt" type User struct { Name string…When do you give a method a pointer receiver instead of a value receiver?
package counter type Counter struct{ n int } // wrong: the receiver is a copy; the caller's Counter never changes.func (c Counter) IncBroken() { c.n++ }…What is a method set, and why does
Worker{}not satisfy an interface whoseRunmethod has a pointer receiver?package work type Worker struct{ done int } func (w *Worker) Run() { w.done++ } // in the method set of *Worker onlyfunc (w Worker) Done() int { return w.done } // in both method sets…Go has no constructors. What is the
NewTconvention, and when do you reach for functional options?package server import ( "errors" "log/slog" "time"…What does this program print, and why doesn't
Outer.Nameoverride theNamethatDescribecalls?type Base struct{} func (Base) Name() string { return "base" }func (b Base) Describe() string { return "I am " + b.Name() } type Outer struct{ Base } func (Outer) Name() string { return "outer" } func main() { o := Outer{} fmt.Println(o.Name()) fmt.Println(o.Describe()) fmt.Println(o.Base.Name())}What does embedding an interface in a struct do, and when is it useful?
package mw import ( "log/slog" "net/http" "sort"…Find the bug: the audit log written by
logEventholds only timestamps;nameanduser_idnever appear.type Event struct { time.Time Name string `json:"name"` UserID int64 `json:"user_id"`} func logEvent(w io.Writer, e Event) error { b, err := json.Marshal(e) if err != nil { return err } _, err = w.Write(append(b, '\n')) return err}What is a struct tag, how do packages like
encoding/jsonread it, and what happens when a tag has a typo?package api import ( "encoding/json" "fmt" "reflect"…Go has no
implementskeyword. How do you make the compiler check that a type satisfies an interface right where the type is defined?package store import "context" type Store interface { Get(ctx context.Context, key string) ([]byte, error)…Where should an interface be declared in Go, and what does "accept interfaces, return structs" mean?
What does this code print, and why does calling a method on a nil pointer not panic?
type Tree struct { Left, Right *Tree Val int} func (t *Tree) Sum() int { if t == nil { return 0 } return t.Val + t.Left.Sum() + t.Right.Sum()} func main() { var t *Tree fmt.Println(t.Sum()) fmt.Println((&Tree{Val: 1, Left: &Tree{Val: 2}}).Sum())}This code prints
falseand then panics. Why iswnot nil, and how do you fixauditLog?func auditLog(enabled bool) io.Writer { var buf *bytes.Buffer if enabled { buf = new(bytes.Buffer) } return buf} func main() { w := auditLog(false) fmt.Println(w == nil) w.Write([]byte("x"))}When are two interface values equal under
==, and when does that comparison panic at run time?package ifeq import ( "errors" "fmt")…Find the bug: under load the service using this
Cachesometimes crashes withconcurrent map read and map writeand sometimes hangs.type Cache struct { mu sync.Mutex m map[string]string} func (c *Cache) Set(k, v string) { c.mu.Lock() defer c.mu.Unlock() c.m[k] = v} func (c Cache) Get(k string) string { c.mu.Lock() defer c.mu.Unlock() return c.m[k]}How is an interface value represented at run time (
eface,iface,itab), and what does putting a value into an interface cost?// Simplified from runtime/runtime2.go and internal/abi (Go 1.25).package sketch import "unsafe" type _type struct{} // size, hash, kind, GC data...…Two structs with the same four fields measure 24 and 16 bytes under
unsafe.Sizeof. What decides struct layout, and when is reordering fields worth it?package layout import ( "fmt" "unsafe")…