writing-go-code
Go Development Standards
Project-specific Go coding standards for this codebase.
Companion Skills
applying-effective-go— General Go idioms from the official Effective Go documentation (naming, control flow, error handling philosophy, concurrency patterns). Complementary to this skill.writing-go-tests— Test conventions, mock usage, assertions, naming. Always load when writing test files.
Code Organization
// 1. Struct definition
type MyService struct {
logger Logger
fs FileSystem
}
// 2. Interface verification (immediately after struct)
var _ Service = (*MyService)(nil)
// 3. Constructor with dependency injection
func NewMyService(logger Logger, fs FileSystem) *MyService {
return &MyService{logger: logger, fs: fs}
}
Dependency Injection
Always inject dependencies via constructors. Never create dependencies internally.
// Good: dependencies injected
func NewHandler(
logger Logger,
service Service,
validator Validator,
) *Handler {
return &Handler{
logger: logger,
service: service,
validator: validator,
}
}
// Bad: dependencies created internally
func NewHandler() *Handler {
return &Handler{
logger: NewDefaultLogger(), // Don't do this
service: NewService(), // Don't do this
}
}
Mock Generation
Mocks use mockery with moq template. To regenerate all mocks:
mockery
Mock types are prefixed with Moq (e.g., MoqLogger, MoqFileSystem). For mock usage conventions in tests, see the writing-go-tests skill.
Optional Types
Use samber/mo for safer nil handling:
import "github.com/samber/mo"
type Config struct {
Shell mo.Option[string]
}
if shell, ok := config.Shell.Get(); ok {
// use shell
}
Code Formatting
- Line length: 120 characters max.
- Vertically align function arguments when there are multiple arguments.
- Insert blank lines between logical sections of code.
- Do not separate error unwrapping from related code with a blank line; treat it as part of the same section.
// Good: error handling is part of the same section
result, err := doSomething()
if err != nil {
return fmt.Errorf("failed to do something: %w", err)
}
// Next logical section starts after blank line
processResult(result)
Documentation
End all type and function comments with a period, following Go conventions.
// MyService handles business logic for the application.
type MyService struct {
// ...
}
// Process executes the main workflow and returns the result.
func (s *MyService) Process(ctx context.Context) error {
// ...
}
Key Rules
- Use the Go standard library whenever possible. Only use third-party libraries when necessary.
- Pre-allocate slices/maps when size is known.
- Wrap OS operations in interfaces for mockability.
- Never edit mock files manually.
More from mrpointer/dotfiles
configuring-zsh
Configure and troubleshoot Zsh shell. Use when editing .zshenv, .zprofile, .zshrc, .zlogin, or .zlogout, setting up powerlevel10k prompt, configuring oh-my-zsh or sheldon plugin manager, fixing PATH or environment variables, debugging slow shell startup, setting up completions/compinit/fpath, or working with zsh-autocomplete, zsh-autosuggestions, or zsh-syntax-highlighting plugins.
20configuring-github-actions
Create and troubleshoot GitHub Actions workflows. Use when editing .github/workflows files, setting up CI/CD pipelines, configuring matrix builds for multi-platform testing, debugging failing workflows, adding caching or artifacts, running E2E tests in containers, or asking "why is my workflow failing" or "how do I test on multiple OSes".
11managing-chezmoi
Manage dotfiles with chezmoi. Use when adding files to chezmoi, running chezmoi add/apply/diff/status, debugging why changes aren't appearing, working with chezmoi templates or .chezmoiignore, understanding source vs target files, resolving merge conflicts, or asking "how do I manage this file with chezmoi". For chezmoi command uncertainties, use Context7 to fetch latest docs.
2writing-go-tests
Write Go tests following project conventions. Use when creating test files, writing unit or integration tests, choosing mocks, or setting up test fixtures. Covers test naming, assertions, mock usage, table-driven patterns, and common pitfalls.
1testing-go-code
Run Go unit tests, coverage reports, and benchmarks. Use when you need to run tests, check coverage, run benchmarks, or regenerate mocks after interface changes.
1linting-go-code
Lint and format Go code. Use when you need to run linters, fix lint errors, format code, or understand why a linter is complaining.
1