傳個(gè)參數(shù)都有坑,我蚌埠了!
最近在工作中發(fā)現(xiàn)一個(gè)坑,關(guān)鍵是這個(gè)坑還不報(bào)錯(cuò),所以在此記錄一下,順便也對相關(guān)知識點(diǎn)做一個(gè)總結(jié)。
關(guān)于這個(gè)坑,還得從「不定參數(shù)」說起。
不定參數(shù)?
不定參數(shù),顧名思義,也就是「參數(shù)個(gè)數(shù)不確定」的時(shí)候golang支持的一種機(jī)制。
舉個(gè)例子?
我們想實(shí)現(xiàn)一個(gè)多個(gè)數(shù)字累加的方法,既然是多個(gè)數(shù)字,那么數(shù)字的個(gè)數(shù)肯定是不確定的,所以我們可以如下編寫。
通過上面的示例我們可以看出不定參數(shù)的使用還是很簡單的,只要在參數(shù)定義的時(shí)候,在「類型前面加上三個(gè)點(diǎn)」就可以了。但是不定參數(shù)在使用的時(shí)候還有其他需要注意的問題需要注意一下。
- 所有的不定參數(shù)類型必須是相同的。
- 不定參數(shù)必須是函數(shù)的最后一個(gè)參數(shù)。
- 不定參數(shù)在函數(shù)體內(nèi)相當(dāng)于一個(gè)切片,對切片的操作同樣適合對不定參數(shù)的操作。(比如上述例子中,是可以對args做「for range」操作的)。
- 切片也可以作為參數(shù)傳遞給不定參數(shù),切片名稱后面要加上“...”。
前面三點(diǎn)其實(shí)還是比較好理解的,針對第四點(diǎn)看看下面例子,也是「容易出問題」的地方,而且本文要說的「坑」也和這個(gè)有關(guān)。
通過上述例子咱們應(yīng)該已經(jīng)對不定參數(shù)有了一定的掌握,接下來咱們看一個(gè)特殊的場景 如果「不定參數(shù)的各個(gè)參數(shù)類型不一樣」怎么辦?這種場景其實(shí)還是很常見的,用interface類型即可解決。比如我們要封裝一個(gè)生成rediskey的方法。?
上面的代碼看似沒有問題,但是輸出結(jié)果卻看似來就像亂碼一樣,這是為什么呢?我們來分析一下
- 我們在main函數(shù)中調(diào)用「MakeRedisKey」函數(shù)的時(shí)候傳進(jìn)去的「ucid和name」都為不定參數(shù)。
- 「在MakeRedisKey函數(shù)中」,打印出來的args的類型為「切片」類型,也就是 []interface {}。
- 我們看一下「fmt.Sprintf」函數(shù)的定義。
我們會(huì)發(fā)現(xiàn)Sprintf的第二個(gè)參數(shù)也是「不定參數(shù)」。
這就相當(dāng)于在「MakeRedisKey」中,我們拿著「切片類型」的參數(shù)args,去傳給一個(gè)「不定參數(shù)」作為參數(shù),按照我們上面總結(jié)的**把切片傳給不定參數(shù)的時(shí)候,需要在參數(shù)后面加上...**這條定律,上面代碼改成如下即可正常。
這樣我們就可以得到正常的結(jié)果了。最后總結(jié)一下,「我們在使用不定參數(shù)的時(shí)候,尤其是涉及到多次傳遞的時(shí)候,一定不要想當(dāng)然,記得在中間傳遞過程中在參數(shù)后面加上...」。