久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Go語(yǔ)言過(guò)程式編程

 心平9bwburua3p 2017-04-14

Go 語(yǔ)言過(guò)程式編程

實(shí)驗(yàn)簡(jiǎn)介

這節(jié)講解Go語(yǔ)言的各種語(yǔ)句,,控制結(jié)構(gòu),,以及如何使用這些語(yǔ)句進(jìn)行過(guò)程式編程,課程的內(nèi)容比較多,,但是都比較重要,,在編寫(xiě)Go程序的過(guò)程中會(huì)頻繁使用到。

一,、實(shí)驗(yàn)說(shuō)明

本課程所有源代碼,,可以在XfceTerminal中通過(guò)以下方式克隆到實(shí)驗(yàn)環(huán)境:

$ git clone http://git./shiyanlou/Golang_Programming

二. Go語(yǔ)言語(yǔ)句基礎(chǔ)

之所以先學(xué)習(xí)過(guò)程式編程,是因?yàn)樵贕o語(yǔ)言中面向?qū)ο缶幊桃彩墙⒃诿嫦蜻^(guò)程的基礎(chǔ)上的,。形式上講,Go語(yǔ)言需要使用分號(hào)(;) 來(lái)作為上下文語(yǔ)句的分隔結(jié)束符,。實(shí)際上在前面的代碼中我們可以看到在Go語(yǔ)言中很少使用分號(hào),那是因?yàn)榫幾g器會(huì)自動(dòng)在需要分號(hào)的地方加上分號(hào),。但是有兩個(gè)地方必須使用分號(hào),第一個(gè)是需要在一個(gè)行中放入一條或多條語(yǔ)句時(shí),,或者是在使用原始的 for 循環(huán)時(shí)。Go語(yǔ)言也支持多重賦值,,如a, b = b, a,。另外在之前的課程中我們提到過(guò)快速聲明操作符:=,它的作用是同時(shí)在一個(gè)語(yǔ)句中聲明和賦值一個(gè)變量,。當(dāng):=操作符用于多個(gè)逗號(hào)分隔的變量時(shí),,如果該變量已經(jīng)存在,則只是簡(jiǎn)單的修改它的值,。但是當(dāng):=操作符位于作用域的起始處時(shí),,Go語(yǔ)言會(huì)創(chuàng)建一個(gè)新的變量,不管該變量之前是否存在,,如在if或者for語(yǔ)句中,。下面有一個(gè)例子可以說(shuō)明:

a, b, c := 2, 3, 5 
for a := 7; a < 8; a++ {
    fmt.Println(a)
}

以上代碼中,先使用:=聲明并賦值了三個(gè)變量,,Go會(huì)自動(dòng)推導(dǎo)出變量的類(lèi)型,。然后再for語(yǔ)句處又一次使用:=操作符聲明了變量a。需要注意的地方是,,for語(yǔ)句代表了一個(gè)新的作用域,,所以:=在這里新聲明創(chuàng)建了一個(gè)變量a,這個(gè)變量和之前的變量a是完全不同的兩個(gè)變量(內(nèi)存地址不一樣),,所以是一個(gè)影子變量,,因?yàn)楦采w了外部的同名變量。這是需要注意的一個(gè)地方,。

1. 類(lèi)型轉(zhuǎn)換

Go語(yǔ)言提供了一種在不同但相互兼容的類(lèi)型之間相互轉(zhuǎn)換的方式,,這種轉(zhuǎn)換非常有用并且是安全的。但是需要注意的是在數(shù)值之間進(jìn)行轉(zhuǎn)換可能造成其他問(wèn)題,如精度丟失或者錯(cuò)誤的結(jié)果,。以下是類(lèi)型轉(zhuǎn)換的語(yǔ)法:

  • resultOfType := Type(expression)

幾個(gè)例子:

x := int16(2345)        // 聲明一個(gè)類(lèi)型為int16的整數(shù),,其值為2345
y := int32(x)           // 將int16類(lèi)型的整數(shù)轉(zhuǎn)換為int32類(lèi)型
a := uint16(6500)       // 聲明一個(gè)類(lèi)型為uint16類(lèi)型的整數(shù)
b := int16(x)           // 轉(zhuǎn)換為int16類(lèi)型,雖然能轉(zhuǎn)換成功,,但是由于6500超過(guò)in16類(lèi)型的范圍,,會(huì)導(dǎo)致結(jié)果錯(cuò)誤,b的值為 -536

