Golang中的函數

函數

在go語言中,函數的基本組成爲:關鍵字func、函數名、參數列表、返回值、函數體和返回語句數組

  • 函數的定義

定義一個最簡單的加法函數閉包

func Add(a int,b int)(ret int,err error){
    if a < 0 || b < 0{
        err = errors.New("這個函數只支持兩個非負數的數字相加")
        return
    }

    return a + b,nil
}

若是參數列表中若干相鄰的參數類型是相同的話,好比上述例子中的a和b,則能夠在參數列表中省略前面的類型聲明,例如:函數

func Add(a,b int)(ret int,err error){
    // ...     
}

若是返回值列表中多個返回值的類型相同,也能夠用一樣的方式合併code

若是函數只有一個返回值,也能夠這樣寫:對象

func Add(a,b int) int{
    // ...    
}
  • 函數的調用

函數調用很是方便,只須要事先導入了該函數所在的包,就能夠直接調用了,在go語言中,對函數命名有必定要求,只有大寫開頭的字母才能夠被其餘包調用,小寫字母開頭的函數只能在本包被調用作用域

例:假設Add函數在func1中開發

package main

import (
    "fmt"
    //導入包
    "functions/func1"
)

func main()  {
    a := 1
    b := 2
    // 經過包名調用函數
    ret,err := func1.Add(a,b)
    fmt.Println(ret,err)
}

函數的不定參數

  • 不定參數的類型

不定參數是值函數傳入的參數個數爲不定數量。io

func main(){
    // myfunc函數能夠接收任意個int類型的參數
    myfunc(1,2,3,4,5,6,7,8)
}

// ... 表示不定參數
func myfunc(args ...int){
    for _,arg := range args {
        fmt.Println(arg)
    }
}

...type格式的類型只能做爲函數的參數類型存在,而且必須是最後一個參數。。它是一
個語法糖(syntactic sugar),即這種語法對語言的功能並無影響for循環

從內部實現機理上來講,類型...type本質上是一個數組切片,也就是[]type,這也是爲
什麼上面的參數args能夠用for循環來得到每一個傳入的參數。
假如沒有...type這樣的語法糖,開發者將不得不這麼寫:function

func myfunc2(args []int) {
    for _, arg := range args {
        fmt.Println(arg)
        }
}

從函數的實現角度來看,這沒有任何影響,該怎麼寫就怎麼寫。但從調用方來講,情形則完
全不一樣:

myfunc2([]int{1, 3, 7, 13})
  • 任意類型的不定參數
func myfunc(args ...interface{}){
    // ...
}

用interface{}傳遞任意類型數據是go語言的慣例用法

匿名函數與閉包

  • 匿名函數

匿名函數由一個不帶函數名的函數聲明和函數體組成,如:

func(a,b int) bool {
    return a * b
}

匿名函數能夠直接賦值給一個變量或者直接執行

// 賦值給一個變量
f := func(a,b int) int {
    return a * b
}

// 直接執行
func(a,b int) bool {
    return a * b
}(1,2)
  • 閉包
    • 閉包的基本概念:閉包是能夠包含自由(未綁定到特定對象)變量的代碼塊,這些變量不在這個代碼塊內或者
      任何全局上下文中定義,而是在定義代碼塊的環境中定義。要執行的代碼塊(因爲自由變量包含
      在代碼塊中,因此這些自由變量以及它們引用的對象沒有被釋放)爲自由變量提供綁定的計算環
      境(做用域)。
    • 閉包的價值:閉包的價值在於能夠做爲函數對象或者匿名函數,對於類型系統而言,這意味着不只要表示
      數據還要表示代碼。支持閉包的多數語言都將函數做爲第一級對象,就是說這些函數能夠存儲到
      變量中做爲參數傳遞給其餘函數,最重要的是可以被函數動態建立和返回。
    • go語言中的閉包
func main()  {
    var j int = 5
    //一個函數的返回值是一個函數的執行
    a := func()(func()) {
        var i int = 10
        return func() {
            fmt.Printf("i,j : %d  %d \n",i,j)
        }
    }()
    a()
    j *= 2
    a()

}
相關文章
相關標籤/搜索