golang 定义一个空切片_Golang简单入门教程——函数进阶使用
本文始發(fā)于個人公眾號:TechFlow,原創(chuàng)不易,求個關(guān)注
今天是golang專題的第八篇,我們來聊聊golang當中的函數(shù)。
我們在之前的時候已經(jīng)介紹過了函數(shù)的基本用法,知道了怎么樣設(shè)計或者是定義一個函數(shù),以及怎么樣調(diào)用一個函數(shù),還了解了defer的用法。今天這篇文章我們來繼續(xù)深入這個話題,來看看golang當中關(guān)于函數(shù)的一些進階的用法。
返回error
前文當中我們曾經(jīng)提到過,在golang當中并沒有try catch捕獲異常的機制。在其他語言當中異常只有一種,可以通過try catch語句進行捕獲,而golang當中做了區(qū)分,將異常分為兩種,一種是可以在函數(shù)當中返回的error,另外一種是嚴重的會引起程序崩潰的panic。
在golang中,error也是一個數(shù)據(jù)類型,由于golang支持函數(shù)的多值返回,所以我們可以設(shè)置一個返回值是error。我們通過對這個error的判斷來獲取運行函數(shù)的情況。
舉個例子,比如說,假設(shè)我們實現(xiàn)一個Divide函數(shù)實現(xiàn)兩個int相除。那么顯然我們需要除數(shù)不能為0,當除數(shù)為0的時候我們需要返回一個異常。這個時候我們可以把代碼寫成這樣:
// Divide test func Divide(a, b int) (ret int, err error) {if b == 0 {err = errors.New("divisor is zero")return}return a / b, nil }當我們調(diào)用函數(shù)的時候,我們用兩個變量去接收這個函數(shù)返回的結(jié)果,第二個變量的類型是error。當這個函數(shù)成功執(zhí)行的時候第二個變量的結(jié)果為nil,我們只需要判斷它是否等于nil,就可以知道函數(shù)執(zhí)行是否成功。如果不成功,我們還可以記錄失敗的原因。
func main() {ret, err := Divide(5, 2)if err == nil {fmt.Println(ret)} else {fmt.Println(err)} }這種用法在golang當中非常常見,我們之前在介紹字符串相關(guān)操作的時候也介紹過返回error的用法。我們在設(shè)計函數(shù)的時候如果需要判斷輸入的合法性可以使用error,這樣就可以保證handle住非法的情況,并且也能讓下游感知到。
不定參數(shù)
不定參數(shù)的用法在很多語言當中都有,比如在Python當中,不定參數(shù)是*args。通過*args我們可以接受任何數(shù)量的參數(shù),由于Python是弱變量類型的語言,所以args這些參數(shù)的類型可以互不相同。但是golang不行,golang嚴格限制類型,不定參數(shù)必須要保證類型一樣。除此之外,其他的用法和Python一樣,不定參數(shù)會以數(shù)組的形式傳入函數(shù)內(nèi)部,我們可以使用數(shù)組的api進行訪問。
我們來看一個例子,我們通過...來定義不定參數(shù)。比如我們可以實現(xiàn)一個sum函數(shù),可以將任意個int進行累加。
func Sum(nums ... int) int{ret := 0for _, num := range nums {ret += num}return ret }我們來仔細研究一下上面這個例子,在這個例子當中,我們通過...傳入了一個不定參數(shù),我們不定參數(shù)的類型只寫一次,寫在...的后面。從底層實現(xiàn)的機制上來說,不定參數(shù)本質(zhì)上是將傳入的參數(shù)轉(zhuǎn)化成數(shù)組的切片。但是這就有了一個問題,既然傳入的是一個數(shù)組的切片,我們?yōu)槭裁匆獙iT設(shè)置一個關(guān)鍵字,而不是規(guī)定傳入一個切片呢?
比如上面的代碼我們完全可以寫成這樣:
func Sum(nums []int) int{ret := 0for _, num := range nums {ret += num}return ret }無論從代碼的閱讀還是編寫上來看相差并不大,好像這樣做完全沒有意義,其實不是這樣的。這個關(guān)鍵字簡化的并不是函數(shù)的設(shè)計方,而是函數(shù)的使用方。如果我們規(guī)定了函數(shù)的輸入是一個切片,那么當我們在傳入數(shù)據(jù)的時候,必須要使用強制轉(zhuǎn)化,將我們的數(shù)據(jù)轉(zhuǎn)化成切片,比如這樣:
Sum([]int(3, 4, 6, 8))而使用...關(guān)鍵字我們則可以省略掉強制轉(zhuǎn)化的過程,上面的代碼我們寫成這樣就可以了:
Sum(3, 4, 6, 8)很明顯可以看出差異,使用不定參數(shù)的話調(diào)用方會輕松很多,不需要再進行額外的轉(zhuǎn)換。如果我們要傳入的也是一個數(shù)組,那么在傳遞的時候也需要用...符號將它展開。
a := make([]int) a = append(a, 3) a = append(a, 4) Sum(a...) Sum(a[1:]...)既然聊到不定參數(shù)的傳遞,那么又涉及到了一個問題,當我們想要像Python那樣傳遞多個類型不同的參數(shù)的時候,應(yīng)該怎么辦呢?按照道理golang是靜態(tài)類型的語言,限制死了參數(shù)的類型,是不能隨便轉(zhuǎn)換的才對。但是偏偏這樣操作是可以的,因為golang當中有一個特殊的類型,叫做interface。
interface的用法很多,一個很重要的用法是用在面向?qū)ο螽斨谐洚斀Y(jié)構(gòu)體的接口。這里我們不做過多深入,我們只需要知道,interface的一個用法是可以用來代替所有類型的變量。我們來看一個例子:
func testInterface(args ...interface{}) {for _, arg := range args {switch arg.(type) {case int:fmt.Println("it's a int")case string:fmt.Println("it's a string") case float32:fmt.Println("it's a float")default:fmt.Println("it's an unknown type")}} }func main() {testInterface(3, 4.5, "abc") }我們可以用.(type)獲取一個interface變量實際的類型,這樣我們就實現(xiàn)了任意類型任意數(shù)量參數(shù)的傳入。
匿名函數(shù)和閉包
匿名函數(shù)我們在Python當中經(jīng)常使用到,其實這個概念出現(xiàn)已久,最早可以追溯到1958年Lisp語言。所以這并不是一個新鮮的概念,只是傳統(tǒng)的C、C++等語言沒有支持匿名函數(shù)的功能,所以顯得好像是一個新出現(xiàn)的概念一樣。golang當中也支持匿名函數(shù),但是golang當中匿名函數(shù)的使用方式和Python等語言稍稍有些不同。
在Python當中我們是通過lambda關(guān)鍵字來定義匿名函數(shù),它可以被傳入另一個函數(shù)當中,也可以賦值給一個變量。golang當中匿名函數(shù)的定義方式和普通函數(shù)基本是一樣的,只是沒有函數(shù)名而已,不過它也可以被傳入函數(shù)或者是賦值給另一個變量。
比如:
s := func(a, b int) int {return a + b }c := s(3, 4)除了匿名函數(shù)之外,golang還支持閉包。閉包的概念我們在之前Python閉包的介紹當中曾經(jīng)提到過,我們之前也用過好幾次,閉包的本質(zhì)不是一個包,而是一個函數(shù),是一個持有外部環(huán)境變量的函數(shù)。比如在Python當中,我們經(jīng)常可以看到這樣的寫法:
def outside(x):def inside(y):print(x, y)return insideins = outside(3) ins(5) #3, 5我們可以看到outside這個函數(shù)返回了inside這個函數(shù),對于inside這個函數(shù)而言,它持有了x這個變量。x這個變量并不是屬于它的,而是定義在它的外部域的。并且我們在調(diào)用inside的時候是無法干涉這個變量的,這就是一個閉包的典型例子。根據(jù)輪子哥的說法,閉包的閉的意思并不是封閉內(nèi)部,而是封閉外部。當外部scope失效的時候,函數(shù)仍然持有一份外部的環(huán)境的值。
golang當中閉包的使用方法大同小異,我們來看一個類似的例子:
func main() {a := func(x int) (func(int)) {return func(y int){fmt.Println(x, y)}}b := a(4)b(5) }這個閉包的例子和剛才上面Python那個例子是一樣的,唯一不同的是由于golang是強類型的語言,所以我們需要在定義閉包的時候?qū)⑤斎牒洼敵龅念愋投x清楚。
總結(jié)
關(guān)于golang當中函數(shù)的高級用法就差不多介紹完了,這些都是實際編程當中經(jīng)常使用的方法,如果想要學好golang這門語言的話,這些是基本功。如果你之前有其他語言的基礎(chǔ),來寫go的話,整體上手的難度還是不大的,很多設(shè)計都可以在其他的語言當中找到影子,有了參照來學會簡單得多。
我很難描述實際工作當中寫golang的體驗,和我寫任何一門其他的語言都不一樣,有一種一開始期望很低,慢慢慢慢總能發(fā)現(xiàn)驚喜的感覺。我強烈建議大家去實際感受一下。
如果喜歡本文,可以的話,請點個關(guān)注,給我一點鼓勵,也方便獲取更多文章。
總結(jié)
以上是生活随笔為你收集整理的golang 定义一个空切片_Golang简单入门教程——函数进阶使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梅林安装opkg后安装iperf3_ce
- 下一篇: layui分页limit不显示_小心避坑