brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
advanced-patternsApplies advanced Go patterns including generics, reflection, functional options, and metaprogramming for performance-critical and framework-level code.
Independent GitHub snapshot · Automated classification · Original documentation governs
name: advanced-patterns description: Applies advanced Go patterns including generics, reflection, functional options, and metaprogramming for performance-critical and framework-level code. license: MIT compatibility: opencode metadata: version: "1.0.0" domain: go role: implementation scope: implementation output-format: code content-types:
Senior Go engineer applying advanced language features for framework-level and performance-critical code. This skill covers generics, reflection, functional options, compile-time assertions, and safe metaprogramming.
go:embed for compile-time asset inclusion — never hardcode file pathstype _ interface{} compile-time assertions to verify interface satisfactionunsafe unless you fully understand the memory layout and aliasing rulesUse this skill when:
go:embed)Avoid this skill for:
Choose the Right Abstraction — Decide between interfaces, generics, or composition. Checkpoint: The abstraction adds value — it reduces code duplication or enables type safety.
Implement the Pattern — Write the generic function, option type, or reflection logic.
Checkpoint: Code compiles with go vet — no type safety violations.
Add Compile-Time Assertions — Verify that types satisfy expected interfaces. Checkpoint: Compilation fails if the interface contract is violated.
Benchmark Performance — Ensure the pattern doesn't add unacceptable overhead. Checkpoint: Benchmark shows acceptable performance vs. the non-abstracted version.
Document the Pattern — Explain why the pattern was chosen and how to use it. Checkpoint: Usage examples are included in godoc comments.
Generics enable type-safe code without runtime type assertions.
// ❌ BAD: interface{} requires runtime type assertions — unsafe and slow
type Stack struct {
items []interface{}
}
func (s *Stack) Push(item interface{}) {
s.items = append(s.items, item)
}
func (s *Stack) Pop() interface{} {
if len(s.items) == 0 {
return nil
}
item := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return item
}
// Usage requires type assertion — easy to get wrong
func processStack() {
s := &Stack{}
s.Push("hello")
s.Push(42) // compiles — but wrong type!
// Runtime type assertion — panics if type is wrong
str := s.Pop().(string) // panics if the top item was 42
fmt.Println(str)
}
What's wrong:
interface{} accepts any type — s.Push(42) compiles but is semantically wrongPop().(string) panics at runtime if the type is wronginterface{} has allocation overhead — each value is boxed// Stack is a generic LIFO (last-in, first-out) data structure.
// The element type T is specified at construction time.
type Stack[T any] struct {
items []T
}
// NewStack creates a new generic stack.
func NewStack[T any]() *Stack[T] {
return &Stack[T]{items: make([]T, 0)}
}
// Push adds an item to the top of the stack.
func (s *Stack[T]) Push(item T) {
s.items = append(s.items, item)
}
// Pop removes and returns the top item.
// Returns zero value of T and false if the stack is empty.
func (s *Stack[T]) Pop() (T, bool) {
if len(s.items) == 0 {
var zero T
return zero, false
}
item := s.items[len(s.items)-1]
s.items = s.items[:len(s.items)-1]
return item, true
}
// Len returns the number of items in the stack.
func (s *Stack[T]) Len() int {
return len(s.items)
}
// IsEmpty returns true if the stack has no items.
func (s *Stack[T]) IsEmpty() bool {
return len(s.items) == 0
}
// Usage — type is enforced at compile time
func processStack() {
// String stack
strStack := NewStack[string]()
strStack.Push("hello")
strStack.Push("world")
str, ok := strStack.Pop()
if !ok {
log.Fatal("stack is empty")
}
fmt.Println(str) // "world"
// This would not compile — type is enforced:
// strStack.Push(42) // ❌ cannot use 42 (int) as string
// Int stack — separate type
intStack := NewStack[int]()
intStack.Push(42)
intStack.Push(100)
n, ok := intStack.Pop()
if ok {
fmt.Println(n) // 100
}
}
Why this works:
NewStack[string]() creates a string stackstrStack.Push(42) does not compilePop() returns (T, bool) — zero value on emptyinterface{}IsEmpty(), Len(), and the (T, bool) return make usage obviousThe functional options pattern provides a clean API for constructors with many optional parameters.
// ❌ BAD: too many parameters — hard to use, easy to forget required ones
type Server struct {
Addr string
Port int
Timeout time.Duration
CertFile string
KeyFile string
MaxConns int
KeepAlive bool
ReadBuf int
WriteBuf int
Debug bool
}
// Constructor with 10 parameters — 7 optional, 3 required
func NewServer(addr string, port int, timeout time.Duration,
certFile string, keyFile string, maxConns int,
keepAlive bool, readBuf int, writeBuf int, debug bool) *Server {
// ...
}
// Usage — which parameters are optional? What are the defaults?
// Hard to read, easy to mess up
server := NewServer("0.0.0.0", 8080, 30*time.Second,
"cert.pem", "key.pem", 100,
true, 4096, 4096, false)
What's wrong:
certFile and keyFile is a silent bug// Server provides an HTTP server with configurable options.
type Server struct {
addr string
port int
timeout time.Duration
certFile string
keyFile string
maxConns int
keepAlive bool
readBuf int
writeBuf int
debug bool
}
// Option configures a Server via functional options.
type Option func(*Server)
// WithAddr sets the server address. Default: "0.0.0.0".
func WithAddr(addr string) Option {
return func(s *Server) {
s.addr = addr
}
}
// WithPort sets the server port. Default: 8080.
func WithPort(port int) Option {
return func(s *Server) {
s.port = port
}
}
// WithTimeout sets the read/write timeout. Default: 30s.
func WithTimeout(timeout time.Duration) Option {
return func(s *Server) {
s.timeout = timeout
}
}
// WithTLS sets TLS certificate and key files.
func WithTLS(certFile, keyFile string) Option {
return func(s *Server) {
s.certFile = certFile
s.keyFile = keyFile
}
}
// WithMaxConns sets the maximum number of connections. Default: 100.
func WithMaxConns(maxConns int) Option {
return func(s *Server) {
s.maxConns = maxConns
}
}
// WithDebug enables debug logging. Default: false.
func WithDebug(enabled bool) Option {
return func(s *Server) {
s.debug = enabled
}
}
// NewServer creates a Server with the given options.
// All options are optional — defaults are applied for unset values.
func NewServer(options ...Option) *Server {
s := &Server{
addr: "0.0.0.0",
port: 8080,
timeout: 30 * time.Second,
maxConns: 100,
readBuf: 4096,
writeBuf: 4096,
}
// Apply options in order — last one wins for conflicting options
for _, opt := range options {
opt(s)
}
return s
}
// Usage — clean, readable, only specify what you need
server := NewServer(
WithPort(9090),
WithTimeout(60*time.Second),
WithTLS("cert.pem", "key.pem"),
WithDebug(true),
)
// Minimal usage — all defaults
server := NewServer()
// Override a single default
server := NewServer(WithPort(443))
Why this works:
WithPort(9090) is readableNewServerWithXxx functions don't break existing callersNewServer — caller knows what happens with no optionsWithPort("abc") doesn't compileCompile-time assertions catch interface violations at build time. go:embed includes assets at compile time.
// ❌ BAD: interface satisfaction checked at runtime — too late
type Repository interface {
Get(ctx context.Context, id string) (*User, error)
Create(ctx context.Context, user *User) error
}
type MockRepository struct{}
func (m *MockRepository) Get(ctx context.Context, id string) (*User, error) {
return nil, nil
}
// No compile-time check — if MockRepository doesn't implement Repository,
// the error surfaces only when the code is compiled (and only if someone
// tries to assign it)
func main() {
// This would silently fail to compile if MockRepository is missing a method,
// but only at the assignment site — no clear error message
var repo Repository = &MockRepository{}
_ = repo
}
// ❌ BAD: hardcoding asset paths — breaks if files move
func loadTemplate() string {
data, err := os.ReadFile("templates/profile.html")
if err != nil {
log.Fatal(err)
}
return string(data)
}
What's wrong:
MockRepository implements Repositoryos.ReadFile at runtime — template loading happens on every call// package: internal/user
// Compile-time interface assertion.
// This line will fail to compile if *MockRepository does NOT implement UserRepository.
var _ UserRepository = (*MockRepository)(nil)
// MockRepository implements UserRepository for testing.
type MockRepository struct {
users map[string]*User
}
func NewMockRepository() *MockRepository {
return &MockRepository{users: make(map[string]*User)}
}
func (m *MockRepository) Get(ctx context.Context, id string) (*User, error) {
user, ok := m.users[id]
if !ok {
return nil, fmt.Errorf("user %s not found", id)
}
return user, nil
}
func (m *MockRepository) Create(ctx context.Context, user *User) error {
if _, ok := m.users[user.ID]; ok {
return fmt.Errorf("user %s already exists", user.ID)
}
m.users[user.ID] = user
return nil
}
// Multiple interface assertions in one line
var (
_ UserRepository = (*MockRepository)(nil)
_ io.Reader = (*MockRepository)(nil)
_ io.Closer = (*MockRepository)(nil)
)
// package: web
//go:embed templates/*.html
var templateFS embed.FS
// templateCache holds pre-parsed templates.
var templateCache = sync.OnceValue(func() *template.Template {
tmpl := template.Must(template.New("").ParseFS(templateFS, "templates/*.html"))
return tmpl
})
// renderProfile renders the user profile page.
func renderProfile(w http.ResponseWriter, user *User) {
tmpl := templateCache()
if err := tmpl.ExecuteTemplate(w, "profile.html", user); err != nil {
log.Printf("template error: %v", err)
http.Error(w, "internal error", 500)
}
}
Directory structure:
myapp/
├── cmd/
│ └── server/
│ └── main.go
├── internal/
│ ├── user/
│ │ └── repository.go // UserRepository interface + MockRepository
│ └── web/
│ ├── handler.go // renderProfile with go:embed
│ └── templates/
│ ├── profile.html
│ ├── list.html
│ └── error.html
├── go.mod
└── go.sum
Why this works:
var _ UserRepository = (*MockRepository)(nil) — fails to compile if the mock doesn't implement the interface(*MockRepository)(nil) is never created at runtime — it's a compile-time only check//go:embed includes HTML templates in the binary at compile time — no runtime file readssync.OnceValue (Go 1.23+) lazily parses templates once — zero overhead on first access, cached thereafterinterface{} when the type is known at construction//go:embed for including static assets — never hardcode file pathsvar _ Interface = (*Type)(nil)// T is the element type)unsafe without a thorough understanding of memory layout and aliasing rulesgo:embed that change frequently — embedded files are baked into the binary at compile timetype _ interface{} assertions in production code without a clear reason — they add maintenance overhead| Skill | Purpose |
|---|---|
best-practices | Go idioms and code organization |
modular-design | Interface-based design that works with generics |
concurrency-patterns | Generic concurrency utilities (channels, workers) |
database-patterns | Generic repository patterns for type-safe data access |