“Accept interfaces, return structs” in Go

Setting the scene

├── db
│ └── db.go
└── user
└── user.go

Accepting interfaces

//db.go
package
db
type Store struct {
db *sql.DB
}
func NewDB() *Store { ... } //func to initialise DBfunc (s *Store) Insert(item interface{}) error { ... } //insert itemfunc (s *Store) Get(id int) error { ... } //get item by id
//user.go
package user
type UserStore interface {
Insert(item interface{}) error
Get(id int) error
}
type UserService struct {
store UserStore
}
// Accepting interface here!
func NewUserService
(s UserStore) *UserService {
return &UserService{
store: s,
}
}
func (u *UserService) CreateUser() { ... }func (u *UserService) RetrieveUser(id int) User { ... }
  • Looser coupling, greater flexibility
  • Easier testing
//user_test.gofunc TestCreateUser(t *testing.T) {
s := new(inMemStore) //use some in-memory store...
service := NewUserService(s)

//... test the CreateUser() function
}

Return Structs

//db.go
package
db
type Store struct {
db *sql.DB
}
// returning concrete type here!
func NewDB
() *Store { ... }
func (s *Store) Insert(item interface{}) error { ... }func (s *Store) Get(id int) error { ... }

Bad example: preemptive interfaces

//postgres.go
package
db

type Store interface {
Insert(item interface{}) error
Get(id int) error
}

type MyStore struct {
db *sql.DB
}

func InitDB() Store { ... } //func to initialise DB
func
(s *Store) Insert(item interface{}) error { ... } //insert item
func
(s *Store) Get(id int) error { ... } //get item by id
//user.go
package
user

type UserService struct {
store db.Store
}

func NewUserService
(s db.Store) *UserService {
return &UserService{
store: s,
}
}
func (u *UserService) CreateUser() { ... }
func (u *UserService) RetrieveUser(id int) User { ... }

Conclusion

  1. Let the consumer define the interfaces it uses
  2. Producers should return concrete types

Additional resources

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Bryan F Tan

Bryan F Tan

85 Followers

Software Engineer | Interested in Go and distributed systems