GO項目實戰之Gorm格式化時間字段實現
goshop開源項目的更新
備註:前面項目中用到的代碼已經分享到GitHub中去瞭,並且以後所有項目中會出現的代碼都會提交上去,歡迎查閱。感興趣的可以點個star哦~
https://gitee.com/jobhandsome/goshop/
在使用 gorm
查詢時,如果未對時間字段進行處理,結構體內的字段類型咱們使用的是 time.Time
:
type Model struct { ID int64 `json:"id" gorm:"primary_key"` CreatedAt *time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at"` DeletedAt *time.Time `json:"deleted_at" sql:"index"` }
這裡咱們使用 time.Time
類型在 gorm
進行查詢的返回結果,讀取到的時間字段往往是這樣:“2022-07-03T22:14:02.973528+08:00
”,帶著時區和毫秒。但其實往往這樣的格式,不是咱們想要的。
那麼問題就來瞭:
- 如果想要 “
2022-07-03 22:14:02
” 這樣的格式,需要怎麼處理呢? - 當插入一條數據到對應的表中時,
UpdateAt
字段是不賦值的,插入到數據庫則會0001-01-01 00:00:00.000000+00:00
,系統賦瞭⼀個默認值,當不想插⼊默認值
時如何處理?
通過上面的分析,咱們能確定兩個需求:
讀取到的時間需要是:“2022-07-03 22:14:02” 這樣的格式
當時間字段不賦值時,不插入默認值
解決方法:
定義一個時間類型 struct
type LocalTime time.Time
雖然該數據類型實際類型為 time.Time
,但是不具備 time.Time
的內置⽅法,需要重寫 MarshalJSON
⽅法來實現數據解析
func (t *LocalTime) MarshalJSON() ([]byte, error) { tTime := time.Time(*t) return []byte(fmt.Sprintf("\"%v\"", tTime.Format("2006-01-02 15:04:05"))), nil }
註意:
GO
的格式化時間的規定時間字符串必須為2006-01-02 15:04:05
這是GO
的誕⽣時間,不能更改為其他時間(這個時間字符串與java
的"yyyy-MM-dd HH:mm:ss
")同作⽤
將 time.Time
替換成 LocalTime
type Model struct { ID int64 `json:"id" gorm:"primary_key"` CreatedAt *LocalTime `json:"created_at"` UpdatedAt *localTime `json:"updated_at"` DeletedAt *localTime `json:"deleted_at" sql:"index"` }
到瞭這一步就解決瞭第一個需求讀取數據時將將時間數據格式化。
下面來實現第二個需求:
func (t LocalTime) Value() (driver.Value, error) { var zeroTime time.Time tlt := time.Time(t) //判斷給定時間是否和默認零時間的時間戳相同 if tlt.UnixNano() == zeroTime.UnixNano() { return nil, nil } return tlt, nil }
Value
⽅法即在存儲時調⽤,將該⽅法的返回值進⾏存儲,該⽅法可以實現數據存儲前對數據進⾏相關操作。
func (t *LocalTime) Scan(v interface{}) error { if value, ok := v.(time.Time); ok { *t = LocalTime(value) return nil } return fmt.Errorf("can not convert %v to timestamp", v) }
Scan
⽅法可以實現在數據查詢出來之前對數據進⾏相關操作。
到瞭這一步,咱們就實現瞭上面需求的功能。
補充:gorm時間格式化問題詳解
說明
在做項目時發現gorm的時間格式是帶有時區輸入輸出的,對平常使用的2020-01-03 12:22:33格式有一定的出入,不方便前端和後端的對接,所以自己整理一下處理這個問題方法,方便大傢參考
代碼如下
package models import ( "database/sql/driver" "errors" "fmt" "strings" "time" ) //BaseModel 基礎結構體 信息信息 type BaseModel struct { CreateTime MyTime `gorm:"comment:'創建時間';type:timestamp;";json:"createTime"` UpdateTime MyTime `gorm:"comment:'修改時間';type:timestamp;";json:"updateTime"` Remark string `gorm:"comment:'備註'";json:"remark"` } //MyTime 自定義時間 type MyTime time.Time func (t *MyTime) UnmarshalJSON(data []byte) error { if string(data) == "null" { return nil } var err error //前端接收的時間字符串 str := string(data) //去除接收的str收尾多餘的" timeStr := strings.Trim(str, "\"") t1, err := time.Parse("2006-01-02 15:04:05", timeStr) *t = MyTime(t1) return err } func (t MyTime) MarshalJSON() ([]byte, error) { formatted := fmt.Sprintf("\"%v\"", time.Time(t).Format("2006-01-02 15:04:05")) return []byte(formatted), nil } func (t MyTime) Value() (driver.Value, error) { // MyTime 轉換成 time.Time 類型 tTime := time.Time(t) return tTime.Format("2006-01-02 15:04:05"), nil } func (t *MyTime) Scan(v interface{}) error { switch vt := v.(type) { case time.Time: // 字符串轉成 time.Time 類型 *t = MyTime(vt) default: return errors.New("類型處理錯誤") } return nil } func (t *MyTime) String() string { return fmt.Sprintf("hhh:%s", time.Time(*t).String()) }
實現原理
其實現方式其實是通過在時間讀取json時對解析格式進行重寫,對轉換成字符串時進行重寫達到效果
總結
到此這篇關於GO項目實戰之Gorm格式化時間字段實現的文章就介紹到這瞭,更多相關GO Gorm格式化時間字段內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- gorm+gin實現restful分頁接口的實踐
- golang中json和struct的使用說明
- Golang 使用gorm添加數據庫排他鎖,for update
- Golang 中的json.Marshal問題總結(推薦)
- gORM操作MySQL的實現