聲明:
func funcName(input1 type1, intput2 type2) (output1 type1, output2 type2) {
………………
//能夠有多個返回值
return val1, val2
}
說明:golang中經過func來聲明一個函數,函數能夠有一個或者多個參數,每一個參數後面帶類型,經過,分隔;函數能夠返回多個值,返回的個數要於聲明時定義的返回個數相同,聲明時能夠不寫返回的變量名,而直接使用類型(若是隻有一個返回值且不聲明返回值變量,那麼能夠省略返回值的括號,若是沒有返回值,那麼就直接省略最後的返回信息定義)
例:
func SumAndProduct(a, b int) (int, int) {
return a+b, a*b
}
func SumAndProduct(a, b int) (add int, Multiplied int) {
add = a + b;
Multiplied = a * b;
return
}
這兩段代碼都是正確的,當定義函數時命令了返回參數變量時,能夠直接返回而不用帶變量名。注意:若是命令的返回參數跟函數代碼塊中的變量同名,他會被隱藏,此時需顯示return返回結果;還有就是顯式return會先修改命名返回值,而後再執行defer延遲語句。
參數之變參:
golang支持變參,變量中全部參數的類別必須是同一種,且必須是最後一個形參。函數內獲取變參爲一個slice。函數聲明爲:func FuncName(args ...int) { } args ...int 告訴go這個函數接受變參參數。 使用如sum(x[2:6]...)
參數的使用:
函數的參數都是進行拷貝賦值的,只是分爲copy值和copy指針,傳遞指針使用「&變量名」,在函數聲明中使用「變量名 *類型」,如:
func Add(num *int) int {
*num = *num + 100
return *num
}
使用,nmber := 100 Add(&number) fmt.Println(number)
go語言中,string,slice,map這三種類型實現的機制相似指針,因此能夠直接傳遞,而不用取地址後傳遞指針。若函數須要改變slice長度,則仍需去地址傳遞指針。
匿名函數和閉包:
閉包和匿名函數常常一塊兒使用,可使用閉包來訪問函數中的局部變量(被訪問操做的變量爲指針指向關係,操做的是同一個局部變量)如: golang
func closure(x int) (func(), func(int)) {
fmt.Printf("初始值x爲:%d,內存地址:%p\n", x, &x)
f1 := func() {
x = x + 5
fmt.Printf("x+5:%d,內存地址:%p\n", x, &x)
}
f2 := func(y int) {
x = x + y
fmt.Printf("x+%d:%d,內存地址:%p\n", y, x, &x)
}
return f1, f2
}
func main() {
func1, func2 := closure(10)
func1()
func2(10)
func2(20)
}
輸出結果爲:
初始值x爲:10,內存地址:0xc080000038
x+5:15,內存地址:0xc080000038
x+10:25,內存地址:0xc080000038
x+20:45,內存地址:0xc080000038
延遲語句defer:
golang中,有種語句defer語句,在函數執行到最後時,這些defer語句纔會按照定義的逆序執行,等這些defer語句都執行完後,函數再返回。全部能夠利用這個來進行資源安全關閉,解加鎖,記錄執行狀況等。defer是採用先進後出的模式的,如棧。注意:定義的延遲操做,若有提供參數會發生值的拷貝,儘管這些函數在退出時才執行,但所使用的參數是在定義時的拷貝,拷貝的原則和變量的賦值原則一個,slice,map,channel是指針拷貝。
函數做爲值、類型:
在golang中函數也是一種變量,可使用type來定義它,它的類型就是全部擁有相同的參數,相同的返回值的一種類型
type TypeName func(input1 type1, input2 type2) (output1 type1, output2 type2)
函數做爲類型就能夠把這個類型的函數看成值來傳遞,如面向對象中的組合方法,如:
//聲明一個函數類型
type handlerNum func(int) int
func Add(num int) int {
sum := 0
for i := 1; i <= num; i++ {
sum += i
}
return sum
}
func
Product(num int) int {
return (1 + 100) * 100 / 2
}
func Gauss (num int, h handlerNum) {
return h(num)
}
Gauss(100, Add) 和 Gauss(100, Product)這兩個函數獲得的結果都是同樣的。
Panic和Recover:
golang中沒有異常機制,它不能拋出異常,而是使用了panic和recover機制,panic它會中斷原有的控制流程,並進入一個恐慌流程中,當函數調用panic,原有函數的執行會被中斷,但原有函數中的defer函數會正常的執行,而後函數返回到調用它的地方
。在調用的地方,函數的行爲就像調用了panic,這一過程繼續向上,直到發生panic的gorutine中全部調用的函數返回,此時程序退出。恐慌能夠直接調用panic產生,也能夠有運行時錯誤產生。recover可讓進入恐慌流程中的goroutine恢復過來,recover僅在defer延遲函數內部中有效,在正常的執行過程當中,調用recover會返回nil,而且沒有其餘任務效果,若是當前的goroutine陷入恐慌,調用recover能夠捕獲panic的輸入值,並恢復正常的程序執行。
main函數和init函數:
golang中的兩個保留函數,init函數可以應用於全部的package,main函數只能應用於main包中,兩個函數在定義時不能有任何的參數和返回值,一個package能夠有多個init函數,但爲了可讀性強烈建議用戶在一個package中每一個文件只寫一個init函數,而main函數有且一個存在main包中。
程序初始化和執行都起始於main包,若是main包還導入其餘的包,那麼會在編譯時將他們依次導入,當一個包被多個包同時導入,那麼它只會導入一次,當導入的包還引入了其餘的包,那麼還會先將其餘包導入進來,而後再對這些包的包級常量和變量進行初始化,接着執行init函數,依次類推,等全部的被導入的包都加載完畢並初始化完畢後,就會開始對main包的包級常量和變量進行初始化,而後執行main包中的init函數,最後執行main函數。const->var->init->main的過程。
內置函數:
close:關閉channel。
len:獲取string,array,slice的長度,map key的數量和buffer channel可用數據數量。
cap:獲取array長度、slice容量,以及buffer channel的最大緩存容量。
new:對指定類型分配初始化過的內存空間(零值填充),並返回指針。
make:僅用於slice、map、channel指針賦值類型,除了初始化內存,還負責設置相關屬性。
append:向slice尾部追加一個或多個元素。
copy:在不一樣的slice間複製數據,並返回複製的個數,如:copy(s1, s2[2:7])
panic/recover:錯誤處理
complex/real/imag:複數處理。