另外在Go語(yǔ)言中可以通過(guò)type關(guān)鍵字聲明類(lèi)型,,如type StringsSlice []string 將[]string(string類(lèi)型的切片)聲明為StringSlice類(lèi)型,。

2. 類(lèi)型斷言

說(shuō)到類(lèi)型斷言就需要先了解下Go語(yǔ)言中的接口,。在Go語(yǔ)言中接口是一個(gè)自定義類(lèi)型,。它聲明了一個(gè)或者多個(gè)方法。任何實(shí)現(xiàn)了這些方法的對(duì)象(類(lèi)型)都滿(mǎn)足這個(gè)接口,。接口是完全抽象的,,不能實(shí)例化。interface{}類(lèi)型表示一個(gè)空接口,,任何類(lèi)型都滿(mǎn)足空接口,。也就是說(shuō)interface{}類(lèi)型的值可以用于表示任意Go語(yǔ)言類(lèi)型的值。這里的空接口有點(diǎn)類(lèi)似于python語(yǔ)言中的object實(shí)例,。既然interface{} 可以用于表示任意類(lèi)型,,那有的時(shí)候我們需要將interface{}類(lèi)型轉(zhuǎn)換為我們需要的類(lèi)型,這個(gè)操作類(lèi)型斷言,。一般情況下只有我們希望表達(dá)式是某種特定類(lèi)型的值時(shí)才使用類(lèi)型斷言,。Go語(yǔ)言中可以使用以下語(yǔ)法:

  • resultOfType, boolean := expression.(Type) // 安全的類(lèi)型斷言
  • resultOfType := expression.(Type) // 非安全的類(lèi)型斷言,失敗時(shí)程序會(huì)產(chǎn)生異常

使用VIM創(chuàng)建源文件type_t.go,,輸入以下源文件:

package main

import (
    "fmt"
)

func main() {
    x := uint16(65000)
    y := int16(x) // 將 x轉(zhuǎn)換為int16類(lèi)型
    fmt.Printf("type and value of x is: %T and %d\n", x, x) // %T 格式化指令的作用是輸出變量的類(lèi)型
    fmt.Printf("type and value of y is: %T and %d\n", y, y)

    var i interface{} = 99 // 創(chuàng)建一個(gè)interface{}類(lèi)型,,其值為99
    var s interface{} = []string{"left", "right"}
    j := i.(int) // 我們假設(shè)i是兼容int類(lèi)型,并使用類(lèi)型斷言將其轉(zhuǎn)換為int類(lèi)型
    fmt.Printf("type and value of j is: %T and %d\n", j, j)

    if s, ok := s.([]string); ok { // 創(chuàng)建了影子變量,,if的作用域中覆蓋了外部的變量s
        fmt.Printf("%T -> %q\n", s, s)
    }
}

運(yùn)行程序:

$ go run type_t.go
type and value of x is: uint16 and 65000
type and value of y is: int16 and -536
type and value of j is: int and 99
[]string -> ["left" "right"]

三. 分支和for語(yǔ)句

Go語(yǔ)言提供了3種分支,,即ifswitch,、select, 其中select用于監(jiān)聽(tīng)channel(通道)在講解通道的時(shí)候再詳細(xì)介紹,。

1. if 分支

語(yǔ)法:

if optionalStatement1; booleanExpression1 {
    block1
} else if optionalStatement2; booleanExpression2 {
    block2
} else {
    block3
}

其中optionalStatement是可選的表達(dá)式,真正決定分支走向的是booleanExpression1的值,。

2. switch分支

Go語(yǔ)言中switch分支既可用于常用的分支就象C語(yǔ)言中的switch一樣,也可以用于類(lèi)型開(kāi)關(guān),所謂類(lèi)型開(kāi)關(guān)就是用于判斷變量屬于什么類(lèi)型,。但是需要注意的是Go語(yǔ)言的switch語(yǔ)句不會(huì)自動(dòng)貫穿,,相反,,如果想要貫穿需要添加fallthrough語(yǔ)句,。表達(dá)式開(kāi)關(guān)switch的語(yǔ)法如下:

switch optionalStatement; optionalExpression {
    case expression1: block1
    ...
    case expressionN: blockN
    default: blockD
}

下面是個(gè)例子:

switch {        // 沒(méi)有表達(dá)式,默認(rèn)為T(mén)rue值,,匹配分支中值為T(mén)rue的分支
    case value < minimum:
        return minimum
    case value > maximum:
        return maximum
    default:
        return value
}

