接口 - 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() {}