亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

7.Go語言基礎之函數

發布時間:2020-06-11 00:10:10 來源:網絡 閱讀:322 作者:DevOperater 欄目:編程語言

1.函數

1.1函數定義

Go語言中定義函數使用fun關鍵字,具體格式為
func 函數名(參數)(返回值){
    函數體
}

其中:
1.函數名:由字母,數字,下劃線組成。但函數名的第一個字母不能是數字。在同一個包內,函數名不能重名。
2.參數:參數由變量名和變量類型組成。
3.返回值:可以只寫返回值類型,多個返回值必須用()包裹,并用,分隔。
4.函數體:實現指定功能的代碼塊。

定義一個求兩個數和的函數:
func intSum(x int, y int) int {
    return x + y
}

函數的參數和返回值是可選的,我們也可以不傳參也沒有返回值。
func sayHello() {
    fmt.Println("Hello vita")
}

1.2函數的調用

定義了函數后,可以通過 函數名()的方式調用函數。
調用有返回值的函數時,可以不接收返回值。

package main

import "fmt"

func sayHello(){
    fmt.Println("hello vita")
}
func main() {
    sayHello()
}

結果:
hello vita

1.3參數

1.3.1類型簡寫

函數的參數中如果相鄰變量的類型相同,則可以省略類型。

package main

func intSum(x,y int)int{
    return x+y
}
func main() {
    intSum(1,2)
}

intSum函數有兩個參數,x,y的類型都是int,因此可以省略x的類型,因為y后面有類型說明。

1.3.2可變參數

可變參數即參數數量不固定。Go語言中的可變參數通過在參數后面加...來標識。
注意:可變參數通常要作為函數的最后一個參數。

package main

import "fmt"

func intSum(x ...int)int{
    fmt.Println(x)//x是一個切片
    sum:=0
    for _,value :=range x{
        sum+=value
    }
    return sum
}
func main() {
    sum1 := intSum(1,2,3,4,5)
    sum2 := intSum(1,2,3,4,5,6,7)
    sum3 := intSum(1,2,3,4,5,6,7,8,9)
    fmt.Println(sum1)
    fmt.Println(sum2)
    fmt.Println(sum3)

}

結果:
[1 2 3 4 5]
[1 2 3 4 5 6 7]
[1 2 3 4 5 6 7 8 9]
15
28
45

1.3.3固定參數搭配可變參數

可變參數放在固定參數的后面

package main

import "fmt"

func intSum(x int,y ...int)int{
    sum:=x
    for _,value :=range y{
        sum+=value
    }
    return sum
}
func main() {
    sum1 := intSum(1,2,3,4,5)
    sum2 := intSum(1,2,3,4,5,6,7)
    sum3 := intSum(1,2,3,4,5,6,7,8,9)
    fmt.Println(sum1)
    fmt.Println(sum2)
    fmt.Println(sum3)

}

結果:
15
28
45

1.4返回值

1.4.1多返回值

Go語言中支持多返回值,函數如果有多個返回值,必須使用()把所有返回值包裹起來。

package main

func calc(x,y int)(int,int){
    sum :=x+y
    sub:=x-y
    return sum,sub
}
func main() {
    calc(3,2)

}

1.4.2返回值命名

函數定義時,可以給返回值命名,并在函數體中直接使用這些變量,最后通過return關鍵字返回。
package main

func calc(x,y int)(sum int,sub int){
    sum =x+y
    sub=x-y
    return 
}
func main() {
    calc(3,2)
}

2.函數進階

2.1全局變量

全局變量是定義在函數外部的變量,他在程序整個運行周期內都有效。在函數中可以訪問到全局變量。

package main

import "fmt"

var num int64=100
func testGlobalVar(){
    fmt.Printf("num=%d\n",num)
}
func main() {
    testGlobalVar() //num=100
}

2.2局部變量

函數內定義的變量,無法在函數外使用。
func testLocalVar() {
    //定義一個函數局部變量x,僅在該函數內生效
    var x int64 = 100
    fmt.Printf("x=%d\n", x)
}

func main() {
    testLocalVar()
    fmt.Println(x) // 此時無法使用變量x
}
如果局部變量和全局變量重名,優先訪問局部變量。

package main

import "fmt"