在上面的例子中,,switch后面沒(méi)有默認(rèn)的表達(dá)式,,這個(gè)時(shí)候Go語(yǔ)言默認(rèn)其值為T(mén)rue。 在前面我們提到過(guò)類(lèi)型斷言,,如果我們知道變量的類(lèi)型就可以使用類(lèi)型斷言,,但是當(dāng)我們知道類(lèi)型可能是許多類(lèi)型中的一種時(shí)候,我們就可以使用類(lèi)型開(kāi)關(guān),。其語(yǔ)法如下:

switch optionalStatement; typeSwitchGuard {
    case type1: block1
    ...
    case typeN: blockN
    default: blockD
}

3. for循環(huán)語(yǔ)句

在前面的代碼中我們已經(jīng)遇到很多遍for語(yǔ)句了,,它可以遍歷數(shù)組,切片,,映射等類(lèi)型,,也可以用于無(wú)限循環(huán)。以下是其語(yǔ)法:

for { // 無(wú)限循環(huán)
    block
}

for booleanExpression { // while循環(huán),,在Go語(yǔ)言中沒(méi)有while關(guān)鍵字

}

for index, char := range aString { // 迭代字符串

}

for item := range aChannel { // 迭代通道

}

說(shuō)了這么多,,讓我們進(jìn)行下練習(xí),創(chuàng)建源文件switch_t.go,,輸入以下代碼:

package main

import (
    "fmt"
)

func classchecker(items ...interface{}) { // 創(chuàng)建一個(gè)函數(shù),,該函數(shù)可以接受任意多的任意類(lèi)型的參數(shù)
    for i, x := range items {
        switch x := x.(type) { // 創(chuàng)建了影子變量
        case bool:
            fmt.Printf("param #%d is a bool, value: %t\n", i, x)
        case float64:
            fmt.Printf("param #%d is a float64, value: %f\n", i, x)
        case int, int8, int16, int32, int64:
            fmt.Printf("param #%d is a int, value: %d\n", i, x)
        case uint, uint8, uint16, uint32, uint64:
            fmt.Printf("param #%d is a uint, value: %d\n", i, x)
        case nil:
            fmt.Printf("param #%d is a nil\n", i)
        case string:
            fmt.Printf("param #%d is a string, value: %s\n", i, x)
        default:
            fmt.Printf("param #%d's type is unknow\n", i)
        }
    }
}

func main() {
    classchecker(5, -17.98, "AIDEN", nil, true, complex(1, 1))

}

以上代碼中我們首先創(chuàng)建了一個(gè)接收任意數(shù)量任意類(lèi)型參數(shù)的函數(shù),然后使用for ... range aSlice的語(yǔ)法迭代了每一個(gè)在切片items中的元素,,接著使用了switch類(lèi)型開(kāi)關(guān)判斷了每一個(gè)參數(shù)的類(lèi)型,,并打印了其值和類(lèi)型。程序運(yùn)行輸出如下:

$ go run switch_t.go
param #0 is a int, value: 5
param #1 is a float64, value: -17.980000
param #2 is a string, value: AIDEN
param #3 is a nil
param #4 is a bool, value: true
param #5's type is unknow

四. 函數(shù)

Go語(yǔ)言可以很方便的自定義函數(shù),,其中有特殊的函數(shù)main函數(shù),。main函數(shù)必須出現(xiàn)在main包里,且只能出現(xiàn)一次,。當(dāng)Go程序運(yùn)行時(shí)候會(huì)自動(dòng)調(diào)用main函數(shù)開(kāi)始整個(gè)程序的執(zhí)行,。main函數(shù)不可接收任何參數(shù),也不返回任何結(jié)果,。 Go語(yǔ)言中函數(shù)的創(chuàng)建使用以下語(yǔ)法:

func functionName(optionalParameters) optionalReturnType { 
    block // func 函數(shù)名(參數(shù)列表) 單個(gè)返回值類(lèi)型
}

func functionName(optionalParameters) (optionalReturnValues) { 
    block // func 函數(shù)名(參數(shù)列表) (返回值1 類(lèi)型,,返回值2 類(lèi)型)
}

函數(shù)可以有任意多個(gè)參數(shù),,也可以有任意多個(gè)返回值,返回值可以是命名的,。具體的看以下例子:

func func1(first int, rest ...int) int { 
    return first // func1 函數(shù)可以接收任多的int類(lèi)型參數(shù),,并且返回一個(gè)int類(lèi)型的值
}

func func2(first int, second string) (int, string) { 
    return first, second // func2 接收兩個(gè),函數(shù),,并且返回一個(gè)int和string類(lèi)型的值
}

