欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

記一次go語言使用time.Duration類型踩過的坑

 更新時間:2022年01月26日 16:31:28   作者:Go學堂  
本文主要介紹了記一次go語言使用time.Duration類型踩過的坑,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

01 踩到的坑

先來說說在項目中踩到的使用time.Duration類型的坑。我們的背景是要做一個延時任務。延時任務就是指將一個任務延遲到一定的時間后再執(zhí)行,所以就需要根據延時時間計算出該任務要執(zhí)行的時間。我們這里的延時時間以毫秒為單位,當時我們定義的是500毫秒。即設置了一個全局的變量interval time.Duration。 即interval = 500 * time.Milliseconds。然后就通過以下公式來計算要

執(zhí)行的時間了:

可執(zhí)行時間=當前時間+延遲時間可執(zhí)行時間=當前時間 + 延遲時間可執(zhí)行時間=當前時間+延遲時間

由以上公式可得到我們的一個任務的可執(zhí)行時間為 time.Now().UnixMilli() + int64(interval) 。大家看這里有什么問題嗎?
問題在于計算的結果值不是在當前的毫秒數上增加了500,而是增加了500000000,多了6個零。這是為什么呢?

02 time.Duration的真實面目

我們從源碼中找到答案。我們從time包中看到time.Duration的定義:

// A Duration represents the elapsed time between two instants
// as an int64 nanosecond count. The representation limits the
// largest representable duration to approximately 290 years.
type Duration int64

由源碼可知,Duration本質上是一個int64的類型。從注釋可知,代表的是兩個時間點之間持續(xù)的納秒數 。 所以這里有兩點信息 :一是該類型代表的是一段持續(xù)時間,二是該類型的基本單位是納秒。 這里我先重點關注基本單位是納秒這點。我們再來看幾個常量的定義:

const (
? ? Nanosecond ?Duration = 1
? ? Microsecond ? ? ? ? ?= 1000 * Nanosecond
? ? Millisecond ? ? ? ? ?= 1000 * Microsecond
? ? Second ? ? ? ? ? ? ? = 1000 * Millisecond
? ? Minute ? ? ? ? ? ? ? = 60 * Second
? ? Hour ? ? ? ? ? ? ? ? = 60 * Minute
)

一個單位的Duration是代表1納秒。 而time.Micorsecond、time.Millisecond、time.Second、time.Minute、time.Hour的單位實際上都是納秒。也就是說我們使用到的time.Millisecond實際上是1000000納秒。所以就有了interval=500*time.Millisecond=500 * 1000000 = 500000000,然后在計算延時后的執(zhí)行時間時兩個單位不一樣造成計算出來的值不是預期的增加500毫秒的結果。

03 問題解決

知道了time.Duration類型的基本單位是代表納秒之后,我們就可以很好的解決了。就是統一單位。
我們也發(fā)現,在time包中對于time.Duration類型的對象有轉換成秒、毫秒等對應的函數。如下:

所以我們直接獲取即可:

可執(zhí)行時間 := time.Now().UnixMilli() + interval.Millisecond()

04 time.Duration編程實踐

上面是我在編碼時因為沒搞懂time.Duration類型的本質含義猜到的一個坑。那么我們在實際編碼時在定義和持續(xù)時間有關的變量時應該使用int類型還是time.Duration類型呢?
我的建議是大家盡量用time.Duration類型。為什么呢?第一個原因是和標準庫類型統一,不用做過多的轉換。因為我們觀察可以發(fā)現,無論是開源程序,還是go的標準庫,凡是和持續(xù)時間相關的變量類型都是使用的time.Duration,這樣類型統一我們來看幾個例子。

示例一:context.WithTimeout

func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
? ? return WithDeadline(parent, time.Now().Add(timeout))
}

我們看到,context包中的WithTimeout函數中的timeout的類型是time.Duration。

示例二:time.Sleep

func Sleep(d Duration)

time包中的Sleep函數的d參數也是Duration類型。

示例三:time.NewTicker

func NewTicker(d Duration) *Ticker

如果我們自己的程序中相關變量使用的也是time.Duration類型,那么在調用標準庫函數時就不用進行類型轉化了。

第二個原因就是該類型在語義上就明確了time.Duration類型值的基本單位是納秒。這樣在函數調用過程中就不用進行單位換算了。我們看下面以連接redis的示例是如何進行類型轉換的。

我們在連接redis的時候,一般都會設置讀寫超時時間以及定義redis的地址,我們有如下配置:

type config struct {
    Addr string
    ReadTimeout int64 //以秒為單位
}

