| sdk | ||
| services | ||
| vendor | ||
| .gitignore | ||
| go.mod | ||
| go.sum | ||
| README.md | ||
gaore-common-sdk-go
1.目录架构
├── README.md
├── sdk
│ ├── auth `认证类`
│ ├── client.go `客户端主入口类`
│ ├── config.go
│ ├── requests `请求类`
│ ├── responses `响应类`
│ └── utils `工具类`
└── services
└── jedi
2.引入
go get -u golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk
或 Go Module
import "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk"
3.服务端认证及返回处理
调用 auth.UnSign 方法,提供*http.Request请求实例,以及signer.Signer 签名器(签名器需要包括凭据)
即可完成整个验签过程
这里以beego为例 :
package applications
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/context"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth/credentials"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/auth/signers"
"golib.gaore.com/GaoreGo/grlogs"
)
func init() {
// 过滤器
beego.InsertFilter("/api/*", beego.BeforeRouter, func(context *context.Context) {
httpRequest := context.Request
err := auth.UnSign(httpRequest, signers.NewAccessKeySigner(&credentials.AccessKeyCredential{
AccessKeyId: "aaaaaa",
AccessKeySecret: "bbbbbb",
AccessKeyFrom: context.Input.Param("access_from"),
}))
if err != nil {
resp := response.NewJsonByDefaultFailed()
resp.Msg = err.Error()
resp.Code = 10086
var (
hasIndent = beego.BConfig.RunMode != beego.PROD
)
context.Output.Status = 500
context.Output.JSON(resp, hasIndent, false)
}
})
}
服务端返回的响应体为以下结构的json字符流, code,status,msg 这三个字段最好要包含且数据类型要一致 , data 部分为业务内容,自行定义
{
"code": 1001,
"msg": "不能为空",
"status": false,
"data": {
...
}
}
4.sdk编写
在services目录下以服务归类新建文件夹, 如jedi为短信服务,以 RpcRequest 和 BaseResponse 以基类写好请求子类和响应子类。一个请求接口对应一对请求和响应类。
import "golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk"
const (
HOST = "jedi" // 如果非全域名会自动补全.gaore.com , 如jedi 会自动补全jedi.goare.com, 也可以打全域名 test.uu89.com
VERSION = "2020-08-04"
)
type Client struct {
sdk.Client
}
func NewClientWithAccessKey(accesskey, secrect, source string) (client *Client, err error) {
client = &Client{}
err = client.InitWithAccessKey(accesskey, secrect, source)
return
}
func (c *Client) Test(req *DemoTestRequest) (response *DemoTestResponse, err error) {
response = CreateDemoTestResponse()
err = c.DoAction(req, response)
return
}
请求类,对参数用标签解释, 如 position:"Query" field:"param_1" default:"" , 有三个字段 position , field, default
-
position为标志该参数为请求体对应的位置,Queryquery参数,Bodypost请求体参数,Head请求头参数 -
field解释成参数实际名称 -
default默认值
type DemoTestRequest struct {
*requests.RpcRequest
Param1 string `position:"Query" field:"param_1" default:"" `
Param2 int `position:"Query" field:"param_2" default:"10086" `
Param3 bool `position:"Query" field:"param_3" default:"false" `
}
对应解释成http请求为:
GET param_1=111¶m_2=10086¶m_3=false
完整示例:
package jedi
import (
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/requests"
"golib.gaore.com/GaoreGo/gaore-common-sdk-go/sdk/responses"
)
// 定义请求体
type DemoTestRequest struct {
*requests.RpcRequest
Param1 string `position:"Query" field:"param_1" default:"" `
Param2 int `position:"Query" field:"param_2" default:"10086" `
Param3 bool `position:"Query" field:"param_3" default:"false" `
}
func CreateDemoTestRequest() (req *DemoTestRequest) {
req = &DemoTestRequest{RpcRequest: &requests.RpcRequest{}}
// InitWithApiInfo 初始化请求,有三个参数,域名,版本,和路径
// 域名参数如果非全域名会自动补全.gaore.com , 如jedi 会自动补全jedi.goare.com, 也可以打全域名 test.uu89.com
req.InitWithApiInfo(HOST, VERSION, "/api/sms/Index")
// 定义 请求方法 POST 或 GET
req.Method = requests.GET
return
}
// 定义响应体
type DemoTestResponse struct {
*responses.BaseResponse
Data DemoTestResponseData `json:"data"`
}
type DemoTestResponseData struct {
Account string `json:"account"`
Total int `json:"total"`
}
func CreateDemoTestResponse() *DemoTestResponse {
return &DemoTestResponse{
BaseResponse: &responses.BaseResponse{},
}
}
终端调试打开方式, 需要在系统环境变量上加入(三选一):
DEBUG=sdk,signer,request
5.测试用例编写要求
新增或修改 services/* 下的接口封装时,必须配套可编译的测试,并遵循下列约定(风格可参考 services/cs/client_test.go 与 services/game/client_test.go)。
5.1 单测职责(一条用例里要覆盖什么)
- 请求侧:构造
Create*Request,填入业务参数后调用requests.InitParam(req),再断言 HTTP 方法、GetActionName()路径、以及 Query/Form 等关键参数是否注入正确。 - 调用侧:使用本服务
NewClient()(或项目约定的构造方式)真实调用Client上对应方法,覆盖DoAction与签名、序列化整条链路。 - 响应侧:断言
err == nil、响应非nil,并对业务字段做断言(如Code、Msg、Data及关键业务 ID、类型等);必须通过fmt.Printf打印返回内容,便于人工核对逻辑是否正确。 - 风格:与
cs一致时优先使用t.Error/t.Errorf+return早退出;断言失败时除t.Errorf外可再fmt.Printf("%#+v\n", resp)(及对*resp.Data)便于排错。
5.2 组织方式
- 同一能力的多条场景(如白名单与黑名单):可拆成
TestXxx、TestXxxBlack等若干函数,每个函数内仍应完整包含「请求校验 → 真实调用 → 响应断言 → 打印」,避免把断言拆成大量只测一行的小函数。 - 禁止仅写「只校验
InitParam、不调 Client」的孤立用例作为唯一测试;若需 mock(无网/CI),可另加辅助函数,但不应替代上述真实调用用例作为唯一验收。
5.3 输出与可读性
- 使用
fmt.Printf("%#+v\n", resp)打印完整响应结构体;若Data为指针,再打印fmt.Printf("%#+v\n", *resp.Data)。 - 测试函数顶部用简短中文注释说明测的是哪条接口、什么场景。
5.4 运行
go test ./services/<包名> -run Test<名称> -v