Droplet——一款轻量的Golang应用层框架( 三 )

参数绑定【Droplet——一款轻量的Golang应用层框架】Usage 一节中所展示的,我们可以通过 wrapper.InputType 选项来告诉 Droplet 是否期望自动化进行参数绑定,如果某些场景下你不需要从 Body 进行自动的参数绑定了,可以通过显式的选项来禁止它,如:
r.POST("/json_input/:id", ginwrap.Wraps(JsonInputDo, wrapper.InputType(reflect.TypeOf(&JsonInput{}), wrapper.DisableUnmarshalBody())))参数绑定的Tag格式如下:
auto_read: ({key},{source}) or @body其中值如下:

  • key: 用于到各个来源中匹配对应值
  • source: 可选值有 query, header, path, body(缺省默认)
  • @body: 特殊的取值,意味着获取原生的body作为字段值,此时你的字段类型应该为 []byte or io.ReadCloser
同时 Droplet 会自动使用 validator 对入参进行校验,因此你可以使用其 tag 来辅助验证参数合法性 。
响应整形通常来说API都会在响应的最外层进行一层包装,比如 Droplet 自带的 wrapper 如下所示:
{"code": 0,// API 错误码"message": "",// API 消息"data": {},// 响应数据"request_id": "" // 请求ID}当然你可以完全去掉这个默认 Wrapper 或者 使用满足你们团队规范的 Wrapper(需要实现 data.HttpResponse 接口) 来替换它:
type NativeJsonResp struct { data interface{}}func (n *NativeJsonResp) Set(code int, msg string, data interface{}) { n.data = https://www.huyubaike.com/biancheng/data}func (n *NativeJsonResp) SetReqID(reqId string) {}func (n *NativeJsonResp) MarshalJSON() ([]byte, error) { return json.Marshal(n.data)}func main() {... droplet.Option.ResponseNewFunc = func() data.HttpResponse {return &NativeJsonResp{} }...}对于另外一些并不需要 Wrapper 或者 你想要自行控制返回的内容时可以在 Handler 中使用一些实现了特定接口的返回值,如下所示:
func GetLoginQRCode(ctx droplet.Context) (interface{}, error) { type makeQRCodeResp struct {SceneID string `json:"scene_id"`Stateint`json:"state"`Urlstring `json:"url"` } var resp makeQRCodeResp if err := goreq.Get(UrlMakeQRCode, goreq.SetHeader(fakeClientHeader()), goreq.JsonResp(&resp)).Do(); err != nil {return nil, fmt.Errorf("get qrcode failed: %w", err) } return &data.RawResponse{StatusCode: http.StatusOK,Body:[]byte(fmt.Sprintf(QRCodeBase, resp.SceneID, resp.SceneID, resp.Url)), }, nil}类似的还有 data.FileResponsedata.SpecCodeResponse,根据其名字你可以在需要的场景选择它们 。
同时在整形过程中,为了业务研发不再需要关心错误处理,Droplet 会自动将 err != nil 的响应转化到 code 与 message 字段上 。如下图所示:
func ErrorAPI(ctx droplet.Context) (interface{}, error) {return nil, errors.New("failed")}那么你将得到如下的响应:
{"code": 10000,"message": "failed"}当然,你可以使用 data.BaseError 来指定你想返回的错误码:
func ErrorAPI(ctx droplet.Context) (interface{}, error) {return nil, data.BaseError{Code: 100, Message: "custom message"}}
Tips
  • 这些特定的响应其背后都是实现了某一类接口,如果有需要你也完全可以自行实现 。
流量记录Droplet 自带了记录 API 出参与入参的能力,但是默认所有记录信息都会被抛弃,如果想要启用它,你需要实现 Droplet 的全局 Logger,如下所示:
import ("github.com/shiningrush/droplet/log")func main() {...// CustomLogger 需要实现 log.Interface log.DefLogger = &CustomLogger{}// droplet 默认只会记录 Path,Method,耗时等信息,如果你需要打印 API 的输入与输出,可以在全局选项中开启(在Wraps函数中也可指定)droplet.Option.TrafficLogOpt = &middleware.TrafficLogOpt{LogReq:true,LogResp: true, }...}

经验总结扩展阅读