亚洲综合原千岁中文字幕_国产精品99久久久久久久vr_无码人妻aⅴ一区二区三区浪潮_成人h动漫精品一区二区三

主頁 > 知識庫 > golang內(nèi)置函數(shù)len的小技巧

golang內(nèi)置函數(shù)len的小技巧

熱門標簽:如何利用高德地圖標注家 武漢百應(yīng)人工智能電銷機器人 揚州電銷外呼系統(tǒng)軟件 智能語音電銷的機器人 上海企業(yè)外呼系統(tǒng)排名 百度地圖標注位置網(wǎng)站 電腦外呼系統(tǒng)輻射大嗎 開通400電話申請流程 400手機電話免費辦理

len是很常用的內(nèi)置函數(shù),可以測量字符串、slice、array、channel以及map的長度/元素個數(shù)。

不過你真的了解len嗎?也許還有一些你不知道的小知識。

我們來看一道GO101的題目,這題也被GO語言愛好者周刊轉(zhuǎn)載:

package main

import "fmt"

func main() {
    var x *struct {
        s [][32]byte
    }
    
    fmt.Println(len(x.s[99]))
}

題目問你這段代碼的運行結(jié)果,選項有編譯錯誤、panic、32和0。

我們分析一下,別看x的聲明定義一大長串,實際上就是定義了一個有個[][32]byte的結(jié)構(gòu)體,然后x是這個結(jié)構(gòu)體的指針。

然后我們沒有初始化x,所以x是一個值為nil的指針。看到這里你也許以及有答案了,對nil指針解引用訪問它的成員s,那不就是panic嘛。即使引用x的成員合法,我們的s也沒有初始化,訪問沒有初始化的slice也會panic。

然而這么想你就錯了,代碼的實際運行結(jié)果是32!

為什么呢?我們看看len的幫助文檔:

For some arguments, such as a string literal or a simple array expression, the result can be a constant. See the Go language specification's "Length and capacity" section for details.

這句話很重要,對于結(jié)果是數(shù)組的表達式,len可能會是一個編譯期常量,而且數(shù)組類型的長度在編譯期是可知的,所以熟悉c++的朋友大概會立刻想到這樣的常量是不需要進行實際求值的,簡單類型推導(dǎo)即可獲得。不過口說無憑,我們看看spec里的描述:

The expression len(s) is constant if s is a string constant. The expressions len(s) and cap(s) are constants if the type of s is an array or pointer to an array and the expression s does not contain channel receives or (non-constant) function calls; in this case s is not evaluated. Otherwise, invocations of len and cap are not constant and s is evaluated.

如果表達式是字符串常量那么len(s)也是常量。如果表達式s的類型是array或者array的指針,且表達式不是channel的接收操作或是函數(shù)調(diào)用,那么len(s)是常量,且表達式s不會被求值;否則len和cap會對s進行求值,其計算結(jié)果也不是一個常量。

其實說的很清楚了,但還有三點需要說明。

第一個是視為常量的表達式里為什么不能含有chan的接收操作和函數(shù)調(diào)用?

這個答案很簡單,因為這兩個操作都是使用這明確希望發(fā)生“副作用”的。特別是從chan里接收數(shù)據(jù),還會導(dǎo)致goroutine阻塞,而我們的常量len表達式不會進行求值,這些你期望會發(fā)生的副作用便不會產(chǎn)生,會引發(fā)一些隱蔽的bug。

第二個是我們注意到了函數(shù)調(diào)用前用non-constant修飾了,這是什么意思?

按字面意思,一部分函數(shù)調(diào)用其實是可以在編譯期完成計算被當(dāng)成常量處理的,而另一些不可以。

