接口 - meetbill/chi GitHub Wiki
+---------------+
| server |
+-------+-------+
|
|
+-------V-------+
| router |
+-------+-------+
|
| req ghttp.Request
+-------V-------+
| controller |
+-------+-------+
|
| params struct
+-------V------------------------------------------------------------------------------------+
| serivce |
+-------+---------------------------------------------------+--------------------------------+
| model struct |
| |
+-------V-------+ +SDK-------------------------------V--------------------------------+
| dao | |+XAgent---------------------------------------------+ +xx---------+|
+-------+-------+ ||const.go interface.go xagent_sdk.go xagent_test.go | |... ||
| |+---+---------+------------+------------------------+ +-----------+|
| +----|---------|------------|---------------------------------------+
+-------V-------+ | | |
| database | +---------|------------|------------------------------------> 常量
+---------------+ +------------|------------------------------------> 接口(XAgentService)、参数和返回结果结构体定义
+------------------------------------> agent 结构体, 方法和 XAgentService New 方法
---------------------------------------------
(1)我们为什么要提供New方法?
因为我们的service struct 是小写开头,所以如果我们不用New方法的话,外部就没办法调用这个struct
(2) 我们打算对外提供的 service struct那为什么要小写开头?
因为如果我们大写开头,那么别人调用的时候,struct中可能部分元素不给赋值,则默认空值。这样会导致service的部分方法调用时会Panic。所以这里相当于是一个强制调用者必须按照我们的定义(也就是New方法)进行传参赋值
(3) 那我们可以通过 New 方法对外进行返回service结构体从而提供服务,为什么要返回接口呢?
第一个,用接口的话,使用者点进来第一时间就知道你提供了哪些方法(全部暴露在interface),简单明了,不用的话我还得一个个去找你对外提供了哪些服务,你这10个文件,我十个都需要看一下
第二个,如果我们不使用接口,那么我们就和golang的基本理念相违背了 包中小写开头类型不对外进行暴露 原则,而使用接口则我们对外暴露接口即可
(4) 里面有一行代码 var _ Service = (*service)(nil) 这句代码是用来做什么的
这个其实在很多开源项目中会这样写,具体用处就是校验*service这个结构体,有没有实现Service这个接口
可参考这个github issue:https://github.com/uber-go/guide/issues/25
例子
https://github.com/xinliangnote/go-gin-api
go-gin-api-master/internal/services/admin/service.go
package admin
import (
"github.com/xinliangnote/go-gin-api/internal/pkg/core"
"github.com/xinliangnote/go-gin-api/internal/repository/mysql"
"github.com/xinliangnote/go-gin-api/internal/repository/mysql/admin"
"github.com/xinliangnote/go-gin-api/internal/repository/redis"
)
var _ Service = (*service)(nil)
type Service interface {
i()
Create(ctx core.Context, adminData *CreateAdminData) (id int32, err error)
PageList(ctx core.Context, searchData *SearchData) (listData []*admin.Admin, err error)
PageListCount(ctx core.Context, searchData *SearchData) (total int64, err error)
UpdateUsed(ctx core.Context, id int32, used int32) (err error)
Delete(ctx core.Context, id int32) (err error)
Detail(ctx core.Context, searchOneData *SearchOneData) (info *admin.Admin, err error)
ResetPassword(ctx core.Context, id int32) (err error)
ModifyPassword(ctx core.Context, id int32, newPassword string) (err error)
ModifyPersonalInfo(ctx core.Context, id int32, modifyData *ModifyData) (err error)
CreateMenu(ctx core.Context, menuData *CreateMenuData) (err error)
ListMenu(ctx core.Context, searchData *SearchListMenuData) (menuData []ListMenuData, err error)
MyMenu(ctx core.Context, searchData *SearchMyMenuData) (menuData []ListMyMenuData, err error)
MyAction(ctx core.Context, searchData *SearchMyActionData) (actionData []MyActionData, err error)
}
type service struct {
db mysql.Repo
cache redis.Repo
}
func New(db mysql.Repo, cache redis.Repo) Service {
return &service{
db: db,
cache: cache,
}
}
func (s *service) i() {}