Skip to content
Agentmart
Submit a tool

go-practices

Go-specific patterns for dependency injection, interface design, testing with mockery, and idiomatic project structure.

Skill by ovargas

IndexedMIT★ 14
Write a review

Chalk Labs

Need help deploying go-practices?

Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.

Book a call

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/ovargas-go-practices

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Go-specific patterns for dependency injection, interface design, testing with mockery, and idiomatic project structure.

Use cases: design, testing

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md and code. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/go-practices

What's inside

Skill name
go-practices
Description
Go-specific patterns for dependency injection, interface design, testing with mockery, and idiomatic project structure.
License
MIT
Instructions
779 lines in SKILL.md · view on GitHub

Agent Skills spec issues

  • body: 779 lines (spec recommends under 500)

Files (1)

  • SKILL.md

SKILL.md (first lines)

# Go Practices

These are Go-specific conventions that implement the architectural principles from the `design-principles` skill with concrete Go patterns. When this skill conflicts with a plugin skill, this skill wins — it reflects the project's actual conventions.

<!-- CUSTOMIZE: Add your specific Go version, module path, project layout, and any additional conventions below -->

## Dependency Inversion in Go

Go's implicit interface satisfaction makes dependency inversion natural — but only if you follow the pattern consistently.

### The Core Pattern

**Interfaces are defined where they are consumed, not where they are implemented.**

```go
// internal/user/service/user_service.go — the CONSUMER defines what it needs

type UserRepository interface {
    FindByID(ctx context.Context, id string) (*model.User, error)
    Save(ctx context.Context, user *model.User) error
}

type UserService struct {
    repo   UserRepository   // interface, not *repository.userRepository
    email  EmailSender      // interface, not *smtp.Client
    logger Logger           // interface, not *zap.Logger
}

func NewUserService(repo UserRepository, email EmailSender, logger Logger) *UserService {
    return &UserService{repo: repo, email: email, logger: logger}
}
```

### Unexported Struct, Exported Constructor, Interface Return

The implementation struct is **unexported** (lowercase). The constructor is exported and returns the **consumer's interface type**, not the concrete type. This gives two guarantees:

1. No one outside the package can depend on the concrete type
2. The compiler validates the interface contract at the implementation site — missing methods are caught here, not at the injection point

```go
// internal/user/repository/postgres_user.go — the IMPLEMENTATION

import (
    "myapp/internal/user/model"
    "myapp/internal/user/service"
)

// unexported struct — no one outside this package can name it
type userRepository struct {
    db *sql.DB
}

// exported constructor returns the consumer's interface
func NewUserRepository(db *sql.DB) service.UserRepository {
    return &userRepository{db: db}
}

func (r *userRepository) FindByID(ctx context.Context, id string) (*model.User, error) {
    // implementation
}

func (r *userRepository) Save(ctx context.Context, user *model.User) error {
    // implementation
}
```

**Why this matters:** If `userRepository` is missing a method that `service.UserRepository` requires, the compiler error appears in `NewUserRepository` — right where you're building the implementation. You don't discover it later in `main.go` or when a test fails.

### Multi-Consumer Interfaces

When the same implementation satisfies interfaces from different consumers, the constructor returns a composite interface:

```go
// Two different consumers need different views of the same repository
// package service:   type UserRepository interface { FindByID(...); Save(...) }
// package reporting: type UserQuery interface { FindByID(...); ListActive(...) }

// The constructor returns both
func NewUserRepository(db *sql.DB) interface {
    service.UserRepository
    reporting.UserQuery
} {
    return &userRepository{db: db}
}
```

Each consumer still receives only the interface it declared — the composite is only visible at the wiring site. This keeps each consumer's dependency minimal.

### Wiring — Module Factory Pattern

Each module exports a **factory function** at the module root package (`internal/user/`) that wires its own internals and returns a struct of ready-to-use components. This keeps the composition root clean — `main.go` only knows about modules, not their internal layers.

```go
// internal/user/module.go — the module's public factory
package user

import (
    "database/sql"

    "myapp/internal/user/handler"
    "myapp/internal/user/repository"
    "myapp/internal/user/service"
)

// Services exposes what this module provides to the outside world
type Services struct {
    Handler     *handler.UserHandler
    UserService service.UserService      // exposed as interface for cross-module use
}

// New wires the module's internal dependency graph and returns ready-to-use components
func New(db *sql.DB, emailSender service.EmailSender, logger service.Logger) *Services {
    repo := repository.NewUserRepository(db)               // returns service.UserRepository
    svc := service.NewUserService(repo, emailSender, logger)
    h := handler.NewUserHandler(svc)

    return &Services{
        Handler:     h,

From ovargas/virtual-team, MIT.

More from ovargas/virtual-team

Signals

Stars
14
Forks
1
Open issues
0
Last commit (this folder)
May 12, 2026 (5 months ago)
Last release
Oct 8, 2026 (21 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from ovargas

Done for you

Rather not set it up yourself?

Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.

See how we build AI agents →Read the case studies

Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.

launches shipped
50+
launches shipped
media placements
500+
media placements
founders on every account
2
founders on every account

Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block

Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.

Get go-practices running in your business

Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.

Goes to the Chalk Labs founders, not the newsletter. Privacy

Need help deploying go-practices?

CallGet help
Cite this page

go-practices skill. Agent Mart. https://agentmart.dev/skills/ovargas-go-practices (last updated 2026-10-24)