写得比较长,🙏
问题是这样的,A 层依赖于 B 层,A 作为使用者想隔离 B 的依赖,定义 interface 的时候该如何设计?
比如:controller 层从 JSON 绑定 model ,后续需要调用 service 层的用户处理逻辑
代码如下:
// package main
// 构造 user service 实例
userService := service.NewUserService(...)
// userApp 依赖 user service
userApp := controller.NewUserApp(userService)
-----
// package controller
type UserApp struct {
svc *service.UserService
}
type User struct {
...
}
func NewUserApp(svc *service.UserService) *UserApp {
return &UserApp{svc: svc}
}
// handler
func (app* UserApp) Add(c Context) error {
// controller 层绑定 model
var user User
if err := bindJSON(c, &user); err != nil {
return err
}
// model 转换
var svcUser service.User
toSvcUser(user, &svcUser);
// 调用 service 逻辑
return app.svc.AddUser(svcUser)
}
----
// package service
type UserService struct {
...
}
func NewUserService(...) *UserService {
...
}
这里为了方便测试 controller ,希望把 service 的依赖作为一个接口,变成下面这样:
// package controller
type IUserService interface {
AddUser(user xxx) error
}
type UserApp struct {
svc IUserService
}
func NewUserApp(svc IUserService) *UserApp {
return &UserApp{svc: svc}
}
我的疑问是这里的接口应该是下面的哪一种:
方法 1:
type IUserService interface {
// 使用自己包的类型
AddUser(u User)
}
方法 2:
type IUserService interface {
// 使用依赖包的类型
AddUser(u service.User)
}
方法 3:
另开一个 models 包。把类型全塞 models 包里面,controller 层和 service 层都依赖于 models
这种做法似乎不推荐吗?
https://rakyll.org/style-packages/
如果是第一种的话,我是不是还需要在 controller 层加一个 adapter 来适配接口:
// package controller
type UserServiceAdapter struct {
svc *service.UserService
}
// adapter 实现接口
func (adapter *UserServiceAdapter) AddUser(user User) error {
// model 转换
var svcUser service.User
toSvcUser(user, &svcUser);
// 调用 service 逻辑
return adapter.svc.AddUser(svcUser)
}
func NewUserServiceAdapter(svc *service.UserSvC) *UserServiceAdapter{
return &UserServiceAdapter{ svc: svc }
}
// package
// 构造 user service 实例
userService := service.NewUserService(...)
userApp := controller.NewUserApp(
// 创建 adapter ,adapter 满足接口
controller.NewUserServiceAdapter(userService)
)
相关参考链接:
https://tutorialedge.net/golang/accept-interfaces-return-structs/
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.