//定義全局變量num
var num int64 = 10

func testNum() {
    num := 100
    fmt.Printf("num=%d\n", num) // 函數中優先使用局部變量
}
func main() {
    testNum() // num=100
}
語句塊中定義的變量,通常我們會在if條件判斷,for循環,switch語句上使用這種定義變量的方式。

func testLocalVar2(x, y int) {
    fmt.Println(x, y) //函數的參數也是只在本函數中生效
    if x > 0 {
        z := 100 //變量z只在if語句塊生效
        fmt.Println(z)
    }
    //fmt.Println(z)//此處無法使用變量z
}
for循環語句中定義的變量,也只在for語句塊中生效
func testLocalVar3() {
    for i := 0; i < 10; i++ {
        fmt.Println(i) //變量i只在當前for語句塊中生效
    }
    //fmt.Println(i) //此處無法使用變量i
}

2.3定義函數類型

我們可以使用type關鍵字定義一個函數類型,具體格式如下:
type calculation func(int, int) int

上面語句定義了一個calculation類型,它是一種函數類型,接收兩個int參數,返回值類型為int。

簡單的說,凡是滿足這個條件的函數都是calculation類型的函數,例如下面的add和sub是calculation類型。

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

func sub(x, y int) int {
    return x - y
}

add和sub都能賦值給calculation類型的變量。
var c calculation
c = add

2.4函數類型變量

我們可以聲明函數類型的變量并且為該變量賦值:
func main() {
    var c calculation               // 聲明一個calculation類型的變量c
    c = add                         // 把add賦值給c
    fmt.Printf("type of c:%T\n", c) // type of c:main.calculation
    fmt.Println(c(1, 2))            // 像調用add一樣調用c

    f := add                        // 將函數add賦值給變量f1
    fmt.Printf("type of f:%T\n", f) // type of f:func(int, int) int
    fmt.Println(f(10, 20))          // 像調用add一樣調用f
}

3.高階函數

高階函數分為函數作為參數和函數作為返回值。

3.1函數作為參數

package main

import "fmt"

func add(x,y int) int  {
    return x+y
}
func calc(x,y int, op func(int,int) int) int{
    return op(x,y)
}
func main()  {
    ret2 := calc(10,20,add)
    fmt.Println(ret2) //30
}

3.2函數作為返回值

package main

import (
    "errors"
    "fmt"
)

func add(x,y int) int  {
    return x+y
}
func sub(x,y int) int  {
    return x-y
}
func do(s string) (func(int, int) int,error)  {
    switch s {
    case "+":
        return add,nil
    case "-":
        return sub,nil
    default:
        err := errors.New("無法識別的操作符")
        return nil,err

    }
}
func main()  {

    addResult,err := do("+")
    fmt.Println(addResult(1,2),err)
    subResult,err := do("-")
    fmt.Println(subResult(2,1),err)
    informalResult,err := do(".")
    fmt.Println(informalResult,err)

}

結果:
3 <nil>
1 <nil>
<nil> 無法識別的操作符

Process finished with exit code 0

3.3匿名函數

函數可以作為返回值,但是在GO語言中,只能定義匿名函數。
匿名函數就是沒有函數名的函數,匿名函數的定義格式如下:

func(參數)(返回值){
    函數體
}

匿名函數因為沒有函數名,所以不能像普通函數那樣調用,所以匿名函數需要保存到某個變量或者作為立即執行函數。
匿名函數多用于實現回調函數和閉包。
package main

import "fmt"

func main()  {
    //將匿名函數保存到變量
    add := func(x,y int) {
        fmt.Println(x+y)
    }
    add(10,20) //通過變量調用匿名函數

    //自執行函數:匿名函數定義完加()直接執行
    func(x,y int){
        fmt.Println(x+y)
    }(10,20)

}

結果:
30
30

Process finished with exit code 0

3.4閉包

閉包,在Python中,是外部函數的返回值是內部函數的應用,內部函數使用了外部函數的變量,這就構成了閉包。
在Go語言中,也是同樣的。
adder函數的返回值是一個內部的匿名函數,該匿名函數引用了外部的變量x,并且x變量在f的生命周期內一直有效。
package main

import "fmt"

