最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go defer與time.sleep的使用與區(qū)別

 更新時(shí)間:2024年04月19日 10:59:44   作者:寸 鐵  
本文主要介紹了Go defer與time.sleep的使用與區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

請(qǐng)大家看下面這段代碼,看運(yùn)行結(jié)果會(huì)出現(xiàn)什么,為什么?

問題

demo

package main

import (
	"log"
	"time"
)

func main() {
	start := time.Now()

	defer func() {
		log.Printf("匿名函數(shù)時(shí)間差: %v", time.Since(start))
	}()

	defer log.Printf("時(shí)間差: %v", time.Since(start))
	time.Sleep(3 * time.Second)
	log.Printf("函數(shù)結(jié)束")
}

這里不少同學(xué)會(huì)認(rèn)為:這題我會(huì),先輸出函數(shù)結(jié)束,待整個(gè)函數(shù)結(jié)束后,根據(jù)defer后進(jìn)先出的順序依次打印計(jì)算的時(shí)間差,由于這里睡眠了3秒,兩個(gè)時(shí)間差應(yīng)該都是3秒左右

所以答案為:

函數(shù)結(jié)束
時(shí)間差:3s
匿名函數(shù)時(shí)間差:3s

看到這里,我想說同學(xué)你的思路和想法是好的,一開始我也和你一樣,但是這里的答案是錯(cuò)的,那為什么錯(cuò)呢?總得有個(gè)原因吧!很明顯匿名函數(shù)的時(shí)間差符合邏輯是對(duì)的,那為什么時(shí)間差與預(yù)期不符合呢?下面我來進(jìn)行分析。

運(yùn)行結(jié)果

在這里插入圖片描述

分析

這里的關(guān)鍵點(diǎn)在于為什么時(shí)間差0,也就是說為什么時(shí)間差這個(gè)defer語(yǔ)句沒有被time.sleep 所影響?進(jìn)一步分析,就是查看start賦值時(shí)機(jī)在哪?是在一開始調(diào)用defer就賦值,還是說在函數(shù)結(jié)束后給defer中的start賦值,從而造成結(jié)果的不同。
帶著這個(gè)問題,不妨來debug一下,看一下函數(shù)語(yǔ)句的執(zhí)行順序。

設(shè)置斷點(diǎn)

要想看一下start的賦值時(shí)機(jī),設(shè)置斷點(diǎn)在出現(xiàn)start變量前面即可。

在這里插入圖片描述

設(shè)置好斷點(diǎn)后,開始進(jìn)行debug

debug查看

step1

一開始,先初始化start的值

在這里插入圖片描述

step2

接著,來到第一個(gè)defer + 匿名函數(shù),看它有沒有進(jìn)去里面的printf語(yǔ)句給start變量進(jìn)行賦值,step over 直接跳過了匿名函數(shù)defer語(yǔ)句,也就是說明并沒有給匿名函數(shù)中的defer語(yǔ)句中的start賦值

在這里插入圖片描述

step3

之后,進(jìn)入defer語(yǔ)句中,給time.Since中的start進(jìn)行賦值。

這里,會(huì)發(fā)現(xiàn)問題的關(guān)鍵所在,對(duì)比defer + 匿名函數(shù) 一開始調(diào)用(非執(zhí)行)時(shí),不會(huì)對(duì)里面的變量(參數(shù))start進(jìn)行賦值。

然而普通的defer + printf則在一開始時(shí)就會(huì)對(duì)里面的變量start賦值,賦值后不會(huì)先time.since的結(jié)果計(jì)算出來,會(huì)在defer調(diào)用后,也就是光標(biāo)移動(dòng)到下一條語(yǔ)句時(shí)調(diào)用time.sleep計(jì)算時(shí)間差,其結(jié)果就是0s 左右,此時(shí)不會(huì)在調(diào)用時(shí)輸出,待整個(gè)函數(shù)執(zhí)行完畢退出后,依次按照defer 順序輸出。

在這里插入圖片描述

step4

進(jìn)一步來到了time.sleep ,這也說明step3 確實(shí)給defer 語(yǔ)句賦值了,并沒有跳過,現(xiàn)在開始休眠3 s, 觀察3s后會(huì)光標(biāo)會(huì)去到哪里?

猜想:3s 后會(huì)先輸出函數(shù)結(jié)束 ,之后函數(shù)退出,開始執(zhí)行defer 語(yǔ)句.
結(jié)合匿名函數(shù)的時(shí)間差為3s左右,又因?yàn)?code>defer +匿名函數(shù)中的start 還未賦值,會(huì)回到開頭的defer + 匿名函數(shù)進(jìn)行賦值。

