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

Go語(yǔ)言defer的一些神奇規(guī)則示例詳解

 更新時(shí)間:2022年11月17日 16:15:42   作者:程序員麻辣燙  
這篇文章主要為大家介紹了Go語(yǔ)言defer的一些神奇規(guī)則示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

測(cè)試題

defer有一些規(guī)則,如果不了解,代碼實(shí)現(xiàn)的最終結(jié)果會(huì)與預(yù)期不一致。對(duì)于這些規(guī)則,你了解嗎?

這是關(guān)于defer使用的代碼,可以先考慮一下返回值。

package main
import (
	"fmt"
)
/**
 * @Author: Jason Pang
 * @Description: 快照
 */
func deferFuncParameter1() {
	var aInt = 1
	defer fmt.Println(aInt)
	aInt = 2
	return
}
/**
 * @Author: Jason Pang
 * @Description: 快照
 */
func deferFuncParameter2() {
	var aInt = 1
	defer func(t int) {
		fmt.Println(t)
	}(aInt)
	aInt = 2
	return
}
/**
 * @Author: Jason Pang
 * @Description: 動(dòng)態(tài)
 */
func deferFuncParameter3() {
	var aInt = 1
	defer func() {
		fmt.Println(aInt)
	}()
	aInt = 2
	return
}
/**
 * @Author: Jason Pang
 * @Description: 影響返回值
 * @return ret
 */
func deferFuncReturn1() (ret int) {
	ret = 10
	defer func() {
		ret++
		fmt.Println("-----", ret)
	}()
	return 2
}
/**
 * @Author: Jason Pang
 * @Description: 不影響返回值
 * @return ret
 */
func deferFuncReturn2() (ret int) {
	ret = 10
	defer func(ret int) {
		ret++
		fmt.Println("-----", ret)
	}(ret)
	return 2
}
/**
 * @Author: Jason Pang
 * @Description: defer順序
 */
func deferFuncSeq1() {
	var aInt = 1
	defer fmt.Println(aInt)
	aInt = 2
	defer fmt.Println(aInt)
	return
}
func main() {
	fmt.Println("快照")
	deferFuncParameter1()
	deferFuncParameter2()
	deferFuncParameter3()
	fmt.Println("返回值")
	fmt.Println(deferFuncReturn1())
	fmt.Println(deferFuncReturn2())
	fmt.Println("執(zhí)行順序")
	deferFuncSeq1()
}

正確輸出為:

? myproject go run main.go

快照

1

1

2

返回值

----- 3

3

----- 11

2

執(zhí)行順序

2

1

分析

defer有幾條重要規(guī)則,上面的結(jié)果都能從這些規(guī)則中找到答案。

規(guī)則一當(dāng)defer被聲明時(shí),其參數(shù)就會(huì)被實(shí)時(shí)解析

當(dāng)defer被聲明的時(shí)候,如果直接使用了參數(shù),此時(shí)的參數(shù)就會(huì)使用快照值,在整個(gè)生命周期內(nèi)不會(huì)變化。如deferFuncParameter1、deferFuncParameter2,雖然aInt在defer聲明后被變更,但defer里的值不會(huì)再變了。

func deferFuncParameter1() {
	var aInt = 1
	defer fmt.Println(aInt)
	aInt = 2
	return
}
func deferFuncParameter2() {
	var aInt = 1
	defer func(t int) {
		fmt.Println(t)
	}(aInt)
	aInt = 2
	return
}

與之相反的是deferFuncParameter3,隨aInt的變化而變化。

func deferFuncParameter3() {
	var aInt = 1
	defer func() {
		fmt.Println(aInt)
	}()
	aInt = 2
	return
}

規(guī)則二 defer可能操作主函數(shù)的具名返回值

defer有可能更改函數(shù)的返回值,這是最容易導(dǎo)致錯(cuò)誤的地方。

關(guān)鍵字_return_不是一個(gè)原子操作,實(shí)際上_return_只代理匯編指令_ret_,即將跳轉(zhuǎn)程序執(zhí)行。比如語(yǔ)句 return i ,實(shí)際上分兩步進(jìn)行,即將i值存入棧中作為返回值,然后執(zhí)行跳轉(zhuǎn),而defer的執(zhí)行時(shí)機(jī)正是跳轉(zhuǎn)前,所以說(shuō)defer執(zhí)行時(shí)還是有機(jī)會(huì)操作返回值的。return i的執(zhí)行過(guò)程如下所示:

result = i 
執(zhí)行defer
return

所以基于這個(gè)規(guī)則,對(duì)于deferFuncReturn1,

func deferFuncReturn1() (ret int) {
	ret = 10
	defer func() {
		ret++
		fmt.Println("-----", ret)
	}()
	return 2
}

執(zhí)行過(guò)程為:

ret = 2
ret++
fmt.Println("-----", ret)
return

所以最終ret的值為3。

對(duì)于deferFuncReturn2,因?yàn)閐efer聲明的時(shí)候直接使用了參數(shù),所以使用的是快照,不會(huì)影響ret的返回值。

規(guī)則三 延遲函數(shù)執(zhí)行按后進(jìn)先出順序執(zhí)行

即先出現(xiàn)的 defer最后執(zhí)行

這個(gè)規(guī)則大家都很熟悉,defer按照棧的順序執(zhí)行。

坑實(shí)例

