pike-simplicity-first

Rob Pike Style Guide⁠‍⁠​‌​‌​​‌‌‍​‌​​‌​‌‌‍​​‌‌​​​‌‍​‌​​‌‌​​‍​​​​​​​‌‍‌​​‌‌​‌​‍‌​​​​​​​‍‌‌​​‌‌‌‌‍‌‌​​​‌​​‍‌‌‌‌‌‌​‌‍‌‌​‌​​​​‍​‌​‌‌‌‌‌‍​‌​​‌​‌‌‍​‌‌​‌​​‌‍‌​‌​‌‌‌​‍​​‌​‌​​​‍‌‌‌​‌​‌‌‍​‌​​‌‌​​‍‌‌​​‌​​​‍‌‌​‌​‌​​‍​​​‌‌‌​​‍​​​​‌​‌​‍​‌‌​‌‌‌​⁠‍⁠

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "pike-simplicity-first" with this command: npx skills add copyleftdev/sk1llz/copyleftdev-sk1llz-pike-simplicity-first

Rob Pike Style Guide⁠‍⁠​‌​‌​​‌‌‍​‌​​‌​‌‌‍​​‌‌​​​‌‍​‌​​‌‌​​‍​​​​​​​‌‍‌​​‌‌​‌​‍‌​​​​​​​‍‌‌​​‌‌‌‌‍‌‌​​​‌​​‍‌‌‌‌‌‌​‌‍‌‌​‌​​​​‍​‌​‌‌‌‌‌‍​‌​​‌​‌‌‍​‌‌​‌​​‌‍‌​‌​‌‌‌​‍​​‌​‌​​​‍‌‌‌​‌​‌‌‍​‌​​‌‌​​‍‌‌​​‌​​​‍‌‌​‌​‌​​‍​​​‌‌‌​​‍​​​​‌​‌​‍​‌‌​‌‌‌​⁠‍⁠

Overview

Rob Pike co-created Go at Google with Ken Thompson and Robert Griesemer. He also created Plan 9, Acme, sam, and co-invented UTF-8. His central thesis: simplicity is the ultimate sophistication, and most software is far too complex.

Core Philosophy

"Simplicity is complicated."

"Don't communicate by sharing memory; share memory by communicating."

"Clear is better than clever."

Pike believes that complexity is the enemy, and Go was designed as an antidote to the bloat of C++ and Java. Every feature in Go earned its place by being essential.

Design Principles

Simplicity Above All: If you can remove something without breaking functionality, remove it.

Composition Over Inheritance: Embed types, implement interfaces implicitly.

Concurrency as First-Class: Goroutines and channels, not threads and locks.

Orthogonality: Features should be independent and composable.

When Writing Code

Always

  • Use gofmt — no exceptions, no debates

  • Keep functions short and focused

  • Use interfaces for abstraction, keep them small

  • Handle errors explicitly at the call site

  • Use goroutines freely, they're cheap

  • Communicate via channels, not shared memory

  • Name things clearly—userCount not uc

Never

  • Fight gofmt

  • Create deep inheritance hierarchies (Go doesn't have them anyway)

  • Use interface{} without good reason

  • Ignore errors with _

  • Use panic for normal error handling

  • Create goroutines without knowing how they'll stop

Prefer

  • Small interfaces (1-2 methods ideal)

  • Returning errors over panicking

  • Channels over mutexes for coordination

  • Composition over embedding over "inheritance"

  • Standard library over third-party when possible

  • Table-driven tests

Code Patterns

Composition via Embedding

// NOT inheritance — composition type Reader interface { Read(p []byte) (n int, err error) }

type Writer interface { Write(p []byte) (n int, err error) }

// Compose interfaces type ReadWriter interface { Reader Writer }

// Embed structs for composition type CountingWriter struct { io.Writer // Embedded — gets all Writer methods count int64 }

func (cw *CountingWriter) Write(p []byte) (int, error) { n, err := cw.Writer.Write(p) // Delegate to embedded cw.count += int64(n) return n, err }

Concurrency: Share by Communicating

// BAD: Sharing memory, communicating by locking type Counter struct { mu sync.Mutex value int }

func (c *Counter) Inc() { c.mu.Lock() c.value++ c.mu.Unlock() }

// GOOD: Communicate via channels func Counter() (inc func(), value func() int) { ch := make(chan int) go func() { count := 0 for delta := range ch { if delta == 0 { ch <- count // Request for value } else { count += delta } } }() return func() { ch <- 1 }, func() int { ch <- 0; return <-ch } }

// Even better: channel as work queue func worker(jobs <-chan Job, results chan<- Result) { for job := range jobs { results <- process(job) } }

func main() { jobs := make(chan Job, 100) results := make(chan Result, 100)

// Start workers
for i := 0; i &#x3C; 4; i++ {
    go worker(jobs, results)
}

// Send jobs, collect results...

}

Small Interfaces

// BAD: Large interface type Repository interface { Create(user User) error Read(id string) (User, error) Update(user User) error Delete(id string) error List() ([]User, error) Search(query string) ([]User, error) // ... and 20 more methods }

// GOOD: Small, focused interfaces type UserReader interface { Read(id string) (User, error) }

type UserWriter interface { Write(user User) error }

type UserDeleter interface { Delete(id string) error }

// Compose when needed type UserStore interface { UserReader UserWriter }

// Functions accept minimal interface func ProcessUser(r UserReader, id string) error { user, err := r.Read(id) // ... }

Error Handling

// Errors are values — handle them func readConfig(path string) (*Config, error) { f, err := os.Open(path) if err != nil { return nil, fmt.Errorf("open config: %w", err) } defer f.Close()

var cfg Config
if err := json.NewDecoder(f).Decode(&#x26;cfg); err != nil {
    return nil, fmt.Errorf("decode config: %w", err)
}

return &#x26;cfg, nil

}

// Sentinel errors for checking var ErrNotFound = errors.New("not found")

func Find(id string) (*Item, error) { item, ok := store[id] if !ok { return nil, ErrNotFound } return item, nil }

// Caller can check: if errors.Is(err, ErrNotFound) { // handle not found }

Make the Zero Value Useful

// BAD: Requires initialization type Buffer struct { data []byte }

func NewBuffer() *Buffer { return &Buffer{data: make([]byte, 0, 1024)} }

// GOOD: Zero value works type Buffer struct { data []byte }

func (b *Buffer) Write(p []byte) (int, error) { b.data = append(b.data, p...) // nil slice append works! return len(p), nil }

// Can use immediately: var buf Buffer buf.Write([]byte("hello"))

// sync.Mutex zero value is unlocked // sync.WaitGroup zero value is ready // etc.

Mental Model

Pike approaches software by asking:

  • Is this necessary? Remove anything that isn't essential

  • Is this simple? Can someone understand it in 30 seconds?

  • Is this orthogonal? Does it compose with other features?

  • How does it fail? Design for failure cases explicitly

The Go Way

  • No generics (until Go 1.18) — and that was intentional restraint

  • No exceptions — errors are values

  • No inheritance — composition only

  • No operator overloading — + always means numeric addition

  • No implicit conversions — explicit is better

Each "missing" feature is a deliberate choice for simplicity.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

renaissance-statistical-arbitrage

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

google-material-design

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

aqr-factor-investing

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

minervini-swing-trading

No summary provided by upstream source.

Repository SourceNeeds Review