Closed peterbourgon closed 4 years ago
Lets say you want to create a CRUD app like gokit example service profilesvc
In Go kit, services are typically modeled as interfaces, and implementations of those interfaces contain the business logic.
type Service interface { PostProfile(p Profile) error GetProfile(id string) (Profile, error) DeleteProfile(id string) error }
Persistence — How should I work with databases and data stores? Even better: consider defining an interface to model your persistence operations. The interface will deal in business domain objects, and have an implementation that wraps the database handle.
type Store interface {
Insert(p Profile) error
Select(id string) (Profile, error)
Delete(id string) error
}
type databaseStore struct{ db *sql.DB }
func (s *databaseStore) Insert(p Profile) error { /* ... */ }
func (s *databaseStore) Select(id string) (Profile, error) { /* ... */ }
func (s *databaseStore) Delete(id string) error { /* ... */ }
type Service interface {
PostProfile(p Profile) error
GetProfile(id string) (Profile, error)
DeleteProfile(id string) error
}
type MyService struct {
store Store
value string
logger *log.Logger
}
func NewService(store Store, value string, logger log.Logger) *MyService {
return &MyService{
store: store,
value: value,
logger: logger,
}
}
func (s *MyService) PostProfile(p Profile) error { /* ... */ }
func (s *MyService) GetProfile(id string) (Profile, error) { /* ... */ }
func (s *MyService) DeleteProfile(id string) error { /* ... */ }
both interfaces share the same methods.
why not?
type Service interface {
PostProfile(p Profile) error
GetProfile(id string) (Profile, error)
DeleteProfile(id string) error
}
type databaseStore struct{ db *sql.DB }
func (s *databaseStore) PostProfile(p Profile) error { /* ... */ }
func (s *databaseStore) GetProfile(id string) (Profile, error) { /* ... */ }
func (s *databaseStore) DeleteProfile(id string) error { /* ... */ }
type MyService struct {
databaseStore Service
value string
logger log.Logger
}
func NewService(databaseStore Service, value string, logger log.Logger) *MyService {
return &MyService{
databaseStore: databaseStore,
value: value,
logger: logger,
}
}
func (s *MyService) PostProfile(p Profile) error { /* ... */ }
func (s *MyService) GetProfile(id string) (Profile, error) { /* ... */ }
func (s *MyService) DeleteProfile(id string) error { /* ... */ }
Because although they may have a similar method set, a Repository layer is, importantly, conceptually distinct from a Service layer.