Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
cxuu avatar

Go Interfaces

  • 919 installs
  • 137 repo stars
  • Updated June 20, 2026
  • cxuu/golang-skills

go-interfaces is an agent skill that guides developers on defining, implementing, and composing Go interfaces following Effective Go and Google and Uber style conventions.

About

go-interfaces is an Apache-2.0 cxuu/golang-skills module sourced from Effective Go, the Google Style Guide, and the Uber Style Guide for interface design and composition in Go. The skill applies when defining interfaces, choosing accept-interface versus return-concrete-type boundaries, writing type assertions with the comma-ok idiom, using type switches, or embedding types in public APIs—excluding generics-based polymorphism covered by go-generics. It ships bash scripts/check-interface-compliance.sh to find exported interfaces missing compile-time var _ I = (*T)(nil) assertions, plus references/EMBEDDING.md and references/RECEIVER-TYPE.md for deeper patterns. Core rules: consumers define interfaces, producers return concrete types, avoid embedding in public structs, prefer pointer receivers when any method mutates state, and add blank-identifier checks only when static conversions will not catch drift. Reach for go-interfaces when designing mockable Go package boundaries or reviewing whether an interface is premature.

  • Accept Interfaces, Return Concrete Types pattern explained with concrete examples
  • Scripts/check-interface-compliance.sh finds exported interfaces missing compile-time checks
  • Guidance on type assertions, type switches, embedding, and mockable boundaries
  • Decisions on when to accept an interface versus return a concrete type
  • Sourced from Effective Go, Google Style Guide, and Uber Style Guide

Go Interfaces by the numbers

  • 919 all-time installs (skills.sh)
  • +39 installs in the week ending Aug 5, 2026 (Skillselion tracking)
  • Ranked #431 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
  • Security screen: LOW risk (skills.sh audit)
  • Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cxuu/golang-skills --skill go-interfaces

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs919
repo stars137
Security audit3 / 3 scanners passed
Last updatedJune 20, 2026
Repositorycxuu/golang-skills

When should Go code accept an interface versus a concrete type?

Get expert guidance on defining, implementing, and composing Go interfaces while following community best practices.

Who is it for?

Go backend developers designing testable package APIs who want Uber and Google style guidance on interfaces, embedding, and receiver choices.

Skip if: Generics-heavy polymorphism tasks covered by go-generics or projects with no interface abstraction needs.

When should I use this skill?

The user defines Go interfaces, debates interface versus concrete parameters, needs mockable test boundaries, or runs interface compliance checks.

What you get

Interface definitions at consumption sites, concrete constructor returns, compile-time satisfaction checks, and compliance script results.

  • Interface definitions
  • Compile-time satisfaction checks
  • Compliance script output

By the numbers

  • Bundles scripts/check-interface-compliance.sh and check-interface-compliance.go
  • References 2 companion docs: EMBEDDING.md and RECEIVER-TYPE.md
  • Cites 3 style sources: Effective Go, Google Style Guide, Uber Style Guide

Files

SKILL.mdMarkdownGitHub ↗

Go Interfaces and Composition

Available Scripts

  • `scripts/check-interface-compliance.sh` — Finds exported interfaces missing compile-time compliance checks (var _ I = (*T)(nil)). Run bash scripts/check-interface-compliance.sh --help for options.

---

Accept Interfaces, Return Concrete Types

Interfaces belong in the package that consumes values, not the package that implements them. Return concrete (usually pointer or struct) types from constructors so new methods can be added without refactoring.

// Good: consumer defines the interface it needs
package consumer

type Thinger interface { Thing() bool }

func Foo(t Thinger) string { ... }
// Good: producer returns concrete type
package producer

type Thinger struct{ ... }
func (t Thinger) Thing() bool { ... }
func NewThinger() Thinger { return Thinger{ ... } }
// Bad: producer defines and returns its own interface
package producer

type Thinger interface { Thing() bool }
type defaultThinger struct{ ... }
func NewThinger() Thinger { return defaultThinger{ ... } }

Do not define interfaces before they are used. Without a realistic example of usage, it is too difficult to see whether an interface is even necessary.