舉一個(gè)錯(cuò)誤使用defer的實(shí)例。在go中使用事務(wù)時(shí),有一種推薦寫(xiě)法:將Rollback放到defer中,通過(guò)判斷函數(shù)是否有報(bào)錯(cuò)或者panic,來(lái)判斷是否要回滾。

func  Update() (resp *baseinfo.Resp, err error) {
	//開(kāi)啟事務(wù)
	panicked := true
	tx, err := db.TXBegin()
	if err != nil {
		return resp, nil
	}
	defer func() {
		if panicked || err != nil {
			tx.Rollback()
		}
	}()
	//更新
	err = h.update(shopId, tx)
	if err != nil {//失敗返回
		return resp, nil
	}
	panicked = false
	err = tx.Commit().Error
	if err != nil { //失敗返回
		return resp, nil
	}
	return
}

判斷回滾的err正是函數(shù)的具名返回值,在有報(bào)錯(cuò)的情況下,返回值被賦值為nil,這意味如果有失敗,Rollback也不會(huì)被執(zhí)行。

之所以不將err直接返回,而是使用nil,是因?yàn)榭蚣茉O(shè)計(jì)的問(wèn)題,業(yè)務(wù)錯(cuò)誤通過(guò)resp返回,如果直接返回err,框架會(huì)認(rèn)為是RPC錯(cuò)誤。

以上就是Go語(yǔ)言defer的一些神奇規(guī)則示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Go語(yǔ)言defer規(guī)則的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

  • Go語(yǔ)言安裝和GoLand2021最全超詳細(xì)安裝教程

    Go語(yǔ)言安裝和GoLand2021最全超詳細(xì)安裝教程

    Go語(yǔ)言和GoLand的關(guān)系好比于java和idea、python和pycharm,因此我們需要先安裝好Go語(yǔ)言后才能安裝GoLand。它的安裝和java,python的安裝大同小異,好了,下面給大家?guī)?lái)了GoLand2021安裝教程,需要的朋友參考下吧
    2021-08-08
  • GoLang實(shí)現(xiàn)日志收集器流程講解

    GoLang實(shí)現(xiàn)日志收集器流程講解

    這篇文章主要介紹了GoLang實(shí)現(xiàn)日志收集器流程,看日志是開(kāi)發(fā)者平時(shí)排查BUG所必須的掌握的技能,但是日志冗雜,所以寫(xiě)個(gè)小工具來(lái)收集這些日志幫助我們排查BUG,感興趣想要詳細(xì)了解可以參考下文
    2023-05-05
  • GO制作微信機(jī)器人的流程分析

    GO制作微信機(jī)器人的流程分析

    這篇文章主要介紹了利用go制作微信機(jī)器人,本文主要包括項(xiàng)目基礎(chǔ)配置及詳細(xì)代碼講解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • 詳解Golang中strconv庫(kù)的用法

    詳解Golang中strconv庫(kù)的用法

    strconv包提供了字符串和基本數(shù)據(jù)類(lèi)型之間的相互轉(zhuǎn)換功能,本文將帶大家深入了解Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的strconv包,掌握其常用的函數(shù)和用法,希望對(duì)大家有所幫助
    2023-06-06
  • Go語(yǔ)言中defer語(yǔ)句的用法

    Go語(yǔ)言中defer語(yǔ)句的用法

    這篇文章介紹了Go語(yǔ)言中defer語(yǔ)句的用法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • 探索分析Go?HTTP?GET請(qǐng)求發(fā)送body

    探索分析Go?HTTP?GET請(qǐng)求發(fā)送body

    這篇文章主要為大家介紹了探索分析Go?HTTP?GET請(qǐng)求發(fā)送body,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Go語(yǔ)言變量初始化的實(shí)現(xiàn)示例

    Go語(yǔ)言變量初始化的實(shí)現(xiàn)示例

    在Go語(yǔ)言中,變量的初始化是編寫(xiě)程序時(shí)經(jīng)常遇到的重要操作之一,本文主要介紹了Go語(yǔ)言變量初始化的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-04-04
  • 詳解如何修改Go結(jié)構(gòu)體的私有字段

    詳解如何修改Go結(jié)構(gòu)體的私有字段

    在 Go 語(yǔ)言中,結(jié)構(gòu)體字段的訪問(wèn)權(quán)限是由字段名的首字母決定的:首字母大寫(xiě)表示公共字段(public),首字母小寫(xiě)表示私有字段(private),本文給大家介紹了如何修改Go結(jié)構(gòu)體的私有字段,需要的朋友可以參考下
    2025-01-01
  • 詳解Golang 推薦的命名規(guī)范

    詳解Golang 推薦的命名規(guī)范

    這篇文章主要介紹了詳解Golang 推薦的命名規(guī)范,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-02-02
  • 最新評(píng)論

    韶关市| 贡山| 涞水县| 金昌市| 延庆县| 马鞍山市| 千阳县| 稷山县| 桐柏县| 黎平县| 昭苏县| 桃园市| 南涧| 江川县| 吐鲁番市| 长沙县| 海阳市| 正阳县| 云浮市| 衡山县| 邵阳县| 武陟县| 呼玛县| 临漳县| 武威市| 永福县| 吉安县| 朔州市| 玉树县| 五家渠市| 邓州市| 吴忠市| 石狮市| 运城市| 丰都县| 淅川县| 江门市| 大荔县| 兰溪市| 互助| 罗平县|