New FAQ entries
peterbourgon opened this issue · 2 comments
peterbourgon commented
- Introduction — Understanding Go kit key concepts
- Transport, Endpoint, Service
- Middlewares in general
- Endpoint Middleware, Service Middleware
- Dependency Injection — How do I wire up my Component Graph?
- Configuration — How should Go kit services be configured?
- Persistence — How should Go kit services manage persistence?
- Repository pattern
- e.g. In-Memory & PostgreSQL
- Caching — How should Go kit services interface with cache systems?
- Logging — How should Go kit services manage logs?
- Metrics — How should Go kit services be instrumented?
- Service Discovery — How should Go kit services interact with service discovery systems?
- Templating — What if Go kit services want to render web pages?
- How do I decide where to place a bit of functionality?
andreaslacza commented
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 { /* ... */ }peterbourgon commented
Because although they may have a similar method set, a Repository layer is, importantly, conceptually distinct from a Service layer.