func funcname (/*参数列表*/)(/*a type, b type*/){
//函数体
return a, b
}
package main
import "fmt"
// ...int 不定长参数,可以为0个或多个
func sum(numbers ...int) int {
s := 0
for _, v := range numbers {
s += v
}
return s
}
func main() {
fmt.Println(sum(1, 2, 3))
}
package main
import "fmt"
// 累加100
func sum(n int) int {
if n == 0 {
return 0
}
return n + sum(n-1)
}
func main() {
fmt.Println(sum(100))
}
函数也是一种数据类型,可以通过type给同一类型的函数起别名
package main
import "fmt"
func add(a, b int) int {
return a + b
}
func minus(a, b int) int {
return a - b
}
func calc(a, b int, mf myfunc) int {
res := mf(a, b)
return res
}
/*
给func(int, int) int 这个类型的函数起名为 myfunc
类似于给golang已有的基本数据类型起别名一样,如下:
type long int64 // 这里就是给int64类型起了一个long的别名
var num long //此时num的类型其实就是int64
这里就是将有两个int类型的入参,返回值为一个int的函数,命名为myfun
*/
type myfunc func(int, int) int
func main() {
var res int
res = add(1, 1)
fmt.Println(res)
// 因为calc的其中一个参数是myfunc类型的函数,而add符合这个要求(两个int入参,返回值为一个int)所以可以将add当作参数传入calc函数中使用,这么做的目的是在于,可以通过calc函数实现加减法,方便以后的拓展,比如说想实现乘法,只需要写一个符合myfunc类型的乘法函数,就可以通过calc掉用它
// 总的来说,是方便给代码增加功能
res = calc(1, 1, add) // 等价于add(1,1)
fmt.Println(res)
}
1> 匿名函数的定义方式
package main
import "fmt"
func main() {
//无参数无返回值匿名函数,赋值给f1,并通过f1()调用
f1 := func() {
fmt.Println("无参数无返回值的匿名函数")
}
f1()
//有参数有返回值的匿名函数,将返回值赋给sum,直接在定义匿名函数的同时就掉用
sum := func(a, b int) int {
return a + b
}(1, 2)
fmt.Println(sum)
}
2> 闭包
所谓闭包就是一个函数“捕获”了和它在同一作用域的其它常量和变量。这就意味着当闭包被调用的时候,不管在程序什么地方调用,闭包能够使用这些常量或者变量。它不关心这些捕获了的变量和常量是否已经超出了作用域,所以只有闭包还在使用它,这些变量就还会存在
package main
import "fmt"
func squares() func() int {
x := 0
f := func() int {
x++
return x * x
}
return f
}
func main() {
f := squares()
fmt.Println(f()) // 1
fmt.Println(f()) // 4
fmt.Println(f()) // 9
fmt.Println(f()) // 16
}
函数squares返回另一个类型为 func() int 的函数。对squares的一次调用会生成一个局部变量x并返回一个匿名函数。每次调用时匿名函数时,该函数都会先使x的值加1,再返回x的平方。第二次调用squares时,会生成第二个x变量,并返回一个新的匿名函数。新匿名函数操作的是第二个x变量。
通过这个例子,我们看到变量的生命周期不由它的作用域决定:squares返回后,变量x仍然隐式的存在于f中。
首先需要清楚一个概念:值传递和引用传递的区别
go语言的指针不能运算
go语言只有值传递一种方式(但是我们可以用指针来实现引用传递的效果)
package main
import "fmt"
func swap(a, b int) {
a, b = b, a
}
func main() {
a, b := 3, 4
swap(a, b)
// 这里没有将a,b的值交换过来,因为go里面都是值传递,
//在swap函数里,对a和b的值进行了一份拷贝,也就是说,在swap函数里面,a与b的值交换过来了,
//但是在外部,a和b的值没有发生变化,如果想通过swap函数使a和b的值交换,可以使用指针来实现
fmt.Println(a, b) // 3, 4
}
使用指针来交换a,b的值
package main
import "fmt"
func swap(a, b *int) {
*a, *b = *b, *a
}
func main() {
a, b := 3, 4
swap(&a, &b)
fmt.Println(a, b) // 4, 3
}