
Golang Structs Interfaces
Go package design with consumer-side interfaces and constructors that return concrete structs.
Overview
Golang-structs-interfaces is an agent skill for the Build phase that applies idiomatic Go struct and interface placement—interfaces at consumers, concrete types from constructors.
Install
npx skills add https://github.com/samber/cc-skills-golang --skill golang-structs-interfacesWhat is this skill?
- Define interfaces at the consumer package, not at the implementor
- Return concrete structs from constructors instead of interface types
- Keep interface surfaces minimal—only methods the consumer needs
- Explains rationale: consumer-owned contracts and smaller import graphs
- Eval-oriented traps for notification/email-style dependency injection
Adoption & trust: 3.7k installs on skills.sh; 2k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your Go agent keeps defining fat interfaces in implementor packages and returning interfaces from constructors, coupling tests and imports the wrong way.
Who is it for?
Indie builders designing Go microservices, workers, or CLIs with clean package boundaries and table-driven tests.
Skip if: Greenfield learners who only need Go syntax, or projects with no multi-package Go layout yet.
When should I use this skill?
Designing Go packages with interfaces between services and clients; questions about where to define interfaces or what constructors should return.
What do I get? / Deliverables
Packages emerge with consumer-defined narrow interfaces and concrete struct constructors that are easier to mock and evolve.
- Consumer-local interface definitions with minimal method sets
- Constructors and services using concrete struct types
Recommended Skills
Journey fit
Backend structure decisions in Go belong in Build when APIs, services, and packages are shaped before ship. Focuses on structs, interfaces, and dependency boundaries—the idiomatic Go backend layering solo builders use for services and CLIs.
How it compares
Opinionated Go layering doctrine—not a linter rule pack or a generic REST handler generator.
Common Questions / FAQ
Who is golang-structs-interfaces for?
Solo builders and small teams using coding agents to structure Go backends, especially when multiple packages share dependencies like email, storage, or payments clients.
When should I use golang-structs-interfaces?
During Build (backend) when designing packages, wiring services to external clients, or reviewing where interfaces and New() return types should live.
Is golang-structs-interfaces safe to install?
It is design guidance without shell or network behavior. Check the Security Audits panel on this Prism page for the parent repository before install.
SKILL.md
READMESKILL.md - Golang Structs Interfaces
[ { "id": 1, "name": "interface-at-consumer-not-implementor", "description": "Tests whether the model defines interfaces where they are consumed, not where they are implemented", "prompt": "I'm writing a Go notification service that can send emails. I have an email package with a Client struct that has a Send method. I also have a notification package that needs to use this email client. Where should I define the interface?", "trap": "Without the skill, the model often puts the interface in the email package (the implementor). The skill says interfaces MUST be defined where consumed, not where implemented.", "assertions": [ {"id": "1.1", "text": "Interface is defined in the notification package (the consumer), NOT in the email package"}, {"id": "1.2", "text": "Interface has only the methods the notification package needs (not the full email.Client API)"}, {"id": "1.3", "text": "Email package exports a concrete Client struct, not an interface"}, {"id": "1.4", "text": "Explains WHY: keeps the consumer in control of the contract, avoids importing a package just for its interface"}, {"id": "1.5", "text": "Notification service depends on its own interface, not on email package types"} ] }, { "id": 2, "name": "return-structs-not-interfaces", "description": "Tests whether the model returns concrete types from constructors, not interfaces", "prompt": "I'm designing a Go package with a UserService that depends on a UserStore interface. Should my NewUserService constructor return *UserService or UserServiceInterface? Show me the constructor signature.", "trap": "Without the skill, the model may suggest returning an interface for 'flexibility' or 'abstraction'. The skill says functions SHOULD return concrete types -- NEVER return interfaces from constructors.", "assertions": [ {"id": "2.1", "text": "Constructor returns *UserService (concrete type), NOT an interface"}, {"id": "2.2", "text": "Constructor accepts UserStore as an interface parameter (accept interfaces)"}, {"id": "2.3", "text": "Explains WHY: callers get full access to the concrete type's fields/methods; consumers can assign to interface if needed"}, {"id": "2.4", "text": "Explicitly states that returning interfaces from constructors is bad practice"}, {"id": "2.5", "text": "The accept-interfaces-return-structs principle is stated or demonstrated"} ] }, { "id": 3, "name": "premature-interface-trap", "description": "Tests whether the model avoids creating interfaces prematurely when there is only one implementation", "prompt": "I'm writing a Go application with a UserRepository that talks to PostgreSQL. It's the only database we'll ever use. Should I create a UserRepository interface and a concrete postgresUserRepository struct, or just use a concrete struct directly?", "trap": "Without the skill, the model almost always suggests creating an interface 'for testability' even with a single implementation. The skill says NEVER create interfaces prematurely -- wait for 2+ implementations or a testability requirement.", "assertions": [ {"id": "3.1", "text": "Recommends starting with a concrete struct (not an interface) when there is only one implementation"}, {"id": "3.2", "text": "Mentions the principle: don't design with interfaces, discover them"}, {"id": "3.3", "text": "Suggests extracting an interface LATER when a second consumer or test mock demands it"}, {"id": "3.4", "text": "Acknowledges that testability IS a valid reason to add an interface, but it should be a deliberate choice"}, {"id": "3.5", "text": "Does NOT reflexively recommend creating an interface just because it is a repository"} ] }, { "id": 4, "name": "zero-value-useful-design", "description": "Tests whether the model designs structs with useful zero values using lazy initialization", "prompt": "I have a Go Reg