
本文详解如何为 Go 中基于 time.Time 的嵌套结构体(如 myTime)正确实现 UnmarshalJSON 方法,并解决赋值错误与缺失 String() 方法的问题,确保 Unix 时间戳能顺利解析并格式化输出。
本文详解如何为 go 中基于 time.time 的嵌套结构体(如 mytime)正确实现 unmarshaljson 方法,并解决赋值错误与缺失 string() 方法的问题,确保 unix 时间戳能顺利解析并格式化输出。
在 Go 中,通过类型别名(如 type myTime time.Time)定义新类型时,该类型不会自动继承原类型的任何方法——这是理解本问题的关键。你声明了 myTime 作为 time.Time 的别名,但它是一个全新的、无方法的类型。因此,直接调用 t.String() 会报错(type myTime has no field or method String),而 t = time.Unix(a, 0) 也会失败,因为 t 是 *myTime 类型的指针,而 time.Unix() 返回的是 time.Time 值,二者类型不兼容,且不能直接赋值给指针变量。
✅ 正确实现 UnmarshalJSON
UnmarshalJSON 方法的接收者是 *myTime,意味着你必须解引用指针后赋值。同时,由于 time.Unix() 返回 time.Time,需显式转换为 myTime 类型:
func (t *myTime) UnmarshalJSON(buf []byte) error {
// 注意:标准 JSON 时间戳通常是字符串格式(如 "123123123" 或 "123123123.123")
// binary.Varint 不适用于 JSON 字节流!此处应使用 json.Unmarshal 解析数字
var ts float64
if err := json.Unmarshal(buf, &ts); err != nil {
return err
}
sec := int64(ts)
nsec := int64((ts-float64(sec)) * 1e9)
*t = myTime(time.Unix(sec, nsec))
return nil
}
⚠️ 原代码中误用
binary.Varint(buf)—— 它用于二进制编码的变长整数,完全不适用于 JSON 字符串。JSON 解析必须先将原始字节反序列化为 Go 基础类型(如float64),再构造时间。
✅ 补全 String() 方法
为支持 fmt.Printf("%v", t) 或显式调用 t.String(),需手动实现:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
func (t myTime) String() string {
return time.Time(t).String()
}
注意:此处接收者是 myTime(值类型),而非 *myTime,因 time.Time.String() 是值方法;若定义为指针接收者,则 time.Time(*t) 会产生不必要的地址取值操作,且不符合惯用法。
✅ 完整可运行示例
package main
import (
"encoding/json"
"fmt"
"log"
"time"
)
type myTime time.Time
func (t *myTime) UnmarshalJSON(buf []byte) error {
var ts float64
if err := json.Unmarshal(buf, &ts); err != nil {
return err
}
sec := int64(ts)
nsec := int64((ts-float64(sec)) * 1e9)
*t = myTime(time.Unix(sec, nsec))
return nil
}
func (t myTime) String() string {
return time.Time(t).String()
}
func main() {
var t myTime
data := []byte("123123123.456789") // Unix 时间戳(秒+纳秒小数)
if err := json.Unmarshal(data, &t); err != nil {
log.Fatal(err)
}
fmt.Printf("Parsed time: %s\n", t.String())
fmt.Printf("Formatted (RFC3339): %s\n", time.Time(t).Format(time.RFC3339))
}
? 关键要点总结
- 类型别名(
type T U)不继承方法集,所有需用的方法(如String,MarshalJSON,UnmarshalJSON)都必须显式实现; -
UnmarshalJSON接收者为指针时,务必通过*t = ...赋值,而非t = ...(后者修改的是局部指针副本); - JSON 数值需用
json.Unmarshal解析为float64或int64,不可混用binary包; - 若 JSON 中时间以字符串形式存在(如
"2009-01-01T00:00:00Z"),则需先json.Unmarshal到string,再用time.Parse解析——本例假设输入为数值型时间戳。
掌握这些原则,即可稳健地为任意嵌套结构体定制 JSON 编解码逻辑。










