smithery/jaimestill

go-core

Core Go development patterns and idioms. Use for package design, code organization, configuration patterns, interface definitions, or when editing .go files. Triggers: package structure, dependency hierarchy, interface contracts, config transformation, encapsulation, layered organization, parameter encapsulation, modern Go idioms.

Installation

$ npx skills add smithery/jaimestill --skill go-core

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/jaimestill.

npx skills add smithery/jaimestill

Browse all from smithery/jaimestill

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 8,440 B
  • docs SUMMARY.md 347 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Go Core Development

When This Skill Applies

  • Designing package structure
  • Organizing code within files
  • Implementing configuration patterns
  • Defining interfaces and contracts
  • Working with dependencies between packages
  • Any Go file editing

Principles

1. Configuration Transformation Pattern

Configuration packages serve as ephemeral data containers that transform into domain objects at package boundaries.

Key Pattern:

  • Configuration types handle: structure, defaults, serialization, merging
  • Domain creation happens via finalization/validation functions
  • Runtime behavior depends on initialized state, not configuration values
  • Configuration should not persist beyond initialization phase
// Configuration: structure and defaults only
type ServerConfig struct {
    Host    string        `toml:"host"`
    Port    int           `toml:"port"`
    Timeout time.Duration `toml:"timeout"`
}

// Transformation: config → domain object
func NewServer(cfg ServerConfig) (*Server, error) {
    if cfg.Port == 0 {
        cfg.Port = 8080 // Default
    }
    return &Server{
        addr:    fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
        timeout: cfg.Timeout,
    }, nil
}

Decision Framework:

  • Type 1 (Initialization-Only): Config discarded after creating domain object
  • Type 2 (Immutable Runtime Settings): Config stored throughout object lifetime
  • Type 3 (Mutable Runtime Settings): Config with validated setters and mutex protection

2. Encapsulation & Data Access Pattern

Never expose direct field access to nested structures; always provide semantic getter methods.

Bad:

// Exposes internal structure, fragile to changes
chunk.Choices[0].Delta.Content

Good:

// Semantic getter encapsulates access logic
func (c *Chunk) ExtractContent() string {
    if len(c.Choices) == 0 {
        return ""
    }
    return c.Choices[0].Delta.Content
}

// Usage
content := chunk.ExtractContent()

Benefits:

  • Hides internal structure complexity
  • Bounds checking in one place
  • Easier refactoring

3. Layered Code Organization

Structure code within files in dependency order: foundational types first.

Order:

  1. Package declaration
  2. Imports
  3. Constants
  4. Global variables
  5. Interfaces
  6. Pure types/enums (data structures without methods)
  7. Structures + methods (grouped together)
  8. Standalone functions
package example

import "context"

// Constants
const DefaultTimeout = 30 * time.Second

// Interfaces
type Repository interface {
    Find(ctx context.Context, id string) (*Entity, error)
}

// Pure types
type EntityType string

const (
    TypeA EntityType = "a"
    TypeB EntityType = "b"
)

// Structures with methods
type Entity struct {
    ID   string
    Type EntityType
}

func (e *Entity) Validate() error {
    if e.ID == "" {
        return errors.New("id required")
    }
    return nil
}

// Standalone functions
func NewEntity(id string, t EntityType) *Entity {
    return &Entity{ID: id, Type: t}
}

4. Parameter Encapsulation Rule

If a function requires more than 2 parameters, encapsulate them into a structure.

Bad:

func Execute(ctx context.Context, capability string, input string,
    timeout time.Duration, retries int, cache bool) (*Result, error)

Good:

type ExecuteRequest struct {
    Capability string
    Input      string
    Timeout    time.Duration
    Retries    int
    UseCache   bool
}

func Execute(ctx context.Context, req ExecuteRequest) (*Result, error)

Benefits:

  • Self-documenting named fields
  • Optional parameters through zero values
  • Easier extension without breaking existing calls

5. Interface-Based Layer Interconnection

Layers should interconnect exclusively through interfaces, not concrete types.