---

Generality: Hide Implementation, Expose Interface

If a type exists only to implement an interface with no exported methods beyond that interface, return the interface from constructors to hide the implementation:

func NewHash() hash.Hash32 {
    return &myHash{}  // unexported type
}

Benefits: implementation can change without affecting callers, substituting algorithms requires only changing the constructor call.

---

Type Assertions: Comma-Ok Idiom

Without checking, a failed assertion causes a runtime panic. Always use the comma-ok idiom to test safely:

str, ok := value.(string)
if ok {
    fmt.Printf("string value is: %q\n", str)
}

To check if a value implements an interface:

if _, ok := val.(json.Marshaler); ok {
    fmt.Printf("value %v implements json.Marshaler\n", val)
}

---

Type Switch

It's idiomatic to reuse the variable name (t := t.(type)) — the variable has the correct type in each case branch. When a case lists multiple types (case int, int64:), the variable has the interface type.

---

Embedding

Avoid embedding types in public structs — the inner type's full method set becomes part of your public API. Use unexported fields instead.

Read references/EMBEDDING.md when using struct embedding for composition, overriding embedded methods, resolving name conflicts, applying the HandlerFunc adapter pattern, or deciding whether to embed in public API types.

---

Interface Satisfaction Checks

Use a blank identifier assignment to verify a type implements an interface at compile time:

var _ json.Marshaler = (*RawMessage)(nil)

This causes a compile error if *RawMessage doesn't implement json.Marshaler.

Use this pattern when:

  • There are no static conversions that would verify the interface automatically
  • The type must satisfy an interface for correct behavior (e.g., custom JSON

marshaling)

  • Interface changes should break compilation, not silently degrade

Don't add these checks for every interface — only when no other static conversion would catch the error.

Validation: After defining interfaces or implementations, run bash scripts/check-interface-compliance.sh to verify all concrete types have compile-time var _ I = (*T)(nil) checks.

---

Receiver Type

If in doubt, use a pointer receiver. Don't mix receiver types on a single type — if any method needs a pointer, use pointers for all methods. Use value receivers only for small, immutable types (Point, time.Time) or basic types.

Read references/RECEIVER-TYPE.md when deciding between pointer and value receivers for a new type, especially for types with sync primitives or large structs.

---

Quick Reference

ConceptPatternNotes
Consumer owns interfaceDefine interfaces where usedNot in the implementing package
Safe type assertionv, ok := x.(Type)Returns zero value + false
Type switchswitch v := x.(type)Variable has correct type per case
Interface embeddingtype RW interface { Reader; Writer }Union of methods
Struct embeddingtype S struct { *T }Promotes T's methods
Interface checkvar _ I = (*T)(nil)Compile-time verification
GeneralityReturn interface from constructorHide implementation

---

Related Skills

  • Interface naming: See go-naming when naming interfaces (the -er suffix convention) or choosing receiver names
  • Error types: See go-error-handling when implementing the error interface, custom error types, or errors.As matching
  • Generics vs interfaces: See go-generics when deciding whether generics are needed or an interface already suffices
  • Functional options: See go-functional-options when using an interface-based Option pattern for flexible constructors
  • Compile-time checks: See go-defensive when adding var _ I = (*T)(nil) satisfaction checks at API boundaries

Related skills

How it compares

Pick go-interfaces for package-boundary interface design; use go-generics when polymorphism should use type parameters instead of interfaces.

FAQ

Where should Go interfaces be defined per go-interfaces?

go-interfaces follows accept interfaces, return concrete types—define interfaces in the consumer package that uses the behavior, and return structs or pointers from constructors in the implementing package.

What script validates Go interface compliance?

go-interfaces bundles scripts/check-interface-compliance.sh, a bash helper that flags exported interfaces missing compile-time var _ Interface = (*Concrete)(nil) assertions, backed by check-interface-compliance.go.

Does go-interfaces cover Go generics?

go-interfaces explicitly does not cover generics-based polymorphism; the skill points to the separate go-generics skill when type parameters replace interface abstractions.

Is Go Interfaces safe to install?

skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

Backend & APIsbackendtestingintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.