func func3(first int, second string) (a, b int) {
    a, b := 1, 2 // func3 接收兩個(gè)參數(shù),,并返回兩個(gè)int類(lèi)型的值,因?yàn)榉祷刂凳敲?,所以這里可以縮寫(xiě)
    return
}

五. 通信(channel)和并發(fā)(goroutine)語(yǔ)句

在本課程開(kāi)篇中我們就介紹過(guò)Go語(yǔ)言強(qiáng)大的并發(fā)功能,,這些功能都是建立在通信和并發(fā)語(yǔ)句上的。所謂goroutine是程序中與其他goroutine完全獨(dú)立而并發(fā)執(zhí)行的函數(shù)或者方法調(diào)用,。每一個(gè)Go程序都至少有一個(gè)goroutine,,其中main()函數(shù)所在的goroutine是主goroutinegoroutine很像輕量級(jí)的線程,,它們可以被大批量的創(chuàng)建,。那goroutine之間怎么進(jìn)行通信呢?Go語(yǔ)言中推薦的做法是使用channel(通道),。channel是一個(gè)雙向的或者單向的通信管道,可以用于兩個(gè)或者多個(gè)goroutine之間進(jìn)行通信(即接收和發(fā)送)數(shù)據(jù),。

1. 語(yǔ)法

goroutine使用以下的go語(yǔ)句進(jìn)行創(chuàng)建:

  • go function(arguments)
  • go func(parameters) { block } (arguments)

第二種方式中,,我們是創(chuàng)建了一個(gè)臨時(shí)的匿名函數(shù),并馬上在goroutine中執(zhí)行,。 當(dāng)調(diào)用用go關(guān)鍵字執(zhí)行函數(shù)時(shí),,函數(shù)會(huì)在另一個(gè)goroutine上馬上執(zhí)行,并且當(dāng)前的goroutine的執(zhí)行會(huì)從下一條語(yǔ)句馬上恢復(fù),。因此執(zhí)行一個(gè)go語(yǔ)句之后,,當(dāng)前程序中至少有兩個(gè)goroutine在運(yùn)行。

在大多數(shù)情況下,,goroutine之間需要相互協(xié)作,,最好的方式是通過(guò)channel來(lái)交換數(shù)據(jù)。使用下面語(yǔ)法創(chuàng)建channel(通道):

  • make(chan Type)
  • make(chan Type, capacity)

語(yǔ)法中的Type指明了通道能發(fā)送的數(shù)據(jù)類(lèi)型,。其中第一種語(yǔ)法中創(chuàng)建了一個(gè)同步的通道,,一次只能發(fā)送一項(xiàng)數(shù)據(jù),它會(huì)阻塞直到發(fā)送者準(zhǔn)備好發(fā)送和接收者準(zhǔn)備好接收,。如果給定了capacity也就是緩沖區(qū)容量,,在緩沖區(qū)容量未滿(mǎn)之前通道都是異步無(wú)阻塞的。通道支持的操作如下:

語(yǔ)法 含義
channel <- value 發(fā)送value到通道中,,有可能阻塞
<-channel 從通道中接收數(shù)據(jù)
x := <-channel 接收數(shù)據(jù)并賦值給x
x, ok := <-channel 功能同上,,同時(shí)檢查通道是否已關(guān)閉或者是否為空

2. select語(yǔ)句

在前面的課程中我們提到過(guò)select語(yǔ)句,用于監(jiān)聽(tīng)通道。其語(yǔ)法如下:

select {
    case sendOrReceviae1: block1
    ...
    case sendOrReceiveN: blockN
    default: blockD
}

Go語(yǔ)言會(huì)從頭至尾的判斷每一個(gè)case中的發(fā)送和接收語(yǔ)句,。如果其中任何一條語(yǔ)句可以執(zhí)行(即沒(méi)有被阻塞),,那就從那些可執(zhí)行的語(yǔ)句中任意選擇一條來(lái)使用。如果所有的通道都被阻塞,,那可能有兩種情況,。第一種,如果有default語(yǔ)句,,那就會(huì)執(zhí)行default 語(yǔ)句,,同時(shí)程序的執(zhí)行會(huì)從select語(yǔ)句恢復(fù)。第二種,,如果沒(méi)有default語(yǔ)句,,則select語(yǔ)句會(huì)一直阻塞,直到有一個(gè)通道可用

