returninterface
About 307 wordsAbout 1 min
2025-01-16
Enforces "accept interfaces, return structs" pattern.
Category
Clean Code
What It Checks
This analyzer detects functions that return interfaces when they should return concrete types.
Why It Matters
The Go proverb: "Accept interfaces, return structs."
Returning interfaces:
- Limits what callers can do with the result
- Hides implementation details unnecessarily
- Makes testing harder
- Prevents callers from accessing struct fields
Examples
Bad: Return Interface
type UserRepository interface {
Get(id string) (*User, error)
Save(user *User) error
}
func NewUserRepository(db *sql.DB) UserRepository { // Returns interface
return &userRepository{db: db}
}Good: Return Concrete Type
type UserRepository struct {
db *sql.DB
}
func NewUserRepository(db *sql.DB) *UserRepository { // Returns struct
return &UserRepository{db: db}
}
func (r *UserRepository) Get(id string) (*User, error) {
// ...
}
func (r *UserRepository) Save(user *User) error {
// ...
}Accept Interface
// Accept interface - callers can pass any implementation
func ProcessUsers(repo UserGetter, ids []string) ([]*User, error) {
var users []*User
for _, id := range ids {
user, err := repo.Get(id)
if err != nil {
return nil, err
}
users = append(users, user)
}
return users, nil
}
type UserGetter interface {
Get(id string) (*User, error)
}Exceptions
The analyzer exempts several common patterns:
Factory Functions: Functions with these prefixes are exempt:
New,Create,Build,Make,Get,Open,Connect
Error Interfaces: Functions returning error interfaces are exempt:
- Standard
errortype - Custom error types like
MyError,humane.Error
Standard Library Interfaces:
io.Reader,io.Writer,io.Closer,io.ReadClosercontext.Contexthttp.Handler,http.RoundTripperfmt.Stringer,sort.Interface
// Plugin system - interface return is appropriate
func LoadPlugin(path string) (Plugin, error) {
// Returns interface because implementation is unknown
}
// Error interfaces are fine
func ProcessData(data []byte) humane.Error {
// ...
}Configuration
# .golint-sl.yaml
analyzers:
returninterface: true # enabled by defaultWhen to Disable
- Plugin systems
- Factory functions for multiple implementations
analyzers:
returninterface: falseRelated Analyzers
- emptyinterface - Interface{} usage
- interfaceconsistency - Interface implementations
