golang中处理接口中的时间(created_at等)

golang中的time采用的是rfc3339时间协议,mgo.v2不能直接将time.Time类型的字段存入mongodb中 ,同样也不方便将mongo存储的timestamp转为time.Timer。因此,需要实现一个自定义的时间类型BsonTime。为了能够对mgo.v2的序列化支持,需要实现标准库中的Unmarshaler接口。实现了该接口能够将mongodb和golang的时间戳打通,还够将BsonTime类型的时间在toJson的时候转为常用的时间字符串。

对api接口中传入的时间戳,可以使用mapstructure和实现自定义的Decode函数实现解析,将时间戳、事件字符串转为自定义的BsonTime

在线运行地址:https://play.golang.org/p/nciTC7rdYZC

自定义BsonTime,将golang的time.Time存入mongodb中

const timeFormart = "2006-01-02 15:04:05"

// 对struct增加 MarshalJSON ,UnmarshalJSON , String 方法,实现自定义json输出格式与打印方式
type BsonTime struct {
	time.Time
}

func (t BsonTime) String() string {
	return t.Time.Format(timeFormart)
}

// 实现它的json序列化方法
func (t BsonTime) MarshalJSON() ([]byte, error) {
	var stamp = fmt.Sprintf("\"%s\"", t.Time.Format("2006-01-02 15:04:05"))
	return []byte(stamp), nil
}

func (t *BsonTime) UnmarshalJSON(data []byte) error {
	if err := t.Time.UnmarshalJSON(data); err != nil {
		return err
	}
	return nil
}

func (t BsonTime) GetBSON() (interface{}, error) {
	if t.IsZero() {
		return nil, nil
	}
	return t.Time, nil
}

func (t *BsonTime) SetBSON(raw bson.Raw) error {
	var tm time.Time
	if err := raw.Unmarshal(&tm); err != nil {
		return err
	}
	t.Time = tm
	return nil
}

利用mapstructure库提供的自定义Decode函数,对struct中的BsonTime字段使用自定义的Decode方法。

func ToTimeHookFunc() mapstructure.DecodeHookFunc {
	return func(
		f reflect.Type,
		t reflect.Type,
		data interface{}) (interface{}, error) {
		if !reflect.DeepEqual(t, reflect.TypeOf(BsonTime{})) {
			return data, nil
		}
		var tTime time.Time
		var err error
		switch f.Kind() {
		case reflect.String:
			tTime, err = time.Parse("2006-01-02 15:04:05", data.(string))
		case reflect.Float64:
			tTime, err = time.Unix(0, int64(data.(float64))*int64(time.Millisecond)), nil
		case reflect.Int64:
			tTime, err = time.Unix(0, data.(int64)*int64(time.Millisecond)), nil
		default:
			return data, nil
		}
		if err != nil {
			return nil, err
		}
		return BsonTime{
			Time: tTime,
		}, nil
	}
}

// Map2StructWithBsonTime user `mapstructure` convert map to struct, with process time to BsonTime.
func Map2StructWithBsonTime(input map[string]interface{}, result interface{}) error {
	decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
		Metadata:   nil,
		DecodeHook: mapstructure.ComposeDecodeHookFunc(ToTimeHookFunc()),
		Result:     result,
		TagName:    "json",
	})
	if err != nil {
		return err
	}
	if err := decoder.Decode(input); err != nil {
		return err
	}
	return nil
}

使用

import (
	"encoding/json"
	"fmt"
	"github.com/globalsign/mgo/bson"
	"github.com/mitchellh/mapstructure"
	"log"
	"reflect"
	"time"
)
var rawStr = `
{
    "created_by": "7290310f-3574-4520-9ef1-79188bc7c997",
    "created_time": 1563884700000,
    "last_edited_time": 1563884700000,
    "last_edited_by": "7290310f-3574-4520-9ef1-79188bc7c997",
    "last_reply_at": "2019-07-01 12:34:56"
}
`

// AuthorTime must define `JSON TAG`.
type AuthorTime struct {
	CreatedBy   string   `json:"created_by"`
	CreatedAt   BsonTime `json:"created_time"`
	UpdatedBy   string   `json:"last_edited_by"`
	UpdatedAt   BsonTime `json:"last_edited_time"`
	LastReplyAt BsonTime `json:"last_reply_at"`
}

func main() {
	var paramsBind map[string]interface{}              // 模拟gin的参数绑定
	err := json.Unmarshal([]byte(rawStr), &paramsBind) //paramsBind需要是引用类型
	if err != nil {
		panic(err)
	}

	// 将参数转化为struct
	var author AuthorTime
	err = Map2StructWithBsonTime(paramsBind, &author)
	if err != nil {
		panic(err)
	}

	// 转为json
	toJson, err := json.Marshal(&author)
	if err != nil {
		panic(err)
	}
	log.Println(string(toJson))
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Go接口是一个使用非常广泛的概念,可以让您以一种非常灵活的方式编写代码,同时保持代码的可读性和可维护性。接口是一种类型,它定义了一组方法,这些方法可以被不同的类型实现。下面是一些关于Go接口的详细信息: 1. 接口是一种类型。 在Go接口是一种类型,它定义了一组方法。一个类型可以实现一个或多个接口。 2. 接口定义方法。 接口是由一组方法定义的,这些方法没有实现。一个类型可以实现接口定义的所有方法,只要它们按照接口定义的方式进行实现即可。 3. 接口实现。 一个类型可以实现一个或多个接口。一个类型只需要实现接口定义的所有方法,就可以称之为实现了这个接口。 4. 接口的实现是隐式的。 在Go接口的实现是隐式的。一个类型只需要实现接口定义的所有方法,就可以自动实现这个接口。 5. 接口变量和接口值。 接口变量是一个接口类型的变量,它可以存储任何实现了该接口的值。接口值是一个接口类型的值,它可以存储任何实现了该接口的值。 6. 空接口。 空接口是一种不包含任何方法的接口。它可以存储任何类型的值。 7. 类型断言。 类型断言是一种将接口值转换为其他类型的方法。如果转换失败,它会返回一个零值和一个错误。 8. 接口的嵌套。 接口的嵌套是一种将多个接口组合成一个新接口的方法。新接口包含了所有组合接口的方法。 9. 接口的多态性。 接口的多态性是一种让不同类型的对象可以以相同的方式进行处理的方法。这样可以让您的代码更加灵活和可维护。 以上是关于Go接口的一些概念和用法的详细介绍。如果您想要更深入地了解接口,可以参考Go的官方文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值