這小節(jié)我們要介紹Go里面的流程控制以及函數(shù)操作。
流程控制
流程控制在編程語(yǔ)言中是最偉大的發(fā)明了,因?yàn)橛辛怂?,你可以通過很簡(jiǎn)單的流程描述來(lái)表達(dá)很復(fù)雜的邏輯。Go中流程控制分三大類:條件判斷,循環(huán)控制和無(wú)條件跳轉(zhuǎn)。
if
if也許是各種編程語(yǔ)言中最常見的了,它的語(yǔ)法概括起來(lái)就是:如果滿足條件就做某事,否則做另一件事。
Go里面if條件判斷語(yǔ)句中不需要括號(hào),如下代碼所示:
復(fù)制代碼 代碼如下:
if x > 10 {
fmt.Println("x is greater than 10")
} else {
fmt.Println("x is less than 10")
}
Go的if還有一個(gè)強(qiáng)大的地方就是條件判斷語(yǔ)句里面允許聲明一個(gè)變量,這個(gè)變量的作用域只能在該條件邏輯塊內(nèi),其他地方就不起作用了,如下所示:
復(fù)制代碼 代碼如下:
// 計(jì)算獲取值x,然后根據(jù)x返回的大小,判斷是否大于10。
if x := computedValue(); x > 10 {
fmt.Println("x is greater than 10")
} else {
fmt.Println("x is less than 10")
}
//這個(gè)地方如果這樣調(diào)用就編譯出錯(cuò)了,因?yàn)閤是條件里面的變量
fmt.Println(x)
多個(gè)條件的時(shí)候如下所示:
復(fù)制代碼 代碼如下:
if integer == 3 {
fmt.Println("The integer is equal to 3")
} else if integer 3 {
fmt.Println("The integer is less than 3")
} else {
fmt.Println("The integer is greater than 3")
}
goto
Go有g(shù)oto語(yǔ)句——請(qǐng)明智地使用它。用goto跳轉(zhuǎn)到必須在當(dāng)前函數(shù)內(nèi)定義的標(biāo)簽。例如假設(shè)這樣一個(gè)循環(huán):
復(fù)制代碼 代碼如下:
func myFunc() {
i := 0
Here: //這行的第一個(gè)詞,以冒號(hào)結(jié)束作為標(biāo)簽
println(i)
i++
goto Here //跳轉(zhuǎn)到Here去
}
標(biāo)簽名是大小寫敏感的。
for
Go里面最強(qiáng)大的一個(gè)控制邏輯就是for,它即可以用來(lái)循環(huán)讀取數(shù)據(jù),又可以當(dāng)作while來(lái)控制邏輯,還能迭代操作。它的語(yǔ)法如下:
復(fù)制代碼 代碼如下:
for expression1; expression2; expression3 {
//...
}
expression1、expression2和expression3都是表達(dá)式,其中expression1和expression3是變量聲明或者函數(shù)調(diào)用返回值之類的,expression2是用來(lái)?xiàng)l件判斷,expression1在循環(huán)開始之前調(diào)用,expression3在每輪循環(huán)結(jié)束之時(shí)調(diào)用。
一個(gè)例子比上面講那么多更有用,那么我們看看下面的例子吧:
復(fù)制代碼 代碼如下:
package main
import "fmt"
func main(){
sum := 0;
for index:=0; index 10 ; index++ {
sum += index
}
fmt.Println("sum is equal to ", sum)
}
// 輸出:sum is equal to 45
有些時(shí)候需要進(jìn)行多個(gè)賦值操作,由于Go里面沒有,操作符,那么可以使用平行賦值i, j = i+1, j-1
有些時(shí)候如果我們忽略expression1和expression3:
復(fù)制代碼 代碼如下:
sum := 1
for ; sum 1000; {
sum += sum
}
其中;也可以省略,那么就變成如下的代碼了,是不是似曾相識(shí)?對(duì),這就是while的功能。
復(fù)制代碼 代碼如下:
sum := 1
for sum 1000 {
sum += sum
}
在循環(huán)里面有兩個(gè)關(guān)鍵操作break和continue ,break操作是跳出當(dāng)前循環(huán),continue是跳過本次循環(huán)。當(dāng)嵌套過深的時(shí)候,break可以配合標(biāo)簽使用,即跳轉(zhuǎn)至標(biāo)簽所指定的位置,詳細(xì)參考如下例子:
復(fù)制代碼 代碼如下:
for index := 10; index>0; index-- {
if index == 5{
break // 或者continue
}
fmt.Println(index)
}
// break打印出來(lái)10、9、8、7、6
// continue打印出來(lái)10、9、8、7、6、4、3、2、1
break和continue還可以跟著標(biāo)號(hào),用來(lái)跳到多重循環(huán)中的外層循環(huán)
for配合range可以用于讀取slice和map的數(shù)據(jù):
復(fù)制代碼 代碼如下:
for k,v:=range map {
fmt.Println("map's key:",k)
fmt.Println("map's val:",v)
}
switch
有些時(shí)候你需要寫很多的if-else來(lái)實(shí)現(xiàn)一些邏輯處理,這個(gè)時(shí)候代碼看上去就很丑很冗長(zhǎng),而且也不易于以后的維護(hù),這個(gè)時(shí)候switch就能很好的解決這個(gè)問題。它的語(yǔ)法如下
復(fù)制代碼 代碼如下:
switch sExpr {
case expr1:
some instructions
case expr2:
some other instructions
case expr3:
some other instructions
default:
other code
}
sExpr和expr1、expr2、expr3的類型必須一致。Go的switch非常靈活,表達(dá)式不必是常量或整數(shù),執(zhí)行的過程從上至下,直到找到匹配項(xiàng);而如果switch沒有表達(dá)式,它會(huì)匹配true。
復(fù)制代碼 代碼如下:
i := 10
switch i {
case 1:
fmt.Println("i is equal to 1")
case 2, 3, 4:
fmt.Println("i is equal to 2, 3 or 4")
case 10:
fmt.Println("i is equal to 10")
default:
fmt.Println("All I know is that i is an integer")
}
在第5行中,我們把很多值聚合在了一個(gè)case里面,同時(shí),Go里面switch默認(rèn)相當(dāng)于每個(gè)case最后帶有break,匹配成功后不會(huì)自動(dòng)向下執(zhí)行其他case,而是跳出整個(gè)switch, 但是可以使用fallthrough強(qiáng)制執(zhí)行后面的case代碼。
復(fù)制代碼 代碼如下:
integer := 6
switch integer {
case 4:
fmt.Println("The integer was = 4")
fallthrough
case 5:
fmt.Println("The integer was = 5")
fallthrough
case 6:
fmt.Println("The integer was = 6")
fallthrough
case 7:
fmt.Println("The integer was = 7")
fallthrough
case 8:
fmt.Println("The integer was = 8")
fallthrough
default:
fmt.Println("default case")
}
上面的程序?qū)⑤敵?br />
復(fù)制代碼 代碼如下:
The integer was = 6
The integer was = 7
The integer was = 8
default case
函數(shù)
函數(shù)是Go里面的核心設(shè)計(jì),它通過關(guān)鍵字func來(lái)聲明,它的格式如下:
復(fù)制代碼 代碼如下:
func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) {
//這里是處理邏輯代碼
//返回多個(gè)值
return value1, value2
}
上面的代碼我們看出
1.關(guān)鍵字func用來(lái)聲明一個(gè)函數(shù)funcName
2.函數(shù)可以有一個(gè)或者多個(gè)參數(shù),每個(gè)參數(shù)后面帶有類型,通過,分隔
3.函數(shù)可以返回多個(gè)值
4.上面返回值聲明了兩個(gè)變量output1和output2,如果你不想聲明也可以,直接就兩個(gè)類型
5.如果只有一個(gè)返回值且不聲明返回值變量,那么你可以省略 包括返回值 的括號(hào)
6.如果沒有返回值,那么就直接省略最后的返回信息
7.如果有返回值, 那么必須在函數(shù)的外層添加return語(yǔ)句
下面我們來(lái)看一個(gè)實(shí)際應(yīng)用函數(shù)的例子(用來(lái)計(jì)算Max值)
復(fù)制代碼 代碼如下:
package main
import "fmt"
// 返回a、b中最大值.
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
x := 3
y := 4
z := 5
max_xy := max(x, y) //調(diào)用函數(shù)max(x, y)
max_xz := max(x, z) //調(diào)用函數(shù)max(x, z)
fmt.Printf("max(%d, %d) = %d\n", x, y, max_xy)
fmt.Printf("max(%d, %d) = %d\n", x, z, max_xz)
fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) // 也可在這直接調(diào)用它
}
上面這個(gè)里面我們可以看到max函數(shù)有兩個(gè)參數(shù),它們的類型都是int,那么第一個(gè)變量的類型可以省略(即 a,b int,而非 a int, b int),默認(rèn)為離它最近的類型,同理多于2個(gè)同類型的變量或者返回值。同時(shí)我們注意到它的返回值就是一個(gè)類型,這個(gè)就是省略寫法。
多個(gè)返回值
Go語(yǔ)言比C更先進(jìn)的特性,其中一點(diǎn)就是函數(shù)能夠返回多個(gè)值。
我們直接上代碼看例子:
復(fù)制代碼 代碼如下:
package main
import "fmt"
//返回 A+B 和 A*B
func SumAndProduct(A, B int) (int, int) {
return A+B, A*B
}
func main() {
x := 3
y := 4
xPLUSy, xTIMESy := SumAndProduct(x, y)
fmt.Printf("%d + %d = %d\n", x, y, xPLUSy)
fmt.Printf("%d * %d = %d\n", x, y, xTIMESy)
}
上面的例子我們可以看到直接返回了兩個(gè)參數(shù),當(dāng)然我們也可以命名返回參數(shù)的變量,這個(gè)例子里面只是用了兩個(gè)類型,我們也可以改成如下這樣的定義,然后返回的時(shí)候不用帶上變量名,因?yàn)橹苯釉诤瘮?shù)里面初始化了。但如果你的函數(shù)是導(dǎo)出的(首字母大寫),官方建議:最好命名返回值,因?yàn)椴幻祷刂?,雖然使得代碼更加簡(jiǎn)潔了,但是會(huì)造成生成的文檔可讀性差。
復(fù)制代碼 代碼如下:
func SumAndProduct(A, B int) (add int, Multiplied int) {
add = A+B
Multiplied = A*B
return
}
變參
Go函數(shù)支持變參。接受變參的函數(shù)是有著不定數(shù)量的參數(shù)的。為了做到這點(diǎn),首先需要定義函數(shù)使其接受變參:
復(fù)制代碼 代碼如下:
func myfunc(arg ...int) {}
arg ...int告訴Go這個(gè)函數(shù)接受不定數(shù)量的參數(shù)。注意,這些參數(shù)的類型全部是int。在函數(shù)體中,變量arg是一個(gè)int的slice:
復(fù)制代碼 代碼如下:
for _, n := range arg {
fmt.Printf("And the number is: %d\n", n)
}
傳值與傳指針
當(dāng)我們傳一個(gè)參數(shù)值到被調(diào)用函數(shù)里面時(shí),實(shí)際上是傳了這個(gè)值的一份copy,當(dāng)在被調(diào)用函數(shù)中修改參數(shù)值的時(shí)候,調(diào)用函數(shù)中相應(yīng)實(shí)參不會(huì)發(fā)生任何變化,因?yàn)閿?shù)值變化只作用在copy上。
為了驗(yàn)證我們上面的說(shuō)法,我們來(lái)看一個(gè)例子
復(fù)制代碼 代碼如下:
package main
import "fmt"
//簡(jiǎn)單的一個(gè)函數(shù),實(shí)現(xiàn)了參數(shù)+1的操作
func add1(a int) int {
a = a+1 // 我們改變了a的值
return a //返回一個(gè)新值
}
func main() {
x := 3
fmt.Println("x = ", x) // 應(yīng)該輸出 "x = 3"
x1 := add1(x) //調(diào)用add1(x)
fmt.Println("x+1 = ", x1) // 應(yīng)該輸出"x+1 = 4"
fmt.Println("x = ", x) // 應(yīng)該輸出"x = 3"
}
看到了嗎?雖然我們調(diào)用了add1函數(shù),并且在add1中執(zhí)行a = a+1操作,但是上面例子中x變量的值沒有發(fā)生變化
理由很簡(jiǎn)單:因?yàn)楫?dāng)我們調(diào)用add1的時(shí)候,add1接收的參數(shù)其實(shí)是x的copy,而不是x本身。
那你也許會(huì)問了,如果真的需要傳這個(gè)x本身,該怎么辦呢?
這就牽扯到了所謂的指針。我們知道,變量在內(nèi)存中是存放于一定地址上的,修改變量實(shí)際是修改變量地址處的內(nèi)存。只有add1函數(shù)知道x變量所在的地址,才能修改x變量的值。所以我們需要將x所在地址x傳入函數(shù),并將函數(shù)的參數(shù)的類型由int改為*int,即改為指針類型,才能在函數(shù)中修改x變量的值。此時(shí)參數(shù)仍然是按copy傳遞的,只是copy的是一個(gè)指針。請(qǐng)看下面的例子:
復(fù)制代碼 代碼如下:
package main
import "fmt"
//簡(jiǎn)單的一個(gè)函數(shù),實(shí)現(xiàn)了參數(shù)+1的操作
func add1(a *int) int { // 請(qǐng)注意,
*a = *a+1 // 修改了a的值
return *a // 返回新值
}
func main() {
x := 3
fmt.Println("x = ", x) // 應(yīng)該輸出 "x = 3"
x1 := add1(x) // 調(diào)用 add1(x) 傳x的地址
fmt.Println("x+1 = ", x1) // 應(yīng)該輸出 "x+1 = 4"
fmt.Println("x = ", x) // 應(yīng)該輸出 "x = 4"
}
這樣,我們就達(dá)到了修改x的目的。那么到底傳指針有什么好處呢?
1.傳指針使得多個(gè)函數(shù)能操作同一個(gè)對(duì)象。
2.傳指針比較輕量級(jí) (8bytes),只是傳內(nèi)存地址,我們可以用指針傳遞體積大的結(jié)構(gòu)體。如果用參數(shù)值傳遞的話, 在每次copy上面就會(huì)花費(fèi)相對(duì)較多的系統(tǒng)開銷(內(nèi)存和時(shí)間)。所以當(dāng)你要傳遞大的結(jié)構(gòu)體的時(shí)候,用指針是一個(gè)明智的選擇。
3.Go語(yǔ)言中string,slice,map這三種類型的實(shí)現(xiàn)機(jī)制類似指針,所以可以直接傳遞,而不用取地址后傳遞指針。(注:若函數(shù)需改變slice的長(zhǎng)度,則仍需要取地址傳遞指針)
defer
Go語(yǔ)言中有種不錯(cuò)的設(shè)計(jì),即延遲(defer)語(yǔ)句,你可以在函數(shù)中添加多個(gè)defer語(yǔ)句。當(dāng)函數(shù)執(zhí)行到最后時(shí),這些defer語(yǔ)句會(huì)按照逆序執(zhí)行,最后該函數(shù)返回。特別是當(dāng)你在進(jìn)行一些打開資源的操作時(shí),遇到錯(cuò)誤需要提前返回,在返回前你需要關(guān)閉相應(yīng)的資源,不然很容易造成資源泄露等問題。如下代碼所示,我們一般寫打開一個(gè)資源是這樣操作的:
復(fù)制代碼 代碼如下:
func ReadWrite() bool {
file.Open("file")
// 做一些工作
if failureX {
file.Close()
return false
}
if failureY {
file.Close()
return false
}
file.Close()
return true
}
我們看到上面有很多重復(fù)的代碼,Go的defer有效解決了這個(gè)問題。使用它后,不但代碼量減少了很多,而且程序變得更優(yōu)雅。在defer后指定的函數(shù)會(huì)在函數(shù)退出前調(diào)用。
復(fù)制代碼 代碼如下:
func ReadWrite() bool {
file.Open("file")
defer file.Close()
if failureX {
return false
}
if failureY {
return false
}
return true
}
如果有很多調(diào)用defer,那么defer是采用后進(jìn)先出模式,所以如下代碼會(huì)輸出4 3 2 1 0
復(fù)制代碼 代碼如下:
for i := 0; i 5; i++ {
defer fmt.Printf("%d ", i)
}
函數(shù)作為值、類型
在Go中函數(shù)也是一種變量,我們可以通過type來(lái)定義它,它的類型就是所有擁有相同的參數(shù),相同的返回值的一種類型
復(fù)制代碼 代碼如下:
type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...])
函數(shù)作為類型到底有什么好處呢?那就是可以把這個(gè)類型的函數(shù)當(dāng)做值來(lái)傳遞,請(qǐng)看下面的例子
復(fù)制代碼 代碼如下:
package main
import "fmt"
type testInt func(int) bool // 聲明了一個(gè)函數(shù)類型
func isOdd(integer int) bool {
if integer%2 == 0 {
return false
}
return true
}
func isEven(integer int) bool {
if integer%2 == 0 {
return true
}
return false
}
// 聲明的函數(shù)類型在這個(gè)地方當(dāng)做了一個(gè)參數(shù)
func filter(slice []int, f testInt) []int {
var result []int
for _, value := range slice {
if f(value) {
result = append(result, value)
}
}
return result
}
func main(){
slice := []int {1, 2, 3, 4, 5, 7}
fmt.Println("slice = ", slice)
odd := filter(slice, isOdd) // 函數(shù)當(dāng)做值來(lái)傳遞了
fmt.Println("Odd elements of slice are: ", odd)
even := filter(slice, isEven) // 函數(shù)當(dāng)做值來(lái)傳遞了
fmt.Println("Even elements of slice are: ", even)
}
函數(shù)當(dāng)做值和類型在我們寫一些通用接口的時(shí)候非常有用,通過上面例子我們看到testInt這個(gè)類型是一個(gè)函數(shù)類型,然后兩個(gè)filter函數(shù)的參數(shù)和返回值與testInt類型是一樣的,但是我們可以實(shí)現(xiàn)很多種的邏輯,這樣使得我們的程序變得非常的靈活。
Panic和Recover
Go沒有像Java那樣的異常機(jī)制,它不能拋出異常,而是使用了panic和recover機(jī)制。一定要記住,你應(yīng)當(dāng)把它作為最后的手段來(lái)使用,也就是說(shuō),你的代碼中應(yīng)當(dāng)沒有,或者很少有panic的東西。這是個(gè)強(qiáng)大的工具,請(qǐng)明智地使用它。那么,我們應(yīng)該如何使用它呢?
Panic
是一個(gè)內(nèi)建函數(shù),可以中斷原有的控制流程,進(jìn)入一個(gè)令人恐慌的流程中。當(dāng)函數(shù)F調(diào)用panic,函數(shù)F的執(zhí)行被中斷,但是F中的延遲函數(shù)會(huì)正常執(zhí)行,然后F返回到調(diào)用它的地方。在調(diào)用的地方,F(xiàn)的行為就像調(diào)用了panic。這一過程繼續(xù)向上,直到發(fā)生panic的goroutine中所有調(diào)用的函數(shù)返回,此時(shí)程序退出??只趴梢灾苯诱{(diào)用panic產(chǎn)生。也可以由運(yùn)行時(shí)錯(cuò)誤產(chǎn)生,例如訪問越界的數(shù)組。
Recover
是一個(gè)內(nèi)建的函數(shù),可以讓進(jìn)入令人恐慌的流程中的goroutine恢復(fù)過來(lái)。recover僅在延遲函數(shù)中有效。在正常的執(zhí)行過程中,調(diào)用recover會(huì)返回nil,并且沒有其它任何效果。如果當(dāng)前的goroutine陷入恐慌,調(diào)用recover可以捕獲到panic的輸入值,并且恢復(fù)正常的執(zhí)行。
下面這個(gè)函數(shù)演示了如何在過程中使用panic
復(fù)制代碼 代碼如下:
var user = os.Getenv("USER")
func init() {
if user == "" {
panic("no value for $USER")
}
}
下面這個(gè)函數(shù)檢查作為其參數(shù)的函數(shù)在執(zhí)行時(shí)是否會(huì)產(chǎn)生panic:
復(fù)制代碼 代碼如下:
func throwsPanic(f func()) (b bool) {
defer func() {
if x := recover(); x != nil {
b = true
}
}()
f() //執(zhí)行函數(shù)f,如果f中出現(xiàn)了panic,那么就可以恢復(fù)回來(lái)
return
}
main函數(shù)和init函數(shù)
Go里面有兩個(gè)保留的函數(shù):init函數(shù)(能夠應(yīng)用于所有的package)和main函數(shù)(只能應(yīng)用于package main)。這兩個(gè)函數(shù)在定義時(shí)不能有任何的參數(shù)和返回值。雖然一個(gè)package里面可以寫任意多個(gè)init函數(shù),但這無(wú)論是對(duì)于可讀性還是以后的可維護(hù)性來(lái)說(shuō),我們都強(qiáng)烈建議用戶在一個(gè)package中每個(gè)文件只寫一個(gè)init函數(shù)。
Go程序會(huì)自動(dòng)調(diào)用init()和main(),所以你不需要在任何地方調(diào)用這兩個(gè)函數(shù)。每個(gè)package中的init函數(shù)都是可選的,但package main就必須包含一個(gè)main函數(shù)。
程序的初始化和執(zhí)行都起始于main包。如果main包還導(dǎo)入了其它的包,那么就會(huì)在編譯時(shí)將它們依次導(dǎo)入。有時(shí)一個(gè)包會(huì)被多個(gè)包同時(shí)導(dǎo)入,那么它只會(huì)被導(dǎo)入一次(例如很多包可能都會(huì)用到fmt包,但它只會(huì)被導(dǎo)入一次,因?yàn)闆]有必要導(dǎo)入多次)。當(dāng)一個(gè)包被導(dǎo)入時(shí),如果該包還導(dǎo)入了其它的包,那么會(huì)先將其它包導(dǎo)入進(jìn)來(lái),然后再對(duì)這些包中的包級(jí)常量和變量進(jìn)行初始化,接著執(zhí)行init函數(shù)(如果有的話),依次類推。等所有被導(dǎo)入的包都加載完畢了,就會(huì)開始對(duì)main包中的包級(jí)常量和變量進(jìn)行初始化,然后執(zhí)行main包中的init函數(shù)(如果存在的話),最后執(zhí)行main函數(shù)。下圖詳細(xì)地解釋了整個(gè)執(zhí)行過程:
![](http://img.jbzj.com/file_images/article/201410/20141028114758728.png?201492811487)
圖2.6 main函數(shù)引入包初始化流程圖
import
我們?cè)趯慓o代碼的時(shí)候經(jīng)常用到import這個(gè)命令用來(lái)導(dǎo)入包文件,而我們經(jīng)??吹降姆绞絽⒖既缦拢?br />
復(fù)制代碼 代碼如下:
import(
"fmt"
)
然后我們代碼里面可以通過如下的方式調(diào)用
復(fù)制代碼 代碼如下:
fmt.Println("hello world")
上面這個(gè)fmt是Go語(yǔ)言的標(biāo)準(zhǔn)庫(kù),其實(shí)是去GOROOT環(huán)境變量指定目錄下去加載該模塊,當(dāng)然Go的import還支持如下兩種方式來(lái)加載自己寫的模塊:
1.相對(duì)路徑
復(fù)制代碼 代碼如下:
import “./model” //當(dāng)前文件同一目錄的model目錄,但是不建議這種方式來(lái)import
2.絕對(duì)路徑
復(fù)制代碼 代碼如下:
import “shorturl/model” //加載gopath/src/shorturl/model模塊
上面展示了一些import常用的幾種方式,但是還有一些特殊的import,讓很多新手很費(fèi)解,下面我們來(lái)一一講解一下到底是怎么一回事
點(diǎn)操作
我們有時(shí)候會(huì)看到如下的方式導(dǎo)入包
復(fù)制代碼 代碼如下:
import(
. "fmt"
)
這個(gè)點(diǎn)操作的含義就是這個(gè)包導(dǎo)入之后在你調(diào)用這個(gè)包的函數(shù)時(shí),你可以省略前綴的包名,也就是前面你調(diào)用的fmt.Println("hello world")可以省略的寫成Println("hello world")
別名操作
別名操作顧名思義我們可以把包命名成另一個(gè)我們用起來(lái)容易記憶的名字
復(fù)制代碼 代碼如下:
import(
f "fmt"
)
別名操作的話調(diào)用包函數(shù)時(shí)前綴變成了我們的前綴,即f.Println("hello world")。
_操作
這個(gè)操作經(jīng)常是讓很多人費(fèi)解的一個(gè)操作符,請(qǐng)看下面這個(gè)import
復(fù)制代碼 代碼如下:
import (
"database/sql"
_ "github.com/ziutek/mymysql/godrv"
)
_操作其實(shí)是引入該包,而不直接使用包里面的函數(shù),而是調(diào)用了該包里面的init函數(shù)。
您可能感興趣的文章:- GO語(yǔ)言延遲函數(shù)defer用法分析
- GO語(yǔ)言Defer用法實(shí)例分析
- Go語(yǔ)言中append函數(shù)用法分析
- Go語(yǔ)言截取字符串函數(shù)用法
- Go語(yǔ)言中普通函數(shù)與方法的區(qū)別分析
- Go語(yǔ)言中函數(shù)的參數(shù)傳遞與調(diào)用的基本方法
- Go語(yǔ)言常見哈希函數(shù)的使用
- go語(yǔ)言簡(jiǎn)單的處理http請(qǐng)求的函數(shù)實(shí)例
- Go語(yǔ)言的os包中常用函數(shù)初步歸納
- 總結(jié)Go語(yǔ)言中defer的使用和注意要點(diǎn)