下面讓我們使用以上的相關(guān)知識(shí)進(jìn)行下練習(xí),,使用VIM創(chuàng)建源文件goroutine_channel_t.go,,輸入如下源代碼:

package main

import (
    "fmt"
    "math/rand"
)

func main() {
    channels := make([]chan bool, 6) // 創(chuàng)建一個(gè)類(lèi)型為chan bool的切片,每一項(xiàng)是能發(fā)送bool值的通道
    for i := range channels { // 通過(guò)`range`初始化切片
        channels[i] = make(chan bool)
    }

    go func() { // 在其他gouroutine中執(zhí)行匿名函數(shù)
        for {
            channels[rand.Intn(6)] <- true // rand.Intn(n int)的用途是產(chǎn)生一個(gè)不大于n的隨機(jī)數(shù)
        }                                  // 發(fā)送數(shù)據(jù)到隨機(jī)出現(xiàn)的通道
    }()

    for i := 0; i < 36; i++ {
        var x int
        select { // select 語(yǔ)句當(dāng)監(jiān)聽(tīng)到哪個(gè)分支的同道未阻塞時(shí)就跳轉(zhuǎn)到哪個(gè)分支
        case <-channels[0]:
            x = 1
        case <-channels[1]:
            x = 2
        case <-channels[2]:
            x = 3
        case <-channels[3]:
            x = 4
        case <-channels[4]:
            x = 5
        case <-channels[5]:
            x = 6
        }
        fmt.Printf("%d ", x)
    }
    fmt.Println()
}

通過(guò)以上注釋可以很清晰的看到整個(gè)代碼的執(zhí)行流程,,下面我們執(zhí)行代碼:

$ go run goroutine_channel_t.go
6 4 6 6 2 1 2 3 5 1 3 2 1 6 5 3 4 6 6 3 6 1 3 5 4 2 2 5 1 4 2 1 6 6 4 3

六. defer, panicrecover

1. defer

開(kāi)發(fā)程序時(shí),,有的時(shí)候忘記關(guān)閉打開(kāi)的文件導(dǎo)致程序執(zhí)行失敗,在python中可以很方便的使用with語(yǔ)句對(duì)這些資源進(jìn)行自動(dòng)管理,。在Go中我們可以使用defer語(yǔ)句完成這項(xiàng)任務(wù),。defer語(yǔ)句用于延遲執(zhí)行一個(gè)函數(shù)或者方法或者是當(dāng)前創(chuàng)建的匿名函數(shù),它會(huì)在外部函數(shù)或者方法返回之前但是其返回值計(jì)算之后執(zhí)行,。這樣就可能在一個(gè)延遲執(zhí)行的函數(shù)中修改函數(shù)的命名返回值,。如果一個(gè)函數(shù)中又多個(gè)defer語(yǔ)句,它們會(huì)以后進(jìn)先出的順序執(zhí)行,。defer最常用的地方就是保證一個(gè)使用完成后的文件正常關(guān)閉,。如下例子:

var file *os.File
var err error
if file, err = os.Open(filename); err != ni {
    do_something(file)
    return
}
defer file.Close()

2. panicrecover

panic類(lèi)似于其他程序中的異常,而recover 則用于恢復(fù)異常,。當(dāng)panic()函數(shù)被調(diào)用時(shí),,外圍函數(shù)或者方法的執(zhí)行會(huì)立即終止。然后任何延遲執(zhí)行的函數(shù)都會(huì)被調(diào)用,。這個(gè)過(guò)程一直在調(diào)用棧中層層發(fā)生,,最后到達(dá)main函數(shù),這個(gè)時(shí)候整個(gè)程序會(huì)終止,,最終將最初的調(diào)用棧信息輸出到stderr,。但是當(dāng)延遲執(zhí)行函數(shù)中包含recover語(yǔ)句時(shí),recover會(huì)捕捉到panic引發(fā)的異常,,并停止panic的傳播,,這個(gè)時(shí)候我們能夠以任何我們想用的方式處理panic,。

Go語(yǔ)言將錯(cuò)誤和異常兩者區(qū)分對(duì)待。錯(cuò)誤是指有可能出錯(cuò)的東西,,程序中已經(jīng)包含處理這些錯(cuò)誤的優(yōu)雅邏輯,。而異常則是指不可能發(fā)生的事情。例如,,一個(gè)永遠(yuǎn)為true的條件在實(shí)際環(huán)境中卻是false,。Go語(yǔ)言推薦使用錯(cuò)誤,而不使用異常,。通常情況下,,我們可以在recover中阻止panic的傳播,并將recover()的返回值轉(zhuǎn)換成錯(cuò)誤,。