func adder() func(int) int  {
    var x int
    return func(y int) int {
        x += y
        return x
    }
}
func main()  {
    f := adder()
    fmt.Println(f(10))//10
    fmt.Println(f(20))//30
    fmt.Println(f(30))//60

    f1 := adder()
    fmt.Println(f1(40))//40
    fmt.Println(f1(50))//90
}

結果:
10
30
60
40
90

Process finished with exit code 0
閉包進階示例1
package main

import "fmt"

func adder2(x int) func(int) int  {
    return func(y int) int {
        x += y
        return x
    }
}
func main()  {
    f := adder2(10)
    fmt.Println(f(10))//20
    fmt.Println(f(20))//40
    fmt.Println(f(30))//70

    f1 := adder2(20)
    fmt.Println(f1(40))//60
    fmt.Println(f1(50))//110
}

結果:
20
40
70
60
110

Process finished with exit code 0
閉包進階示例2:
package main

import (
    "fmt"
    "strings"
)

func makeSuffixFunc(suffix string) func(string) string  {
    return func(name string) string {
        if !strings.HasSuffix(name,suffix){
            return name + suffix
        }
        return name
    }
}
func main()  {
    jpgFunc := makeSuffixFunc(".jpg")
    textFunc := makeSuffixFunc(".txt")
    fmt.Println(jpgFunc("test"))
    fmt.Println(textFunc("test"))
}

結果:
test.jpg
test.txt

Process finished with exit code 0
閉包進階示例3:
package main

import "fmt"

func calc(base int) (func(int) int,func(int) int)  {
    add := func(i int) int {
        base += i
        return base
    }
    sub := func(i int) int {
        base -= i
        return base
    }
    return add,sub
}
func main()  {
    f1,f2 := calc(10)
    fmt.Println(f1(1),f2(2))
    fmt.Println(f1(3),f2(4))
    fmt.Println(f1(5),f2(6))
}

結果:
11 9
12 8
13 7

Process finished with exit code 0

4.defer語句

4.1延遲調用特性

Go語言中的defer語句會將其后面跟隨的語句進行延遲處理。
在defer歸屬的函數即將返回時,將延遲處理的語句按defer定義的逆序進行執行。
即先被defer的語句最后被執行,最后被defer的語句,最先執行。
package main

import "fmt"

func main()  {
    fmt.Println("start")
    defer fmt.Println(1)
    defer fmt.Println(2)
    defer fmt.Println(3)
    fmt.Println("end")
}

結果:
start
end
3
2
1

Process finished with exit code 0
由于defer語句延遲調用的特性,所以defer語句能非常方便的處理資源釋放問題。比如:資源清理、文件關閉、解鎖及記錄時間等。

4.2defer執行時機

在Go語言的函數中,return語句在底層并不是原子操作,它分為給返回值賦值和RET指令兩步。
defer語句執行時機就在賦值操作后,RET指令執行前。具體如圖:

7.Go語言基礎之函數

4.3defer經典案例

package main

import "fmt"

// 關于defer的面試題
func f1() int {
    x := 5
    defer func() {
        x++
    }()
    return x // 1. 返回值=5  2. x++ 3. RET指令  ==> 5
}

func f2() (x int) {
    defer func() {
        x++
    }()
    return 5 // 1. (匯編)返回值=x(5) 2. x++  3.(匯編)RET ==> 6
}

func f3() (y int) {
    x := 5
    defer func() {
        x++
    }()
    return x // 1. (匯編)返回值=y(5)  2. x++  3.(匯編)RET  ==> 5
}
func f4() (x int) {
    defer func(x int) {
        x++
    }(x)
    return 5 //1. (匯編)返回值=x(5)  2. x++(函數內部的x)  3.(匯編)RET  ==> 5
}
func main() {
    fmt.Println(f1())
    fmt.Println(f2())
    fmt.Println(f3())
    fmt.Println(f4())
}

4.4defer面試題

package main

import "fmt"

func calc(index string, a, b int) int {
    ret := a + b
    fmt.Println(index, a, b, ret)
    return ret
}

func main() {
    x := 1
    y := 2
    defer calc("AA", x, calc("A", x, y))
    x = 10
    defer calc("BB", x, calc("B", x, y))
    y = 20
}