在這里插入圖片描述

等待3s鐘

在這里插入圖片描述

step5

3s后,來到了輸出函數(shù)結(jié)束的語(yǔ)句。

在這里插入圖片描述

進(jìn)一步函數(shù)退出,也就是整個(gè)函數(shù)執(zhí)行完畢!

在這里插入圖片描述

step6

又回到了剛才的defer + 匿名函數(shù)果然與step4的猜想一致!

在這里插入圖片描述

關(guān)鍵點(diǎn)來了!如下圖:這里會(huì)進(jìn)入defer + 匿名函數(shù) , 并給里面的start變量賦值。
注意,這里傳參start 還是一開始的start! 只不過time.since(start) 的time 增加(休眠)了3s ,這也很好的解釋了為什么defer + 匿名函數(shù) 輸出的是3s 左右,而defer + printf 語(yǔ)句卻是輸出0s 左右。

在這里插入圖片描述

之后匿名函數(shù)結(jié)束

在這里插入圖片描述

退出當(dāng)前的整個(gè)函數(shù)

在這里插入圖片描述

最后整個(gè)函數(shù)結(jié)束,輸出debug 的結(jié)果:這里加了一些debug 調(diào)試的時(shí)間,以運(yùn)行結(jié)果為準(zhǔn),見下。

在這里插入圖片描述

運(yùn)行結(jié)果如下:

在這里插入圖片描述

探討

debug 后,我們來探討一下為什么會(huì)出現(xiàn)這樣的情況?為什么結(jié)果會(huì)有所不同?里面的機(jī)制是什么?

defer + 輸出語(yǔ)句

傳值時(shí)機(jī):一開始調(diào)用defer 時(shí)傳入

Go 語(yǔ)言中所有的函數(shù)調(diào)用都是傳值的

雖然 defer 是關(guān)鍵字,但是也繼承了這個(gè)特性。假設(shè)我們想要計(jì)算 main 函數(shù)運(yùn)行的時(shí)間,可能會(huì)寫出以下的代碼:

package main

import (
    "fmt"
    "time"
)

func main() {
    start := time.Now()
    // 這里誤以為:startedAt是在time.Sleep之后才會(huì)將參數(shù)傳遞給defer所在語(yǔ)句的函數(shù)中
    defer fmt.Println(time.Since(start))

    time.Sleep(3 * time.Second)
}

關(guān)鍵點(diǎn):調(diào)用defer關(guān)鍵字會(huì)立刻拷貝函數(shù)中引用的外部參數(shù)

所以 time.Since(start) 的結(jié)果不是在 main 函數(shù)退出之前計(jì)算的,而是在 defer 關(guān)鍵字調(diào)用時(shí)賦值計(jì)算的,最終導(dǎo)致上述代碼輸出 0s。

defer + 匿名函數(shù)

傳值時(shí)機(jī):main函數(shù)結(jié)束后,執(zhí)行defer函數(shù) 時(shí)傳入,傳入函數(shù)指針

package main

import (
    "fmt"
    "time"
)

func main() {
    start := time.Now()
    // 使用匿名函數(shù),傳遞的是函數(shù)的指針
    defer func() {
        fmt.Println(time.Since(start))
    }()

    time.Sleep(3 * time.Second)
}

那為什么使用匿名函數(shù)就可以輸出3s 呢?關(guān)鍵點(diǎn):defer 使用匿名函數(shù) , 傳遞的是函數(shù)的指針(函數(shù)是一種指針類型),結(jié)合剛才的斷點(diǎn)分析,不會(huì)在一開始調(diào)用defer + 匿名函數(shù)的時(shí)候就直接賦值,而是在后面main函數(shù)退出時(shí),再執(zhí)行defer +匿名函數(shù) 時(shí)再傳入函數(shù)的指針,并給start變量賦值。

總結(jié)

總而言之:一開始調(diào)用defer+輸出語(yǔ)句會(huì)進(jìn)行傳值,會(huì)在調(diào)用defer 的時(shí)候就直接傳遞值的拷貝(如剛才的defer+輸出語(yǔ)句),從而計(jì)算時(shí)間差。
調(diào)用defer + 匿名函數(shù) 傳遞的是指針類型(如函數(shù)、匿名函數(shù)), 會(huì)在main函數(shù)退出時(shí),在執(zhí)行defer +匿名函數(shù) 時(shí)再傳入函數(shù)的指針,并給里面的變量賦值。