使用VIM創(chuàng)建源文件panic_t.go, 輸入以下代碼:

package main

import (
    "fmt"
    "math"
)

func ContvertIntToInt16(x int) int16 {
    if math.MinInt16 <= x && x <= math.MaxInt16 {
        return int16(x)
    }

    panic(fmt.Sprintf("%d is out of int16 range", x)) // 手動(dòng)觸發(fā)panic
}

func main() {
    i := ContvertIntToInt16(655567)
    fmt.Printf("%d", i)
}

上面代碼中為了演示panic,,代碼中手動(dòng)促發(fā)了panic()的執(zhí)行,但是我們沒(méi)有使用recover進(jìn)行捕捉,,這會(huì)導(dǎo)致整個(gè)程序執(zhí)行失敗,,下面執(zhí)行程序驗(yàn)證下:

$ go run panic_t.go
panic: 655567 is out of int16 range

goroutine 16 [running]:
runtime.panic(0x96bc0, 0x208178180)
    /usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
main.ContvertIntToInt16(0xa00cf, 0x3ec8f)
    /Users/aiden/Project/golang/panic_t.go:13 +0x10f
main.main()
    /Users/aiden/Project/golang/panic_t.go:17 +0x26

goroutine 17 [runnable]:
runtime.MHeap_Scavenger()
    /usr/local/go/src/pkg/runtime/mheap.c:507
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445

goroutine 18 [runnable]:
bgsweep()
    /usr/local/go/src/pkg/runtime/mgc0.c:1976
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445

goroutine 19 [runnable]:
runfinq()
    /usr/local/go/src/pkg/runtime/mgc0.c:2606
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445
exit status 2

可以看到?jīng)]有捕捉panic時(shí),整個(gè)程序退出,,并且打印出了調(diào)用棧的異常信息,。 下面我們使用Go語(yǔ)言推薦的做法捕捉panic并將panic轉(zhuǎn)換為error, 創(chuàng)建源文件panic_t1.go,輸入以下代碼:

package main

import (
    "fmt"
    "math"
)

func ContvertIntToInt16(x int) int16 {
    if math.MinInt16 <= x && x <= math.MaxInt16 {
        return int16(x)
    }

    panic(fmt.Sprintf("%d is out of int16 range", x)) // 手動(dòng)觸發(fā)panic
}

func Int16FromInt(x int) (i int16, err error) {
    defer func() {   // 延遲執(zhí)行匿名函數(shù),,并使用recover捕捉了panic,,并將panic轉(zhuǎn)換為了error
        if e := recover(); e != nil {
            err = fmt.Errorf("%v", e)
        }
    }()
    i = ContvertIntToInt16(x)
    return i, nil
}

func main() {
    if _, e := Int16FromInt(655567); e != nil {

        fmt.Printf("%v\n", e)
    } else {
        fmt.Printf("no errors\n")
    }
}

以上代碼中,我們通過(guò)recover捕捉了異常,,現(xiàn)在程序?qū)惓^D(zhuǎn)換成了錯(cuò)誤,所以程序不會(huì)異常退出,,執(zhí)行驗(yàn)證如下:

$ go run panic_t1.go
655567 is out of int16 range

值得注意的地方是,,在以上代碼中的Int16FromInt(x int) (i int16, err error)函數(shù)中,我們?cè)?code>defer語(yǔ)句的匿名函數(shù)中修改了命名的返回值err,。該函數(shù)在被調(diào)用時(shí),,Go語(yǔ)言會(huì)自動(dòng)的將其返回值設(shè)置為對(duì)應(yīng)類(lèi)型的零值,在Int16FromInt函數(shù)中,,i被初始化為0,,err被初始化為nil。當(dāng)在defer語(yǔ)句中匿名函數(shù)執(zhí)行時(shí)候,,recover如果捕捉到異常,,然后修改了命名返回值err,并保持i的值(零值 )不變,。如果沒(méi)有捕捉到異常,,則程序正常返回inil,。

作業(yè)

請(qǐng)使用本節(jié)所講知識(shí)編寫(xiě)一個(gè)函數(shù),實(shí)現(xiàn)輸入一個(gè)正整數(shù)n,,輸出2-n之間的所有素?cái)?shù),。

動(dòng)手實(shí)踐是學(xué)習(xí) IT 技術(shù)最有效的方式! 開(kāi)始實(shí)驗(yàn)

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶(hù)發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買(mǎi)等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多