提示:defer注冊要延遲執行的函數時該函數所有的參數都需要確定其值
結果:
A 1 2 3
B 10 2 12
BB 10 12 22
AA 1 3 4

Process finished with exit code 0

5.內置函數

7.Go語言基礎之函數

5.1panic/recover

Go語言中,目前(Go1.12)是沒有異常機制的,但是使用panic/recover模式可以處理錯誤。
panic可以在任何地方引發,但是recover只有在defer調用的函數中有效。
package main

import "fmt"

func funcA()  {
    fmt.Println("func A")
}
func funcB()  {
    panic("func B")
}
func funcC()  {
    fmt.Println("func C")
}

func main() {
    funcA()
    funcB()
    funcC()
}

7.Go語言基礎之函數

在程序運行期間,funcB中引發了panic,導致程序崩潰,異常退出了。
這個時候,我們可以通過recover將程序恢復回來,繼續往后執行。
package main

import "fmt"

func funcA()  {
    fmt.Println("func A")
}
func funcB()  {
    defer func() {
        err := recover()
        if err != nil{
            fmt.Println("recover in B")
        }
    }()
    panic("func B")
}
func funcC()  {
    fmt.Println("func C")
}

func main() {
    funcA()
    funcB()
    funcC()
}

結果:
func A
recover in B
func C

Process finished with exit code 0
注意:
1.recover()必須搭配defer使用。
2.2.defer一定要在可能引發panic的語句之前定義。

6.練習題

/*
你有50枚金幣,需要分配給以下幾個人:Matthew,Sarah,Augustus,Heidi,Emilie,Peter,Giana,Adriano,Aaron,Elizabeth。
分配規則如下:
a. 名字中每包含1個'e'或'E'分1枚金幣
b. 名字中每包含1個'i'或'I'分2枚金幣
c. 名字中每包含1個'o'或'O'分3枚金幣
d: 名字中每包含1個'u'或'U'分4枚金幣
寫一個程序,計算每個用戶分到多少金幣,以及最后剩余多少金幣?
程序結構如下,請實現 ‘dispatchCoin’ 函數
*/
var (
    coins = 50
    users = []string{
        "Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth",
    }
    distribution = make(map[string]int, len(users))
)

func main() {
    left := dispatchCoin()
    fmt.Println("剩下:", left)
}
package main

import (
    "fmt"
    "strings"
)

var (
    coins = 50
    users = []string{
        "Matthew", "Sarah", "Augustus", "Heidi", "Emilie", "Peter", "Giana", "Adriano", "Aaron", "Elizabeth",
    }
    distribution = make(map[string]int, len(users))
)

func dispatchCoin()  int{
    count := 0
    for _,value := range users{

        eCount := strings.Count(strings.ToLower(value),"e")
        iCount := strings.Count(strings.ToLower(value),"i")
        oCount := strings.Count(strings.ToLower(value),"o")
        uCount := strings.Count(strings.ToLower(value),"u")
        personCount := eCount*1+iCount*2+oCount*3+uCount*4
        fmt.Printf("Pserson:%s,coins:%d\n",value,personCount)
        count += personCount

    }
    return coins-count

}
func main() {
    left := dispatchCoin()
    fmt.Println("剩下:", left)
}

結果:
Pserson:Matthew,coins:1
Pserson:Sarah,coins:0
Pserson:Augustus,coins:12
Pserson:Heidi,coins:5
Pserson:Emilie,coins:6
Pserson:Peter,coins:2
Pserson:Giana,coins:2
Pserson:Adriano,coins:5
Pserson:Aaron,coins:3
Pserson:Elizabeth,coins:4
剩下: 10

Process finished with exit code 0
向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

黄浦区| 广南县| 新乐市| 延长县| 东源县| 万州区| 双峰县| 宜君县| 班戈县| 尉犁县| 天祝| 综艺| 盐边县| 鄂州市| 侯马市| 科尔| 南靖县| 霸州市| 清水县| 吉首市| 红桥区| 金坛市| 筠连县| 岳普湖县| 鹰潭市| 横峰县| 桂东县| 天等县| 久治县| 碌曲县| 礼泉县| 商洛市| 垫江县| 永善县| 徐闻县| 从化市| 仙桃市| 漳平市| 集安市| 丘北县| 东台市|