定義
函數包含函數名,行參列表,函數體和返回值列表,使用func進行聲明,函數無參數或返回值時則形參列表和返回值列表省略
func name(parameters) returns {
}
形參列表需要描述參數名及參數類型,所有形參爲函數塊局部變量,返回值需要描述返回值類型
舉例
1.無參 無返回值
func sayHello() {
fmt.Println("hello world")
}
2.有參 無返回值
func say(name string, name2 string) {
fmt.Println("hello world:", name, name2)
}
3.有參 有返回值
func add (a int, b int) int {
return a + b
}
func main() {
say("abc", "vbn")
num = add(1, 2)
fmt.println(num)
}
調用
函數通過函數名(實參列表)在調用過程中實參的每個數據會賦值給形參中的每個變量,因 此實參列表類型和數量需要函數定義的形參一一對應。
舉例
1.調用無參無返回值函數
sayHello()
2.調用有參無返回值類型
say("kk", "abc")
3.調用有參有返回值函數
n1, n2 := 1, 2
fmt.Printf("%d + %d = %d\n", n1, n2, add(n1+n2))
參數
1.參數類型合併
// 連續多個變量類型相同
// 保留最後一個元素類型,前面的類型都可以省略
// func add (a int, b int) int
func add (a, b int) int {
return a + b
}
func test(p1, p2 int, p3, p4 string) {
fmt.Println("%T, %T, %T, %T", p1, p2, p3, p4)
}
2.可變參數類型
// 1.可變參數,在一個方法中只能有一個
// 2.並且可變參數必須放在函數聲明參數列表最後
func test(args ...string) {
fmt.Println("%T, %#v", args, args)
}
//至少有n個參數
//add
func add(n1, n2 int, args ...int) int {
total := n1 + n2
for _, v := range args {
total += v
}
return total
}
func mult(n1, n2 int) int {
return n1 * n2
}
func main() {
test()
test("1")
test("1", "2")
fmt.Println(add(1,2,3,4))
}
返回值
1.多個返回值
func calc(n1, n2 int) (int, int) {
//a, b := 1, 2
r1 := mult(1, 2)
r2 := add(1, 2)
return r1, r2
}
函數類型
1.聲明&初始化&調用
//定義函數類型變量,並使用零值nil進行初始化
var callback func(n1, n2 int) (r1, r2, r3, r4 int)
fmt.Printf("%T, %v", callback, callback)
//賦值爲函數calc
callback = calc
fmt.Println(callback(5, 2)) //調用calc函數
2.值類型與引用
import "fmt"
func main() {
// 在內存中申請內存新的空間,將a的值拷貝到b中
// 在修改a 不影響b
// 在修改a 影響b
//值類型 b = a,tmpAge修改不影響age
age := 30
tmpAge := age
tmpAge = 31
fmt.Println(age, tmpAge)
//引用類型 修改tmpUsers影響users
users make([]string, 10)
tmpUsers := users
tmpUsers[0] = "kk"
fmt.Printf("%#v, %#v\n", users, tmpUsers)
}
3. 值類型,函數內修改實參的值
func change(value int) {
value += 1
}
func changePointer(pointer *int) {
*pointer = *pointer + 1
}
func main() {
value := 1
change(value)
fmt.Println(value) // 1
changePointer(&value)
fmt.Println(value) // 2
}
4.函數作爲形參
package main
import "fmt"
func calc(n1 int, n2 int, callback func(int, int) int) int {
// 不定義是什麼運算
// 通過函數參數傳遞我要進行運算
rt := callback(n1, n2)
if rt >= 0 && rt <= 100 {
return rt
}
return -1
}
func add(n1, n2 int) int {
return n1 + n2
}
func multi(n1, n2 int) int {
return n1 * n2
}
func main() {
fmt.Println(calc(1, 2, add))
fmt.Println(calc(10, 100, multi))
}
5.定義函數變量
package main
import "fmt"
func calc(n1 int, n2 int, callback func(int, int) int) int {
// 不定義是什麼運算
// 通過函數參數傳遞我要進行運算
rt := callback(n1, n2)
if rt >= 0 && rt <= 100 {
return rt
}
return -1
}
//第一種
func main() {
add := func(n1, n2 int) int {
return n1 + n2
}
multi := func(n1, n2 int) int {
return n1 * n2
}
fmt.Println(calc(1, 2, add))
fmt.Println(calc(10, 100, multi))
}
//第二種
func main() {
fmt.Println(calc(1, 2, func(n1, n2 int) int {
return n1 + n2
}))
fmt.Println(calc(10, 100, func(n1, n2 int) int {
return n1 * n2
}))
}
閉包
package main
import "fmt"
func addBase(base int) func(int) int {
return func(n int) int {
return base + n
}
}
func main() {
add1 := addBase(1)
fmt.Println(add1(5))
add10 := addBase(10)
fmt.Println(add10(3))
}
錯誤處理
1.error接口
Go語言通過error接口實現錯誤處理的標準模式,通過使用函數返回值列表中的最後一個值返回錯誤信息,將錯誤的處理交由程序員主動進行處理
error接口初始化方法
a)通過errors包的New方法創建
b)通過fmt.Errorf方法創建
//定義除法函數,若除數爲0則使用error返回錯誤信息
func div(n1, n2 int) int {
if n2 == 0 {
return -1, errors.New("除數爲0")
}
return n1 / n2, nil
}
func main() {
if rt, err = div(1, 0); err == nil {
fmt.Println("nil")
}
else {
fmt.Println(err)
}
}
2.defer
defer關鍵字用戶聲明函數,不論函數是否發生錯誤都在函數最後執行(return之前),若使用defer聲明多個函數,則按照聲明的順序,先聲明後執行(先進後出),常用來做資源釋放,日記記錄工作
在函數退出時執行
func main() {
//defer 函數調用
defer func() {
fmt.Println("defer")
}
fmt.Println("main")
}
延遲執行,先輸出main,在輸出defer
func main() {
//defer 函數調用
defer func() {
fmt.Println("defer")
}()
defer func() {
fmt.Println("defer A")
}()
defer func() {
fmt.Println("defer B")
}()
fmt.Println("main")
}
輸出:
main
deferB
deferA
defer
defer是先進後出結構
3.panic與recover函數
go語言提供panic和recover函數用於處理運行時錯誤,當調用panic拋出錯誤,中斷原有的控制流程,常用於不可修復性錯誤。recover函數用於終止錯誤處理流程,僅在defer語句的函數中有效,用於截取錯誤處理流程,recover只能捕獲到最後一個錯誤。
a)panic
package main
import "fmt"
func main() {
defer func() {
fmt.Println("defer 01")
}()
panic("error go")
}
b)recover
//當未發生panic則recover函數得到的結果爲nil
func success() {
defer func() {
fmt.Println(recover())
}()
fmt.Println("success")
}
//當發生panic則recover函數得到的結果爲panic傳遞的參數
func failure() {
defer func() {
fmt.Println(recover())
}()
fmt.Println("failure")
panic("error")
}
//revover只能獲取最後一次的panic信息
func failure2() {
defer func() {
fmt.Println(recover())
}()
defer func() {
fmt.Println("failure 2")
}()
fmt.Println("failure")
panic("error")
}