golangGo中json.Marshal函数
Posted Cutele_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了golangGo中json.Marshal函数相关的知识,希望对你有一定的参考价值。
结构体中的字段首字母必须大写,否则在序列化时将被忽略;
当结构体中包含指针类型的字段时,在序列化时需要先判断该指针是否为 nil,否则在序列化时会出现 panic;
对于嵌套结构体,可以通过在结构体定义中使用匿名字段来实现,但需要注意匿名字段的类型也要满足上述两个条件;
对于封装了某些字段的自定义类型,可以使用该类型的 MarshalJSON 方法来实现自定义的序列化方式;
在 JSON 字符串中,字符串值必须用双引号括起来,而不能使用单引号;
在序列化时,如果存在循环引用,则会出现死循环。
需要特别注意的是,为了能够正确地将 JSON 数据与 Go 的数据结构相互转换,应该遵守一定的编码规范。具体来说,应该使用合适的数据类型来表示不同的数据,如使用 time.Time 来表示时间戳、使用 int64 来表示整数等。此外,在定义结构体时,应该使用 json 标签来指定每个字段在序列化后对应的 JSON 字段名,以保证数据的兼容性。
GolangGo中时间(time)的用法以及gorm处理时间戳
time包提供了时间的显示和测量用的函数。日历的计算采用的是公历。 time 类型
type Time struct { // wall and ext encode the wall time seconds, wall time nanoseconds, // and optional monotonic clock reading in nanoseconds. // // From high to low bit position, wall encodes a 1-bit flag (hasMonotonic), // a 33-bit seconds field, and a 30-bit wall time nanoseconds field. // The nanoseconds field is in the range [0, 999999999]. // If the hasMonotonic bit is 0, then the 33-bit field must be zero // and the full signed 64-bit wall seconds since Jan 1 year 1 is stored in ext. // If the hasMonotonic bit is 1, then the 33-bit field holds a 33-bit // unsigned wall seconds since Jan 1 year 1885, and ext holds a // signed 64-bit monotonic clock reading, nanoseconds since process start. wall uint64 ext int64 // loc specifies the Location that should be used to // determine the minute, hour, month, day, and year // that correspond to this Time. // The nil location means UTC. // All UTC times are represented with loc==nil, never loc==&utcLoc. loc *Location }
time可以精确到纳秒, 下面是各种时间换
package main import ( "fmt" "time" ) func main() { t := time.Now() fmt.Println(t) //获取当前时间2021-09-23 10:55:44.831571 +0800 CST m=+0.000090412 fmt.Println(t.Unix()) //获取当前时间时间戳 1632366278 //fmt.Println(t.UnixMilli()) //获取当前时间毫秒 1632366278605 //fmt.Println(t.UnixMicro()) //获取当前时间微秒 1632366278605122 fmt.Println(t.UnixNano()) //获取当前时间时纳秒 1632366278605122000 fmt.Println(t.Hour()) //获取当前小时 10 fmt.Println(t.Day()) //获取当前天 23 fmt.Println(t.Weekday()) //获取当前周Thursday fmt.Println(t.ISOWeek()) //获取当前周2021 38 //格式化当前时间表示 fmt.Println(t.String()) //字符型 fmt.Println(t.Format("2006-01-02 15:04:05")) //2021-09-23 11:12:42 fmt.Println(t.Format("2006-01-02")) //2021-09-23 fmt.Println(t.Format("15:04:05")) //11:12:42 //指定时间戳转换 fmt.Println(time.Unix(1632366278, 0).Format("2006-01-02 15:04:05")) //2021-09-23 11:04:38 //指定时间转时间戳 tm2, _ := time.Parse("2006-01-02 15:04:05", "2021-09-23 11:04:38") fmt.Println(tm2.Unix()) //1632395078 //"2021-09-08T08:18:46+08:00" 转2021-09-08 08:18:46 t, _ = time.Parse(time.RFC3339, "2021-09-08T08:18:46+08:00") fmt.Println(t.Format("2006-01-02 15:04:05")) //2021-09-07T17:01:34.182659088Z 转2021-09-07 17:01:34 t, _ = time.Parse(time.RFC3339Nano, "2021-09-07T17:01:34.182659088Z") fmt.Println(t.Format("2006-01-02 15:04:05")) //其他格式类似可参考 //ANSIC = "Mon Jan _2 15:04:05 2006" //UnixDate = "Mon Jan _2 15:04:05 MST 2006" //RubyDate = "Mon Jan 02 15:04:05 -0700 2006" //RFC822 = "02 Jan 06 15:04 MST" //RFC822Z = "02 Jan 06 15:04 -0700" // 使用数字表示时区的RFC822 //RFC850 = "Monday, 02-Jan-06 15:04:05 MST" //RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST" //RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // 使用数字表示时区的RFC1123 //RFC3339 = "2006-01-02T15:04:05Z07:00" //RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00" //Kitchen = "3:04PM" //// 方便的时间戳 //Stamp = "Jan _2 15:04:05" //StampMilli = "Jan _2 15:04:05.000" //StampMicro = "Jan _2 15:04:05.000000" //StampNano = "Jan _2 15:04:05.000000000" //设置时区 Location //默认UTC loc, _ := time.LoadLocation("") // 服务器设定的时区,一般为CST //loc, _ := time.LoadLocation("Local") //loc, _ := time.LoadLocation("Asia/Shanghai") t.In(loc).Format("2006-01-02 15:04:05") //1.5s后 now := time.Now() tp, _ := time.ParseDuration("1.5s") fmt.Println(tp, tp.Truncate(1000), tp.Seconds(), tp.Nanoseconds()) m1 := now.Add(tp) fmt.Println(m1) //2021-09-23 14:30:42.006213 +0800 CST m=+1.500352171 //1个小时前 tp, _ = time.ParseDuration("-1h") m1 = now.Add(tp) fmt.Println(m1) //2021-09-23 13:30:40.506213 +0800 CST m=-3599.999647829 //休眠时间 //time.Sleep(time.Duration(10) * time.Second) // func After(d Duration) <-chan Time 非阻塞,可用于延迟 //time.After(time.Duration(10) * time.Second) // func Since(t Time) Duration 两个时间点的间隔 start := time.Now() fmt.Println(time.Since(start)) // 等价于 Now().Sub(t), 可用来计算一段业务的消耗时间 //func Until(t Time) Duration // 等价于 t.Sub(Now()),t与当前时间的间隔 time3 := "2021-03-20 08:50:29" time4 := "2021-03-20 08:50:29" //先把时间字符串格式化成相同的时间类型 t3, _ := time.Parse("2006-01-02 15:04:05", time3) t4, _ := time.Parse("2006-01-02 15:04:05", time4) fmt.Println(t3.Equal(t4)) //true now = time.Now() //Ticker 类型包含一个 channel,有时我们会遇到每隔一段时间执行的业务(比如设置心跳时间等),就可以用它来处理,这是一个重复的过程 // 无法取消 //tick := time.Tick(1 * time.Minute) //for _ = range tick { // // do something //} //NewTicker返回一个新的Ticker,该Ticker包含一个通道字段,并会每隔时间段d就向该通道发送当时的时间。它会调整时间间隔或者丢弃tick信息以适应反应慢的接收者。如果d<=0会panic。关闭该Ticker可以释放相关资源。 // 可通过调用ticker.Stop取消 //创建一个周期性的定时器 //设置定时器为3秒 timer := time.NewTimer(3 * time.Second) fmt.Println("当前时间为:", time.Now()) t = <-timer.C //从定时器拿数据 fmt.Println("当前时间为:", t) timer.Stop() //停止 }
问题:在使用 gorm 的过程中, 处理时间戳字段时遇到问题。写时间戳到数据库时无法写入。
设置数据库的 dsn
parseTime = "True" loc = "Local"
设置自定义 Time 类型
package types import ( "database/sql/driver" "fmt" "time" ) // Time is alias type for time.Time type Time time.Time const ( timeFormart = "2006-01-02 15:04:05" zone = "Asia/Shanghai" ) // UnmarshalJSON implements json unmarshal interface. func (t *Time) UnmarshalJSON(data []byte) (err error) { now, err := time.ParseInLocation(`"`+timeFormart+`"`, string(data), time.Local) *t = Time(now) return } // MarshalJSON implements json marshal interface. func (t Time) MarshalJSON() ([]byte, error) { b := make([]byte, 0, len(timeFormart)+2) b = append(b, \'"\') b = time.Time(t).AppendFormat(b, timeFormart) b = append(b, \'"\') return b, nil } func (t Time) String() string { return time.Time(t).Format(timeFormart) } func (t Time) local() time.Time { loc, _ := time.LoadLocation(zone) return time.Time(t).In(loc) } // Value ... func (t Time) Value() (driver.Value, error) { var zeroTime time.Time var ti = time.Time(t) if ti.UnixNano() == zeroTime.UnixNano() { return nil, nil } return ti, nil } // Scan valueof time.Time 注意是指针类型 method func (t *Time) Scan(v interface{}) error { value, ok := v.(time.Time) if ok { *t = Time(value) return nil } return fmt.Errorf("can not convert %v to timestamp", v) }
这样程序中所有的时间值都使用types.Time类型就可以准确进行时间戳变量的读写操作。
原理:其实就是自定义数据库数据类型,在 sql driver 中实现自定义类型需要实现 Scanner和Valuer接口
//Scanner type Scanner interface { Scan(src interface{}) error } //Valuer type Valuer interface { // Value returns a driver Value. Value() (Value, error) } //unmarshal和marshal 自定义 json 转换格式
- 作者:踏雪无痕
- 出处:http://www.cnblogs.com/chenpingzhao/
- 本文版权归作者和博客园共有,如需转载,请联系 pingzhao1990#163.com
如果您觉得本文对您的学习有所帮助,可通过支付宝(左) 或者 微信(右) 来打赏博主,增加博主的写作动力
以上是关于golangGo中json.Marshal函数的主要内容,如果未能解决你的问题,请参考以下文章
2022-08-11:以下go语言代码输出什么?A:panic;B:编译错误;C:json marshal 报错;D:null;E:nil。 package main import ( “e