Либо, либо ни то, ни другое - на мой взгляд, это не имеет значения, потому что идиоматический подход состоял бы в том, чтобы организовать эти понятия с помощью интерфейсов:
package user
type User ...
type Inserter interface { Insert(User) error }
type Deleter interface { Delete(User) error }
type Manager interface { Inserter, Deleter } // bloated interface
User
в этом случае, вероятно, является конкретным типом строки, как в вашем примере, но можно было бы также сделать его интерфейсом, в котором эти типы не упоминаются.
Если вы пишете функции, которые ссылаются на эти интерфейсы, вы можете быстро склеить их, используя встраивание и продвигаемые поля. .
В вашем случае очевидно, что придерживаться первого стиля реализации намного проще:
type userManager struct { ... }
func (userManager) Insert(u User) error { ... }
func (userManager) Delete(u User) error { ... }
userManager
— это частный тип, поэтому его можно изменять без опасений, пока он продолжает удовлетворять общедоступные интерфейсы.
Отделение интерфейсов от реализации значительно упрощает их сужение, поэтому вместо простого «менеджера пользователей» или чего-то еще вы можете узнать, какие интерфейсы вам действительно нужны для задач. Между прочим, у этого подхода есть замечательное свойство: он хорошо согласуется с моделью возможностей объекта, что помогает упростить такие вещи, как управление доступом на основе ролей.
person
nothingmuch
schedule
18.02.2017