time.Duration 意外地 'divided' 乘以 1'000'000
time.Duration is unexpectedly 'divided' by 1'000'000
我正在使用 time.Duration
将数据存储在结构中,如下所示:
type ApiAccessToken struct {
...
ExpiredIn *time.Duration `bson:"expired_in,omitempty" json:"expired_in,omitempty"`
...
}
我使用这样的常量设置它:
...
const ApiAccessTokenDefaultExpiresIn = 7 * 24 * time.Hour
...
d := ApiAccessTokenDefaultExpiresIn
data := &ApiAccessToken{
...
ExpiredIn: &d
...
}
...
然后我使用 mgo
将数据插入数据库。
我在创建 data
实例之后和插入数据之前进行了检查,ExpiredIn
的值是 604'800'000'000'000 但在 MongoDB 中它变成了604'800'000(或 NumberLong(604800000)
)。
知道为什么吗?谢谢!
当前解决方案:将 MongoDB 返回的 ExpiredIn
乘以 time.Second
所以我得到了我的 Go-flavoured 纳秒 time.Duration
.
我最终使用了 time.Duration
的 string
表示,因为它很简单。
我为我的 ApiAccessToken
结构创建了两个函数来完成 writing/reading 数据的工作。
func (tok *ApiAccessToken) SetExpiredIn(t time.Duration) {
s := t.String() // read the string
tok.ExpiredIn = &s
}
func (tok *ApiAccessToken) GetExpiredIn() (r bool, t time.Duration) {
if tok.ExpiredIn != nil {
var err error
t, err = time.ParseDuration(*tok.ExpiredIn) // parse the string
r = (err == nil) // can we use this?
}
return
}
瞧,成功了!
我们通常会为特定类型编写自定义 MarshalJSON/UnmarshalJSON 来控制它们的值会发生什么 before/after marshaling/unmarshaling.
type ExpiredIn struct {
time.Duration
}
func (e *ExpiredIn) MarshalJSON() ([]byte, error) {
return []byte(string(e.Nanoseconds())), nil
}
func (e *ExpiredIn) UnmarshalJSON(data []byte) error {
i, _ := strconv.ParseInt(string(data[:])), 10, 64)
e.Duration = time.Duration(i)
return nil
}
测试代码如下:
package main
import (
"log"
"time"
"gopkg.in/mgo.v2"
)
type Token struct {
ExpiredIn time.Duration
}
type ExpiredIn struct {
time.Duration
}
func (e *ExpiredIn) MarshalJSON() ([]byte, error) {
return []byte(string(e.Nanoseconds())), nil
}
func main() {
session, err := mgo.Dial("mongodb://localhost:27017/test")
if err != nil {
panic(err)
}
defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
c := session.DB("test").C("tokens")
err = c.Insert(&Recipe{7 * 24 * time.Hour})
if err != nil {
log.Fatal(err)
}
}
大功告成!
我正在使用 time.Duration
将数据存储在结构中,如下所示:
type ApiAccessToken struct {
...
ExpiredIn *time.Duration `bson:"expired_in,omitempty" json:"expired_in,omitempty"`
...
}
我使用这样的常量设置它:
...
const ApiAccessTokenDefaultExpiresIn = 7 * 24 * time.Hour
...
d := ApiAccessTokenDefaultExpiresIn
data := &ApiAccessToken{
...
ExpiredIn: &d
...
}
...
然后我使用 mgo
将数据插入数据库。
我在创建 data
实例之后和插入数据之前进行了检查,ExpiredIn
的值是 604'800'000'000'000 但在 MongoDB 中它变成了604'800'000(或 NumberLong(604800000)
)。
知道为什么吗?谢谢!
当前解决方案:将 MongoDB 返回的 ExpiredIn
乘以 time.Second
所以我得到了我的 Go-flavoured 纳秒 time.Duration
.
我最终使用了 time.Duration
的 string
表示,因为它很简单。
我为我的 ApiAccessToken
结构创建了两个函数来完成 writing/reading 数据的工作。
func (tok *ApiAccessToken) SetExpiredIn(t time.Duration) {
s := t.String() // read the string
tok.ExpiredIn = &s
}
func (tok *ApiAccessToken) GetExpiredIn() (r bool, t time.Duration) {
if tok.ExpiredIn != nil {
var err error
t, err = time.ParseDuration(*tok.ExpiredIn) // parse the string
r = (err == nil) // can we use this?
}
return
}
瞧,成功了!
我们通常会为特定类型编写自定义 MarshalJSON/UnmarshalJSON 来控制它们的值会发生什么 before/after marshaling/unmarshaling.
type ExpiredIn struct {
time.Duration
}
func (e *ExpiredIn) MarshalJSON() ([]byte, error) {
return []byte(string(e.Nanoseconds())), nil
}
func (e *ExpiredIn) UnmarshalJSON(data []byte) error {
i, _ := strconv.ParseInt(string(data[:])), 10, 64)
e.Duration = time.Duration(i)
return nil
}
测试代码如下:
package main
import (
"log"
"time"
"gopkg.in/mgo.v2"
)
type Token struct {
ExpiredIn time.Duration
}
type ExpiredIn struct {
time.Duration
}
func (e *ExpiredIn) MarshalJSON() ([]byte, error) {
return []byte(string(e.Nanoseconds())), nil
}
func main() {
session, err := mgo.Dial("mongodb://localhost:27017/test")
if err != nil {
panic(err)
}
defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
c := session.DB("test").C("tokens")
err = c.Insert(&Recipe{7 * 24 * time.Hour})
if err != nil {
log.Fatal(err)
}
}
大功告成!