在進一步深入之前我們先要看看golang里哪些東西是常量/常量表達式。

  • 首先是各種字面量以及對字面量的類型轉(zhuǎn)換產(chǎn)生的值了,無需多說。
  • 一部分內(nèi)置函數(shù):len、cap、imag、real、complex,它們在參數(shù)是常量的時候本身也是常量表達式。
  • unsafe.Sizeof,因為類型的大小也是編譯期就能確定的,所以它是常量表達式也很好理解。
  • 所有的常量之間的運算(加減乘除位運算等,除了非常量表達式函數(shù)的調(diào)用)都是常量表達式。

從上面的描述里可以看出兩點,內(nèi)置函數(shù)和unsafe.Sizeof的調(diào)用我們可以看成是constant function calls,所有常量表達式除了浮點數(shù)和復(fù)數(shù)表達式都可以在編譯期完成計算。而其他函數(shù)比如用戶自定義函數(shù)的調(diào)用,雖然仍然有可能在編譯期被求值優(yōu)化,但本身不屬于常量表達式。所以語言標準會加以區(qū)分。比如下面這個:

func add(x, y int) int {
    return x + y
}

func main() {
    fmt.Println(add(512, 513)) // 1025
}

如果我們看生成的匯編,會發(fā)現(xiàn)求值已經(jīng)完成,不需要調(diào)用add:

MOVQ    $1025, (SP)
PCDATA  $1, $0
CALL    runtime.convT64(SB)
MOVQ    8(SP), AX
XORPS   X0, X0
MOVUPS  X0, ""..autotmp_16+64(SP)
LEAQ    type.int(SB), CX
MOVQ    CX, ""..autotmp_16+64(SP)
MOVQ    AX, ""..autotmp_16+72(SP)
NOP
MOVQ    os.Stdout(SB), AX
LEAQ    go.itab.*os.File,io.Writer(SB), CX
MOVQ    CX, (SP)
MOVQ    AX, 8(SP)
LEAQ    ""..autotmp_16+64(SP), AX
MOVQ    AX, 16(SP)
MOVQ    $1, 24(SP)
MOVQ    $1, 32(SP)
NOP
CALL    fmt.Fprintln(SB)
MOVQ    80(SP), BP
ADDQ    $88, SP
RET

很明顯的,1025已經(jīng)在編譯期求值了,然而add的調(diào)用不是常量表達式,所以下面的代碼會報錯:

const number = add(512, 513) // error!!!

// example.go:11:7: const initializer add(512, 513) is not a constant

spec給出的實例是調(diào)用的內(nèi)置函數(shù),內(nèi)置函數(shù)也只有在參數(shù)是常量的情況下被調(diào)用才算做常量表達式:

const (
 c4 = len([10]float64{imag(2i)})  // imag(2i) is a constant and no function call is issued
 c5 = len([10]float64{imag(z)})   // invalid: imag(z) is a (non-constant) function call
)
var z complex128

所以len的表達式里如果用了non-constant的函數(shù)調(diào)用,那么就len本身不能算是常量表達式了。

這就有了最后一個疑問,題目中的x不是常量,為什么len的結(jié)果是常量呢?

標準只說表達式里不能有chan的接收和非常量表達式的函數(shù)調(diào)用,沒說其他的不可以。你也可以這么理解,表達式都有結(jié)果值,任何值除了無類型常量(這里顯然不是)都是要有一個確定的類型的,只要這個類型是數(shù)組或者數(shù)組的指針,那len就能獲得數(shù)組的長度,而這一切不需要s一定是常量表達式,編譯器可以簡單推導(dǎo)出表達式的值的類型。不能包含non-constant function calls和chan接收是我在第一點里解釋的,杜絕所有可能的副作用發(fā)生從而保證即使不對表達式求值程序也是正確的,不包含這兩個操作的表達式既可以是常量的也可以不是,所以這里我們能用x.s[99]作為len的參數(shù)。

說了這么多,只要len的參數(shù)類型為array或者array的指針并且符合要求,就不會進行求值,而題目里的表達式正好滿足這點,所以雖然我們看起來是會導(dǎo)致panic的代碼,但是本身并未進行實際求值,因此程序可以正常運行。另外cap也遵循同樣的規(guī)則。