// Interface defines public API
type Renderer interface {
    Render(input []byte) ([]byte, error)
}

// Constructor returns interface, not concrete type
func NewImageMagickRenderer(cfg ImageConfig) (Renderer, error) {
    return &imageMagickRenderer{cfg: cfg}, nil
}

// Consumer stores interface dependency
type PDFDocument struct {
    renderer Renderer  // Interface, not *imageMagickRenderer
}

func NewPDFDocument(r Renderer) *PDFDocument {
    return &PDFDocument{renderer: r}
}

6. Package Dependency Hierarchy

Maintain clear, unidirectional dependencies flowing from high-level to low-level packages.

Level 0: observability/        (no dependencies)
    ↓
Level 1: messaging/            (depends on observability)
    ↓
Level 2: hub/                  (depends on messaging)
    ↓
Level 3: state/                (depends on observability)
    ↓
Level 4: workflows/            (depends on state + observability)

Rules:

  • Lower layers cannot import higher layers
  • Prevents circular dependencies
  • Each layer validates independently
  • Higher layers depend on lower-level interfaces

7. Package Organization Depth Limitation

Avoid package subdirectories deeper than one level.

Good:

pkg/
├── image/
├── cache/
└── document/

Bad:

pkg/
└── document/
    └── formats/
        └── processors/
            └── types/

Deep nesting signals architectural problems. Ask: Should this be a separate package?

8. Contract Interface Pattern

Lower-level packages define minimal interfaces that higher-level packages implement.

// In pkg/cache (lower level)
type Logger interface {
    Log(ctx context.Context, level string, msg string)
}

// Cache uses the interface, doesn't import logger package
type Cache struct {
    logger Logger
}

func NewCache(logger Logger) *Cache {
    return &Cache{logger: logger}
}
// In pkg/logger (higher level) - implements the contract
type SlogAdapter struct {
    slog *slog.Logger
}

func (a *SlogAdapter) Log(ctx context.Context, level, msg string) {
    a.slog.Log(ctx, parseLevel(level), msg)
}

// Usage: dependency injection
cache := NewCache(&SlogAdapter{slog: slog.Default()})

9. Modern Go Idioms (Go 1.25+)

Leverage latest language features and standard library methods.

// sync.WaitGroup.Go() - Combines Add(1) + goroutine launch + implicit Done()
var wg sync.WaitGroup
for _, task := range tasks {
    wg.Go(func() {
        process(task)
    })
}
wg.Wait()

// for range n - Integer range without index variable
workers := min(runtime.NumCPU()*2, len(tasks))
for range workers {
    wg.Go(func() { /* worker */ })
}

// min()/max() built-ins
limit := min(requested, maxAllowed)

// errors.Join() - Combine multiple errors
var errs []error
for _, item := range items {
    if err := validate(item); err != nil {
        errs = append(errs, err)
    }
}
return errors.Join(errs...)

// defer close(channel) - Always in sender goroutine
go func() {
    defer close(results)
    for item := range input {
        results <- process(item)
    }
}()

Anti-Patterns

Leaky Configuration

// Bad: Config persists and is accessed at runtime
type Service struct {
    config Config  // Stored and used later
}

func (s *Service) Process() {
    timeout := s.config.Timeout  // Accessing config at runtime
}
// Good: Config transformed at construction
type Service struct {
    timeout time.Duration  // Only the needed value stored
}

func NewService(cfg Config) *Service {
    return &Service{timeout: cfg.Timeout}
}

God Packages

// Bad: Package does too many things
package utils

func ParseJSON() {}
func SendEmail() {}
func ResizeImage() {}
func ValidateInput() {}
// Good: Single responsibility packages
package json
package email
package image
package validation

Circular Dependencies

// Bad: A imports B, B imports A
package a
import "project/b"

package b
import "project/a"  // Circular!
// Good: Extract shared interface to lower level
package contracts
type Processor interface { Process() }

package a
import "project/contracts"

package b
import "project/contracts"