歸根結(jié)底,是傳入的類型不同,繼而導(dǎo)致傳入變量的時(shí)機(jī)不同,造成輸出的結(jié)果不同!

擴(kuò)展

面試官:請(qǐng)你用defertime.sleep寫一個(gè)計(jì)算函數(shù)運(yùn)行時(shí)間的程序
相信看到這里的小伙伴,已經(jīng)很清楚要寫什么代碼了!

package main

import (
    "fmt"
    "time"
)

func main() {
    start := time.Now()
    // 使用匿名函數(shù),傳遞的是函數(shù)的指針
    defer func() {
        fmt.Println(time.Since(start))
    }()

    time.Sleep(3 * time.Second)
}

到此這篇關(guān)于Go defer與time.sleep的使用與區(qū)別的文章就介紹到這了,更多相關(guān)Go defer與time.sleep內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家! 

相關(guān)文章

  • go?mod?tidy報(bào)錯(cuò)解決方法詳解

    go?mod?tidy報(bào)錯(cuò)解決方法詳解

    這篇文章主要為大家介紹了go?mod?tidy報(bào)錯(cuò)解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Go打包二進(jìn)制文件的實(shí)現(xiàn)

    Go打包二進(jìn)制文件的實(shí)現(xiàn)

    這篇文章主要介紹了Go打包二進(jìn)制文件的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • go?GCM?gin中間件的加密解密文件流處理

    go?GCM?gin中間件的加密解密文件流處理

    這篇文章主要介紹了go語(yǔ)言?GCM加密解密,gin中間件的加密解密及文件流處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪<BR>
    2022-05-05
  • 源碼分析Go語(yǔ)言使用cgo導(dǎo)致線程增長(zhǎng)的原因

    源碼分析Go語(yǔ)言使用cgo導(dǎo)致線程增長(zhǎng)的原因

    這篇文章主要從一個(gè)cgo調(diào)用開始解析Go語(yǔ)言源碼,從而分析一下造成線程增長(zhǎng)的原因,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一學(xué)習(xí)一下
    2023-06-06
  • Go語(yǔ)言利用標(biāo)準(zhǔn)庫(kù)flag編寫一個(gè)命令行參數(shù)解析器

    Go語(yǔ)言利用標(biāo)準(zhǔn)庫(kù)flag編寫一個(gè)命令行參數(shù)解析器

    在日常開發(fā)中,很多工具型程序都需要通過命令行參數(shù)來傳遞配置,本文將通過一個(gè)小實(shí)例,演示如何使用 Go 標(biāo)準(zhǔn)庫(kù) flag 開發(fā)一個(gè)簡(jiǎn)單的命令行參數(shù)解析器
    2025-09-09
  • Golang中的路由使用詳解

    Golang中的路由使用詳解

    這篇文章主要介紹了Golang中的路由使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • 解決Golang time.Parse和time.Format的時(shí)區(qū)問題

    解決Golang time.Parse和time.Format的時(shí)區(qū)問題

    這篇文章主要介紹了解決Golang time.Parse和time.Format的時(shí)區(qū)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • Go語(yǔ)言每天必學(xué)之switch語(yǔ)句

    Go語(yǔ)言每天必學(xué)之switch語(yǔ)句

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言每天必學(xué)之switch語(yǔ)句的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • golang中defer延遲機(jī)制的實(shí)現(xiàn)示例

    golang中defer延遲機(jī)制的實(shí)現(xiàn)示例

    本文講解了golang特殊的defer延遲機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-09-09
  • 關(guān)于Golang變量初始化/類型推斷/短聲明的問題

    關(guān)于Golang變量初始化/類型推斷/短聲明的問題

    這篇文章主要介紹了關(guān)于Golang變量初始化/類型推斷/短聲明的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02

最新評(píng)論

丰城市| 富裕县| 灵山县| 西平县| 洛川县| 长春市| 灵丘县| 桂平市| 库尔勒市| 怀宁县| 乌拉特中旗| 上林县| 云南省| 庄浪县| 剑阁县| 东乌珠穆沁旗| 陈巴尔虎旗| 博白县| 乐昌市| 呼伦贝尔市| 六枝特区| 唐山市| 邓州市| 屏山县| 墨江| 浙江省| 长宁县| 谷城县| 邢台市| 宁波市| 新和县| 阆中市| 古蔺县| 桓台县| 黄梅县| 同心县| 砚山县| 全州县| 西城区| 湘潭县| 阳春市|