最后,還有個小測驗,檢驗一下自己的學(xué)習(xí)吧:

// 以下哪些語句是正確的,哪些是錯誤的
var slice [][]*[10]int

const (
    a = len(slice[10000000000000][4]) // 1
    b = len(slice[1]) // 2
    c = len(slice) // 3
    d = len([1]int{1024}) // 4
    e = len([1]int{add(512, 512)}) // 5
    g = len([unsafe.Sizeof(slice)]int{}) // 6
    g = len([unsafe.Sizeof(slice)]int{int(unsafe.Sizeof(slice))}) // 7
)

參考
https://golang.org/ref/spec#Length_and_capacity

到此這篇關(guān)于golang內(nèi)置函數(shù)len的小技巧的文章就介紹到這了,更多相關(guān)golang內(nèi)置函數(shù)len內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • Go語言基本的語法和內(nèi)置數(shù)據(jù)類型初探

標簽:江西 宜賓 武漢 嘉峪關(guān) 延邊 張掖 新余 黑龍江

巨人網(wǎng)絡(luò)通訊聲明:本文標題《golang內(nèi)置函數(shù)len的小技巧》,本文關(guān)鍵詞  golang,內(nèi)置,函數(shù),len,的,小,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《golang內(nèi)置函數(shù)len的小技巧》相關(guān)的同類信息!
  • 本頁收集關(guān)于golang內(nèi)置函數(shù)len的小技巧的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    国产麻豆精品高清在线播放| 亚洲精品久久久中文字| 国产极品白嫩美女在线观看看 | 超级乱淫黄漫画免费| 黄视频网站在线看| 日韩一级精品视频在线观看| 亚洲天堂在线播放| 国产不卡在线观看视频| 国产精品1024永久免费视频| 日韩一级精品视频在线观看| 日本免费区| 国产麻豆精品高清在线播放| 日本特黄特色aaa大片免费| 韩国三级视频网站| 日韩在线观看网站| 精品久久久久久中文字幕2017| 国产高清视频免费| 国产高清在线精品一区二区| 久久99这里只有精品国产| 午夜在线亚洲| 91麻豆精品国产自产在线观看一区 | 亚洲精品久久久中文字| 91麻豆精品国产高清在线| 黄视频网站在线看| 成人在激情在线视频| 四虎影视精品永久免费网站| 精品视频在线观看视频免费视频| 99久久精品国产麻豆| 国产韩国精品一区二区三区| 国产精品免费久久| 国产网站免费视频| 国产伦理精品| 天天做日日爱| 国产成人精品综合在线| 国产原创视频在线| 美国一区二区三区| 国产视频一区二区在线观看| 韩国毛片免费| 欧美大片一区| 国产a视频| 一级女性全黄生活片免费| 人人干人人插| 日韩专区亚洲综合久久| 韩国三级视频在线观看| 四虎久久精品国产| 一本高清在线| 精品国产一区二区三区久| 成人免费观看网欧美片| 国产成人女人在线视频观看| 天天做日日爱| 国产高清视频免费| 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 亚洲精品永久一区| 一a一级片| 成人a级高清视频在线观看| 台湾美女古装一级毛片| 一a一级片| 国产一区二区福利久久| 日本在线不卡免费视频一区| 九九精品在线播放| 日韩免费在线观看视频| 日韩专区亚洲综合久久| 国产不卡精品一区二区三区| 国产一区二区福利久久| 精品视频在线看| 91麻豆精品国产自产在线观看一区 | 欧美爱爱动态| 欧美另类videosbestsex高清| 久久成人性色生活片| 99久久精品国产麻豆| 一级女性全黄生活片免费| 久久精品大片| 国产高清在线精品一区二区| 精品视频一区二区| 国产成人女人在线视频观看| 国产麻豆精品高清在线播放| 国产麻豆精品高清在线播放| 韩国毛片免费| 你懂的日韩| 精品视频在线观看视频免费视频| 一级女性全黄生活片免费| 日韩av东京社区男人的天堂| 国产一区免费观看| 国产成人精品综合在线| 国产伦精品一区三区视频| 91麻豆精品国产自产在线观看一区 | 好男人天堂网 久久精品国产这里是免费 国产精品成人一区二区 男人天堂网2021 男人的天堂在线观看 丁香六月综合激情 | 香蕉视频亚洲一级| 国产精品1024永久免费视频| 国产亚洲精品成人a在线| 欧美a级片视频| 国产亚洲精品成人a在线| 欧美a免费| 欧美电影免费看大全| 韩国毛片免费| 国产亚洲精品成人a在线| 国产视频一区二区在线观看| 你懂的日韩| 九九九网站| 国产韩国精品一区二区三区| 欧美大片一区| 国产高清在线精品一区二区| 午夜在线亚洲| 精品视频一区二区| 欧美1卡一卡二卡三新区| 亚洲精品永久一区| 精品视频在线看| 欧美国产日韩精品| 久久国产精品只做精品| 日本免费区| 日本乱中文字幕系列| 台湾美女古装一级毛片| 天天色成人网| 人人干人人插| 国产伦精品一区三区视频| 欧美激情一区二区三区在线| 欧美a级片视频| 精品在线免费播放| 一a一级片| 亚洲精品久久久中文字| 亚洲精品久久久中文字| 成人免费高清视频| 天天色成人网| 日韩一级精品视频在线观看| 美国一区二区三区| 韩国毛片免费| 欧美电影免费看大全| 一本高清在线| 精品国产一区二区三区久| 国产视频一区二区在线观看| 日韩在线观看免费| 国产麻豆精品高清在线播放| 韩国三级视频在线观看| 欧美激情一区二区三区在线| 青青久热| 美国一区二区三区| 国产不卡在线观看视频| 日本特黄特色aaa大片免费| 国产原创视频在线| 欧美爱爱动态| 久久精品大片| 久久国产精品只做精品| 久久成人性色生活片| 亚久久伊人精品青青草原2020| 欧美激情一区二区三区在线| 91麻豆精品国产高清在线| 九九精品在线播放| 国产韩国精品一区二区三区| 日本特黄特色aaa大片免费| 日本在线不卡免费视频一区| 成人高清视频在线观看| 国产不卡精品一区二区三区| 国产原创视频在线| 国产不卡在线观看视频| 日韩在线观看免费| 韩国三级视频网站| 国产伦精品一区三区视频| 亚洲女人国产香蕉久久精品 | 一级毛片视频在线观看| 精品久久久久久中文字幕2017| 久久成人性色生活片| 麻豆系列 在线视频| 九九精品在线播放| 国产伦精品一区三区视频| 香蕉视频亚洲一级| 欧美激情一区二区三区在线| 台湾美女古装一级毛片| 国产伦理精品| 国产伦精品一区三区视频| 日本在线不卡免费视频一区| 一a一级片| 精品久久久久久中文字幕2017| 日韩一级精品视频在线观看| 成人a级高清视频在线观看| 韩国三级视频在线观看| 午夜激情视频在线播放| 九九久久国产精品大片| 一级女性全黄生活片免费| 国产a视频| 国产一区免费观看| 精品国产香蕉在线播出| 成人免费观看网欧美片| 九九久久国产精品大片| 台湾美女古装一级毛片| 国产原创视频在线| 日本乱中文字幕系列| 国产高清视频免费| 午夜在线亚洲| 国产高清在线精品一区二区| 欧美另类videosbestsex高清| 欧美另类videosbestsex高清| 一级毛片视频在线观看| 精品视频一区二区| 久久精品大片| 999精品在线| a级毛片免费观看网站| 国产成人精品综合在线| 国产一区二区精品久久91| 99色视频在线观看| 一a一级片|