函数
定义一个函数 跨包的函数需要首字母大写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 func add (a int , b int ) (int ) { return a + b }func main () { fmt.Println(add(1 , 2 )) }func add (a int , b int ) (int , int ) { return a + b, a - b }func main () { a, b := add(1 , 2 ) fmt.Println(a, b) }
不支持重载 相同函数重新声明会报错
1 2 3 4 5 6 func demo1 (a int , b int ) { fmt.Println(a + b) }func demo1 (a int ) { fmt.Println(a) }
可变长度参数 1 2 3 4 5 6 7 8 9 10 11 12 13 func main () { fmt.Println("main" ) test() test(1 ) test(1 , 2 , 3 ) }func test (args ...int ) { for i := 0 ; i < len (args); i++ { fmt.Printf("args[%d]=%d \n" , i, args[i]) } }
基本数据类型和数组进行值传递 值传递是只传递值 函数内部改变值不会导致函数外数据的改变 引用传递是改变函数内部的值会改变函数外部的变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 func main () { fmt.Println("main" ) var a int = 10 test(a) fmt.Println("test a = " , a) }func test (a int ) { a = 20 fmt.Println(a) }func main () { fmt.Println("main" ) var a int = 10 test(&a) fmt.Println("test a = " , a) }func test (a *int ) { *a = 20 fmt.Println(*a) }
函数可以作为值被变量引用 基本实例
1 2 3 4 5 6 7 8 func main () { fmt.Println("main" ) fun := test fun(10 ) }func test (a int ) { fmt.Println(a) }
函数作为参数传递进另一个函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 func main () { fmt.Println("main" ) fun := test getFunc(10 , test) getFunc(10 , fun) }func test (a int ) { fmt.Println("test" ) fmt.Println(a) }func getFunc (a int , testFunc func (int ) ) { fmt.Println("getFunc" ) testFunc(a) }
为了简化数据类型定义 go支持自定义数据类型 其实相当于给数据类型起别名 虽然是相当于起别名 但是go还是认为自定义的是一种新的数据类型 如果想要相互转换需要强转 基本语法 type 自定义类型别名 数据类型
1 2 3 4 5 6 7 8 func main () { fmt.Println("main" ) type myInt int var num1 myInt = 10 var num2 int = 20 num2 = int (num1) fmt.Println(num2) }
可以给函数起别名 方便数据传递时候参数类型的书写 1 2 3 4 5 6 7 8 9 10 11 12 type myFunc func (int ) func main () { fmt.Println("main" ) test(10 , t) }func t (a int ) { fmt.Println("test:" , a) }func test (a int , testFunc myFunc) { testFunc(a) }
支持给返回值命名 这样返回值的顺序不会影响最终返回值的位置
1 2 3 4 5 6 7 8 9 10 11 func main () { fmt.Println("main" ) a, b := test(10 , 20 ) fmt.Println(a, b) }func test (a int , b int ) (res1 int , res2 int ) { res1 = a + b res2 = a - b return }
init函数 初始化函数,可以用来进行一些初始化的操作 init函数在main函数之前被执行 全局变量在init函数之前执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var n1 int = test()func test () int { fmt.Println("test func" ) return 10 }func init () { fmt.Println("init func" ) }func main () { fmt.Println("mian func" ) }
如果包中含有init函数 则先执行包中的init函数再执行main中的全局变量
匿名函数 如果有个函数只需要被调用该一次可以使用匿名函数
在定义匿名函数的时候直接调用 使用最多的方式
1 2 3 4 5 6 func main () { var n1 int = func (a int ,b int ) int { return a + b }(10 ,20 ) fmt.Println(n1) }
将匿名函数赋值给一个变量 1 2 3 4 5 6 func main () { f1 := func (a int ,b int ) int { return a+b } fmt.Println(f1(10 ,20 )) }
全局可调用的匿名函数 1 2 3 4 5 6 var Func1 = func (a int ,b int ) int { return a * b }func main () { fmt.Println(Func1(10 ,20 )) }
闭包 闭包就是一个函数与其相关的引用环境组合的一个整体 闭包是返回的匿名函数+匿名函数意外的变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 func getSum () func (int ) int { var sum int = 0 return func (num int ) int { sum += num return sum } }func main () { f := getSum() fmt.Println(f(1 )) fmt.Println(f(2 )) fmt.Println(f(3 )) }
不使用闭包实现以上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 func getSum (a *int ,b int ) int { *a += b return *a }func main () { var ( sum = 0 a = 10 b = 20 c = 30 ) fmt.Println(getSum(&sum,a)) fmt.Println(getSum(&sum,b)) fmt.Println(getSum(&sum,c)) }