From go-standards
Implement or review the client layer for a Go service following architecture standards
How this skill is triggered — by the user, by Claude, or both
Slash command
/go-standards:go-clientThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Implement or review the client layer for $ARGUMENTS following the specs below exactly.
Implement or review the client layer for $ARGUMENTS following the specs below exactly.
This document describes the top-level structure for a service in this project. Before building any layer, read this file. Then read the spec file for the specific layer you are implementing.
Every service follows this layout:
services/<name>/
├── main.go # Env validation, dependency wiring, server start
├── handler/
│ └── handler.go # Transport layer
├── service/
│ └── service.go # Business logic
├── database/
│ └── database.go # Data access
├── client/
│ └── client.go # Outbound clients to other services or APIs
├── types/
│ └── types.go # Local interfaces for every dependency
└── Dockerfile
Each directory is its own Go package named after the directory.
Implement layers in this order. Each layer depends on the one before it.
types/ — define all interfaces first so every other layer has a contract to depend ondatabase/ — implement the data access layer against the Database interfaceclient/ — implement any outbound clients against their interfacesservice/ — implement business logic using only the interfaces from types/handler/ — implement the transport layer using only the Service interface from types/main.go — wire all concrete implementations together and start the serverDepend on interfaces, not implementations. Every layer holds its dependencies as interfaces from types/. Nothing is imported directly from sibling packages except in main.go.
Inject all dependencies through constructors. All dependencies are passed into New* functions. Nothing is instantiated inside the service or handler.
One responsibility per layer. Transport logic does not touch the database. Business logic does not build queries. Queries do not make outbound calls.
Crash on bad config, log on recoverable errors. Missing environment variables are fatal at startup. Cache failures and best-effort side effects are logged and swallowed. Anything that prevents a correct response is returned as an error.
Shared infrastructure lives in services/common. Reusable clients, interfaces, and domain models are defined there and imported. Never copy infrastructure code into a service.
types/types.goDefine the interfaces that every other layer in the service depends on. This file is the contract layer — it describes what each dependency must provide without specifying how.
Service, Database, SomeClient, etc.Service interface must exactly match the public methods implemented on the service struct — the handler depends on itservices/common and are imported here as neededhandler, service, database, client) — only from services/common and standard librariespackage types
import (
"context"
commontypes "github.com/kabradshaw1/story/services/common"
"github.com/kabradshaw1/story/services/common/genproto/<name>"
)
type Service interface {
MethodOne(ctx context.Context, req *proto.Request) (*proto.Response, error)
MethodTwo(ctx context.Context, req *proto.Request) (*proto.Response, error)
}
type Database interface {
FindRecord(ctx context.Context, id int) (*commontypes.SomeModel, error)
SaveRecord(ctx context.Context, record commontypes.SomeModel) error
}
type SomeClient interface {
Notify(ctx context.Context, payload SomePayload) error
}
Service interface matches the service struct's public methods exactlyservices/common, not redefinedclient/client.goHandle all outbound calls to external services or third-party APIs. This is the only layer that makes outbound network requests.
New* constructor initializes and returns the client structcontext.Context as its first argument and passes it to the underlying callpackage client
type SomeClient struct {
// underlying transport (http.Client, grpc.ClientConn, etc.)
}
func New() *SomeClient {
return &SomeClient{
// initialize transport
}
}
func (c *SomeClient) Notify(ctx context.Context, payload SomePayload) error {
if payload.RequiredField == "" {
return fmt.Errorf("RequiredField is required")
}
// construct and send request using ctx
// check response and return error on failure
return nil
}
New* constructor initializes the transportcontext.Contextnpx claudepluginhub kabradshaw1/go-standards --plugin go-standardsSOLID principles for Go 1.23+. Files < 100 lines, interfaces separated, modular architecture. Modules MANDATORY.
Writes idiomatic Go with goroutines, channels, interfaces, generics, and robust error handling. Optimizes performance with pprof and enforces production-grade testing patterns.