使用函數

函數就是將一段輸入數據轉換爲輸出數據的公用代碼塊閉包

函數示例函數

package main

import "fmt"

func slice_sum(arr []int) int {
    sum := 0
    for _, elem := range arr {
        sum += elem
    }
    return sum
}

func main() {
    var arr1 = []int{1, 3, 2, 3, 2}
    var arr2 = []int{3, 2, 3, 1, 6, 4, 8, 9}
    fmt.Println(slice_sum(arr1))
    fmt.Println(slice_sum(arr2))
}

一、命名返回值,即爲返回值預先定義一個名稱,最後直接一個return,就能夠將預約義的返回值所有返回ui

從新定義上面的求和函數,示例代碼以下spa

func slice_sum(arr []int) (sum int) {
    sum = 0
    for _, elem := range arr {
        sum += elem
    }
    return
}

二、函數多返回值,即同時返回多個值code

package main

import "fmt"

func slice_sum(arr []int) (int, float64) {
    sum := 0
    //注意是float64類型
    avg := 0.0
    for _, elem := range arr {
        sum += elem
    }
    avg = float64(sum) / float64(len(arr))
    return sum, avg
}

func main() {
    var arr = []int{3, 2, 3, 1, 6, 4, 8, 9}
    fmt.Println(slice_sum(arr))
}

也能夠用預命名返回值名稱方式編寫函數代碼blog

func slice_sum(arr []int) (sum int, avg float64) {
    sum = 0
    //注意是float64類型
    avg = 0.0
    for _, elem := range arr {
        sum += elem
    }
    avg = float64(sum) / float64(len(arr))
    return
}

三、變長參數;變長參數列表內參數類型都是相同的、可變長參數只能是函數的最後一個參數遞歸

package main

import "fmt"

func sum(base int, arr ...int) int {
    sum := base
    for _, val := range arr {
        sum += val
    }
    return sum
}

func main() {
    fmt.Println(sum(100, 2, 3, 4))
}

變長參數的函數傳入切片,以下,注意切片後面的三個點ci

func main() {
    var arr = []int{2, 3, 4}
    fmt.Println(sum(100, arr...))
}

四、閉包函數:簡單理解就是在函數內,定義一個返回函數的變量,能夠經過該變量執行其定義的函數,而且在變量函數內可使用或改變外部函數的變量值資源

package main

import "fmt"

func main() {
    var base = 300
    sum := func(arr ...int) int {
        total_sum := base
        for _, val := range arr {
            total_sum += val
        }
        return total_sum
    }
    arr := []int{1, 2, 3, 4}
    fmt.Println(sum(arr...))
}

閉包示例:生成偶數序列,輸出  0,2,4string

package main

import "fmt"

func createEvenGenerator() func() uint {
    i := uint(0)
    return func() (retVal uint) {
        retVal = i
        i += 2
        return
    }
}

func main() {
    nextEven := createEvenGenerator()
    fmt.Println(nextEven())
    fmt.Println(nextEven())
    fmt.Println(nextEven())
}

五、遞歸函數,函數內重複調用本身,直到遇到出口,如階乘函數,出口就是當x=0,示例以下

package main

import "fmt"

func factorial(x uint) uint {
    if x == 0 {
        return 1
    }
    return x * factorial(x-1)
}

func main() {
    fmt.Println(factorial(5))
}

斐波拉切數列,出口是n=1和n=2

package main

import "fmt"

func fibonacci(n int) int {
    var retVal = 0
    if n == 1 {
        retVal = 1
    } else if n == 2 {
        retVal = 2
    } else {
        retVal = fibonacci(n-2) + fibonacci(n-1)
    }
    return retVal
}

func main() {
    fmt.Println(fibonacci(5))
}

六、異常處理

1)defer標註,不論在函數中的什麼位置,都是最後執行,即便中間有異常,也會最後執行defer標識的代碼,以下面例子,雖然second函數在first函數前面,可是最後執行

package main

import "fmt"

func first() {
    fmt.Println("first func run")
}

func second() {
    fmt.Println("second func run")
}

func main() {
    defer second()
    first()
}

defer用於資源釋放的案例

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
)

func main() {
    fname := "D:\\test.txt"
    f, err := os.Open(fname)
    defer f.Close()
    if err != nil {
        os.Exit(1)
    }
    bReader := bufio.NewReader(f)
    for {
        line, ok := bReader.ReadString('\n')
        if ok != nil {
            break
        }
        fmt.Println(strings.Trim(line, "\r\n"))
    }
}

2)、panic觸發異常,在defer中使用recover函數接收異常信息,recover只能在defer中才有效,由於異常拋出後,下面的代碼不會執行,defer會在最後執行

package main

import (
    "fmt"
)

func main() {
    defer func() {
        msg := recover()
        fmt.Println(msg)
    }()

    fmt.Println("I am walking and singing...")
    panic("It starts to rain cats and dogs")
}

結果圖

相關文章
相關標籤/搜索