我們使用包github.com/go-redis/redis/v8包來連接redis。我們看到

func NewRedisClient(conf config) *redis.Client {
    opt := redis.Options{
        Addr: conf.Addr,
        ReadTimeout: conf.ReadTimeout * time.Second
    }
    
    client := redis.NewClient(opt)
    
    return client
}

我們知道redis.Options中的ReadTimeout的類型是time.Duration。 那么,如果我們在config配置文件中定義的int64類型以秒為單位的話,則在NewRedisClient中給redis.Options中的ReadTimeout賦值時,需要做如下轉換:

conf.ReadTimeout * time.Second

那如果我們在config中定義的ReadTimeout的代表的是毫秒的話,那么在NewRedisClient函數中就需要做如下轉換:

conf.ReadTimeout * time.Millisecond

那在config結構體中的ReadTimeout所代表的含義是秒還是毫秒還是其他的由誰來保證呢,只能是人為的進行保證。而如果使用time.Duration類型就是由系統類型來保證的,因為go的標準庫定義的該類型就是代表納秒數。

05 總結

本文從在實際編程中遇到的問題出發(fā),了解到time.Duration類型實際代表的是持續(xù)的納秒數。同時又分析了使用time.Duration類型的好處。在項目中,如果遇到和持續(xù)時間相關的變量的定義,也建議大家盡量使用time.Duration類型。

到此這篇關于記一次go語言使用time.Duration類型踩過的坑的文章就介紹到這了,更多相關go time.Duration內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:

相關文章

  • 深入理解Golang中的dig包管理和解決依賴關系

    深入理解Golang中的dig包管理和解決依賴關系

    這篇文章主要為大家詳細介紹了golang中dig包的使用方法,探討其應用場景,并提供一些示例,展示如何結合其他庫來更好地實現這些場景,感興趣的小伙伴可以了解下
    2024-01-01
  • 解決golang處理http response碰到的問題和需要注意的點

    解決golang處理http response碰到的問題和需要注意的點

    這篇文章主要介紹了解決golang處理http response碰到的問題和需要注意的點,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go代碼格式化gofmt的使用方法實例

    Go代碼格式化gofmt的使用方法實例

    Golang制定了統一的官方代碼風格,并推出gofmt工具(go fmt)來幫助開發(fā)人員格式化代碼到統一的風格,下面這篇文章主要給大家介紹了關于Go代碼格式化gofmt的使用方法,需要的朋友可以參考下
    2023-04-04
  • 深入探索Go語言中unsafe包的使用

    深入探索Go語言中unsafe包的使用

    Go語言的unsafe包被譽為黑科技,它為Go語言提供了底層訪問和操控內存的能力,本文將深入探討Go語言中unsafe包的使用方法和注意事項,需要的可以參考一下
    2023-04-04
  • 使用go module導入本地包的方法教程詳解

    使用go module導入本地包的方法教程詳解

    go module 將是Go語言默認的依賴管理工具。到今天 Go1.14 版本推出之后 Go modules 功能已經被正式推薦在生產環(huán)境下使用了。本文重點給大家介紹如何使用 go module 導入本地包,感興趣的朋友一起看看吧
    2020-03-03
  • golang實現簡單的tcp數據傳輸

    golang實現簡單的tcp數據傳輸

    這篇文章主要為大家介紹了golang實現簡單的tcp數據傳輸,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • Go語言創(chuàng)建、初始化數組的常見方式匯總

    Go語言創(chuàng)建、初始化數組的常見方式匯總

    這篇文章主要介紹了Go語言創(chuàng)建、初始化數組的常見方式,實例匯總了Go語言操作數組的常見技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • Golang實現單元測試中的邏輯層

    Golang實現單元測試中的邏輯層

    前面我們完成了最麻煩的數據層的單元測試,今天我們來看看單元測試中最容易做的一層,數據邏輯層,也就是我們通常說的 service 或者 biz 等
    2023-03-03
  • Golang使用Zookeeper實現分布式鎖

    Golang使用Zookeeper實現分布式鎖

    分布式鎖是一種在分布式系統中用于控制并發(fā)訪問的機制,ZooKeeper?和?Redis?都是常用的實現分布式鎖的工具,本文就來使用Zookeeper實現分布式鎖,希望對大家有所幫助
    2024-02-02
  • GoLang string類型深入分析

    GoLang string類型深入分析

    string 作為 go 語言中的基礎類型,其實有一些需要反復揣摩的,可能是我們使用的場景太簡單,也可能是我們不需要那可憐的一點優(yōu)化來提高性能,對它也就沒那么上心了
    2023-01-01

最新評論