defe 有名返回值跟無名返回值區別 重要

2022-09-24 06:00:10 字數 4300 閱讀 7556

答案

例如:

123

4567

891011

1213

1415

1617

18

func test() int ()

defer func() ()

return i

}func main()

// defer2

// defer1

// return 0

這個例子中,可以看到 defer 的執行順序:後進先出。但是返回值並沒有被修改,這是由於 go 的返回機制決定的,執行 return 語句後,go 會建立乙個臨時變數儲存返回值,因此,defer 語句修改了區域性變數 i,並沒有修改返回值。那如果是有名的返回值呢?

123

4567

891011

1213

14

func test() (i int) ()

return i

}func main()

// defer2

// return 1

這個例子中,返回值被修改了。對於有名返回值的函式,執行 return 語句時,並不會再建立臨時變數儲存,因此,defer 語句修改了 i,即對返回值產生了影響

再看下面乙個題

import "fmt"

var name string = "go"

func myfunc() string ()

fmt.printf("myfunc 函式裡的name:%s\n", name)

return name

}func main()

輸出如下

myfunc 函式裡的name:go

main 函式裡的name: python

main 函式裡的myname: go

來一起理解一下這段**,第一行很直觀,name 此時還是全域性變數,值還是go

第二行也不難理解,在 defer 裡改變了這個全域性變數,此時name的值已經變成了 python

重點在第三行,為什麼輸出的是 go ?

解釋只有乙個,那就是 defer 是return 後才呼叫的。所以在執行 defer 前,myname 已經被賦值成 go 了

答案答案答案答案答案答案專題:go 語言面試題

本文發表於 2020-09-04,最後修改於 2022-02-25。

本站永久網域名稱「 geektutu.com 」,也可搜尋「 極客兔兔 」找到我。

go2 新特性簡明教程

發表於2019-08-15, 閱讀約17分鐘

tensorflow 2 中文文件 - 過擬合與欠擬合

發表於2019-07-12, 閱讀約19分鐘

pandas 資料處理(三) - cheat sheet 中文版

發表於2019-06-16, 閱讀約4分鐘

#關於我 (9)

#go (48)

#百寶箱 (2)

#cheat sheet (1)

#go語言高效能程式設計 (20)

#友鏈 (1)

#pandas (3)

#機器學習 (9)

#python (10)

#rust (1)

#tensorflow (9)

#mnist (5)

#強化學習 (3)

#openai gym (4)

#dqn (1)

#q-learning (1)

#cnn (1)

#tensorflow 2 (10)

#官方文件 (10)

未登入使用者

預覽使用 github 登入

發表於超過 1 年前

新手有兩個問題想請教下:

**中rune("go語言")意思是使用rune強制轉換型別是吧?

其中**塊中的第10行

b = b[:len(a)]
這麼操作的目的是什麼?保證陣列切片一樣長嗎?

發表於超過 1 年前

@lisgroup

第乙個問題,你的理解是對的,字串型別轉換為 rune 切片型別。

第二個問題,這種寫法是為了優化邊界檢查從而提公升執行時效率的。在go語言中稱之為bounds check elimination,簡稱為 bce。簡言解釋下,如果沒有這一句,在執行時,go 語言每次都會對 b[i] 做邊界檢查,看看是否越界了,如果越界了,就 panic。但是如果加上這一句,go語言在編譯時,能夠做一些簡單的靜態分析,發現 b[i] 是不可能越界的,編譯時就能將沒必要的邊界檢查給優化了,那麼執行時,就不會對 b[i] 做邊界檢查,從而提公升執行時效率。

這篇文章提供了更多的示例,幫助理解。bounds check elimination - go101.org

發表於超過 1 年前

_ = b[:len(a)]

發表於超過 1 年前

@givetimetolife 我覺得這種寫法應該也是ok的,go 的切片底層對應的陣列是一樣的,切片只是改變指標的位置,這一步檢查幾乎是沒有損耗的。

發表於大約 1 年前

2. q13 如何判斷 2 個字串切片(slice) 是相等的?

針對這個中的b = b[:len(a)],使用go 1.15.6編譯,已經沒有效果了,在len判斷的時候就已經做了優化

發表於大約 1 年前

@zzhaolei 感謝指出問題,新版本將b = b[:len(a)]去掉後,也不會產生邊界檢查(bounds check)了。

是否產生邊界檢查,可以用下面的命令驗證。

go build -gcflags="-d=ssa/check_bce/debug=1" main.go

例如針對下面的例子,如果 s[2] 沒有越界,那麼 s[1] 和 s[0] 肯定是合法,因此只需要對 s[2] 做一次邊界檢查即可:

package main

func f(s int)

func main() {}

go build -gcflags="-d=ssa/check_bce/debug=1" main.go

# command-line-arguments

./main.go:4:7: found isinbounds

yinhuanyi—— 博主,group的getfrompeer方法返回的byteview必須是指標,好像寫錯了 ``` func (g *group) getfrompeer(peer peergetter, key string) (*byteview, error) , err } return &byteview, nil } ```

有返回值和無返回值函式

前面在定義函式時,有些函式使用了return語句,有些函式沒有使用return語句,使用return語句與不使用return語句有什麼區別呢?由前面的章節我們知道,若定義函式時沒有使用return語句,則預設返回乙個none。要返回乙個none,可以只寫乙個return,但要返回具體的數值,就需要在...

返回值優化

通過傳值方式返回要建立新物件時,應注意使用的形式,例如在operator return integer left.l right.l 咋看起來這像是乙個 對乙個建構函式的呼叫 其實並非如此。這是臨時物件語法,它是在說 建立乙個臨時integer物件並返回它 據此我們可能認為如果建立乙個有名字的區域性...

返回值優化

返回值優化,是一種屬於編譯器的技術,它通過轉換源 和物件的建立來加快源 的執行速度。rvo return value optimization。class complex 複數 complex const complex a real a.real imag a.imag complex opera...