golang iris使用go:linkname添加自定义form解析

在使用iris的时候
我们有这么一个结构体

type BannersCreateOrUpdate struct {
    Id            int               `json:"id" validate:"numeric"`
    Title         string            `json:"title" validate:"required"`
    StartTime     time.Time `json:"start_time" form:"start_time"`
}

我们有一个start_time的字段,如果前端希望传入2019-08-01 11:11:11时,如果使用c.Ctx.ReadForm(&p)的方式来获取,则获取不到正确的时间,报错如下schema: error converting value for "start_time". Details: parsing time "2019-08-01 11:11:11" as "2006-01-02T15:04:05Z07:00": cannot parse " 11:11:11" as "T"
所以这里就会涉及到自定义解析器,类似json的做法.

查看iris的源码,这里使用一个map来存储类型和Converter的map,解析时就通过这个来查找并调用对应的转换器,也提供了一个注册方法来添加转换器,不过由于被封装了formDecoder = NewDecoder(),小写的变量没法直接访问。

type Converter func(string) reflect.Value

// RegisterConverter registers a converter function for a custom type.
func (d *Decoder) RegisterConverter(value interface{}, converterFunc Converter) {
    d.cache.registerConverter(value, converterFunc)
}

刚好可以直接go:linkname,强行获取formDecoder,从而添加注册器。

  • 需要引入_ "unsafe"
  • 添加注释,将schema下的formDecoder链接到这里.
    //go:linkname formDecoder github.com/iris-contrib/schema.formDecoder
  • StartTime的类型换成自定义的NormalTime类型
    实现源码:
package common

import (
    "github.com/iris-contrib/schema"
    _ "github.com/iris-contrib/schema"
    "reflect"
    "time"
    _ "unsafe"
)

//go:linkname formDecoder github.com/iris-contrib/schema.formDecoder
//go:nosplit
var formDecoder *schema.Decoder

type NormalTime time.Time

func (n NormalTime) Converter(s string) reflect.Value {
    if t, err := time.Parse("2006-01-02 15:04:05", s); err == nil {
        return reflect.ValueOf(NormalTime(t))
    }
    return reflect.Value{}
}
func RegisterNormalTimeDecoder() {
    var nt = NormalTime{}
    formDecoder.RegisterConverter(nt, nt.Converter)
}

最后在main.go中或者合适的地方调用RegisterNormalTimeDecoder()即可

你可能感兴趣的:(golang iris使用go:linkname添加自定义form解析)