记⼀次go语⾔使⽤on类型踩过的坑
⽬录
01踩到的坑
on的真实⾯⽬
03问题解决
on编程实践
05总结
01踩到的坑
先来说说在项⽬中踩到的使⽤on类型的坑。我们的背景是要做⼀个延时任务。延时任务就是指将⼀个任务延迟到⼀
定的时间后再执⾏,所以就需要根据延时时间计算出该任务要执⾏的时间。我们这⾥的延时时间以毫秒为单位,当时我们定义
的是500毫秒。即设置了⼀个全局的变量on。即interval=500*econds。然后就通过以下公式来
计算要
执⾏的时间了:
可执⾏时间=当前时间+延迟时间可执⾏时间=当前时间+延迟时间可执⾏时间=当前时间+延迟时间
由以上公式可得到我们的⼀个任务的可执⾏时间为().UnixMilli()+int64(interval)。⼤家看这⾥有什么问题吗?
问题在于计算的结果值不是在当前的毫秒数上增加了500,⽽是增加了500000000,多了6个零。这是为什么呢?
on的真实⾯⽬
我们从源码中找到答案。我们从time包中看到on的定义:
//ADurationreprentstheelapdtimebetweentwoinstants
//rentationlimitsthe
//largestreprentabledurationtoapproximately290years.
typeDurationint64
由源码可知,Duration本质上是⼀个int64的类型。从注释可知,代表的是两个时间点之间持续的纳秒数。所以这⾥有两点信
息:⼀是该类型代表的是⼀段持续时间,⼆是该类型的基本单位是纳秒。这⾥我先重点关注基本单位是纳秒这点。我们再来
看⼏个常量的定义:
const(
NanocondDuration=1
Microcond=1000*Nanocond
Millicond=1000*Microcond
Second=1000*Millicond
Minute=60*Second
Hour=60*Minute
)
⼀个单位的Duration是代表1纳秒。⽽econd、econd、、、的单位实
际上都是纳秒。也就是说我们使⽤到的econd实际上是1000000纳秒。所以就有了
interval=500*econd=500*1000000=500000000,然后在计算延时后的执⾏时间时两个单位不⼀样造成计算出来
的值不是预期的增加500毫秒的结果。
03问题解决
知道了on类型的基本单位是代表纳秒之后,我们就可以很好的解决了。就是统⼀单位。
我们也发现,在time包中对于on类型的对象有转换成秒、毫秒等对应的函数。如下:
所以我们直接获取即可:
可执⾏时间:=().UnixMilli()+econd()
on编程实践
上⾯是我在编码时因为没搞懂on类型的本质含义猜到的⼀个坑。那么我们在实际编码时在定义和持续时间有关的变
量时应该使⽤int类型还是on类型呢?
我的建议是⼤家尽量⽤on类型。为什么呢?第⼀个原因是和标准库类型统⼀,不⽤做过多的转换。因为我们观察可
以发现,⽆论是开源程序,还是go的标准库,凡是和持续时间相关的变量类型都是使⽤的on,这样类型统⼀我们
来看⼏个例⼦。
⽰例⼀:meout
funcWithTimeout(parentContext,on)(Context,CancelFunc){
returnWithDeadline(parent,().Add(timeout))
}
我们看到,context包中的WithTimeout函数中的timeout的类型是on。
⽰例⼆:
funcSleep(dDuration)
time包中的Sleep函数的d参数也是Duration类型。
⽰例三:ker
funcNewTicker(dDuration)*Ticker
如果我们⾃⼰的程序中相关变量使⽤的也是on类型,那么在调⽤标准库函数时就不⽤进⾏类型转化了。
第⼆个原因就是该类型在语义上就明确了on类型值的基本单位是纳秒。这样在函数调⽤过程中就不⽤进⾏单位换算
了。我们看下⾯以连接redis的⽰例是如何进⾏类型转换的。
我们在连接redis的时候,⼀般都会设置读写超时时间以及定义redis的地址,我们有如下配置:
typeconfigstruct{
Addrstring
ReadTimeoutint64//以秒为单位
}
我们使⽤包/go-redis/redis/v8包来连接redis。我们看到
funcNewRedisClient(confconfig)*{
opt:=s{
Addr:,
ReadTimeout:meout*
}
client:=ent(opt)
returnclient
}
我们知道s中的ReadTimeout的类型是on。那么,如果我们在config配置⽂件中定义的int64类型以秒为
单位的话,则在NewRedisClient中给s中的ReadTimeout赋值时,需要做如下转换:
meout*
那如果我们在config中定义的ReadTimeout的代表的是毫秒的话,那么在NewRedisClient函数中就需要做如下转换:
meout*econd
那在config结构体中的ReadTimeout所代表的含义是秒还是毫秒还是其他的由谁来保证呢,只能是⼈为的进⾏保证。⽽如果使
⽤on类型就是由系统类型来保证的,因为go的标准库定义的该类型就是代表纳秒数。
05总结
本⽂从在实际编程中遇到的问题出发,了解到on类型实际代表的是持续的纳秒数。同时⼜分析了使⽤on
类型的好处。在项⽬中,如果遇到和持续时间相关的变量的定义,也建议⼤家尽量使⽤on类型。
到此这篇关于记⼀次go语⾔使⽤on类型踩过的坑的⽂章就介绍到这了,更多相关on内容请搜索以前的
⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!
本文发布于:2023-01-01 16:46:15,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/73071.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |