Function(函数参数传递的时候,值传递(基本类型),go语言中全部都是值传递 指针可以改变值)
1.Function的定义以及初始化
func functionname(parameters list)(return_types){
content
return return_types
//return可以返回单值,可以返回多值,也可以不返回值
}
(1.不返回值
func runForever() {
for {
time.Sleep(time.Second)
fmt.Println("doing")
}
}
(2.返回多值或单值
func add(a, b int, c float32) (int, error) {
//go一个函数可以返回多值
return a + b + int(c), nil
//不同类型的值相加要格式转化,并不能像c一样直接相加转为float型
}
func main() {
//go函数支持普通函数,也支持匿名函数、闭包
/*
go中函数是“一等公民”
1.函数本身可以当做变量
2.函数包含了匿名函数、闭包
3.函数可以满足接口
*/
sum, _ := add(1, 2, 3.14)
fmt.Println(sum)
}
(3.省略写法
func add(a, b int) (sum int, err error) {
sum=a+b
return sum,err
//return
}
可以直接在return_types中定义返回的变量名和类型,避免了再次在函数体中用var定义的繁琐过程
//return 如果在return_types中已经定义了变量名则可以不在return语句中写返回的变量名,go会直接返回return_types
(4.省略号用法
// 省略号的用法
func add(item ...int) (sum int, err error) {
for _, value := range item {
sum += value
}
return
}
func main() {
a := 1
b := 2
sum, _ := add(a, b, 3, 4, 5, 6)
fmt.Println(sum)
}
//1+2+3+4+5+6=21
此时item的本质其实是为一个[]int型的切片
想要切片相加则使用for.range
此时可以往add函数传递多个int型parameters
func add(desc string,item ...int) (sum int, err error) {
for _, value := range item {
sum += value
}
return
}
如果在item前添加了一个正常的parameter那么该parameter是必须要传递值到该function里的
item可以不传入。
以下是Function的底层逻辑图
当我们在add里面改变a的值时,他只是改变了从main函数里面复制的值,并没有办法改变main函数a的值
func add(a, b int, c float32) (int, error) {
a = 3
return a + b + int(c), nil
}
func main() {
a := 1
sum, _ := add(1, 2, 3.14)
fmt.Println(sum)
fmt.Println(a)
此时可以看到a的值仍然为1
但是返回的值为8,说明在add中a的值为3,也说明了在add函数中更改a的值并不会影响main函数中的a
2.Function的一等公民特性
(1.function可以当作变量使用
func add(item ...int) (sum int, err error) {
for _, value := range item {
sum += value
}
return
}
func main() {
**funcVar := add**
a := 1
b := 2
**sum, _ := funcVar(a, b, 3, 4, 5, 6)**
fmt.Println(sum)
fmt.Println(a)
}
Eg:
func cal(op string) func() {
switch op {
case "+":
return func() {
fmt.Println("这是加法")
}
case "-":
return func() {
fmt.Println("这是减法")
}
default:
return func() {
fmt.Println("这是加法")
}
}
}
func main{
cal("+")()
}
(2.function可以作为参数
func add2(a, b int) {
fmt.Printf("sum is:%d\r\n", a+b)
}
func callBack(y int, f func(int, int)) {
f(y, 2)
}
func main{
callBack(1, add2)
}
(3.匿名函数
//第一种
callBack(1, func(a, b int) {
fmt.Printf("total is %d", a+b)
})
//第二种
localFunc := func(a, b int) {
fmt.Printf("total is %d", a+b)
}
callBack(1, localFunc)
可以直接在函数调用时命名匿名函数
3.Function的闭包特性
func auoIncrement() func() int {
local := 0
return func() int {
local += 1
return local
}
}
//闭包
//有个需求,我希望有个函数每次调用一次返回的结果值都是增加一次之后的值
func main{
nextFunc := auoIncrement()
for i := 0; i < 5; i++ {
fmt.Println(nextFunc())
}
}
正常情况下在一个函数中访问另一个函数的局部变量是不可行的
但是如果在使用闭包(一个函数中调用一个匿名函数)即可使用原函数的局部变量
可以做到类似于c语言static类型的效果让值累加
nextFunc2 := auoIncrement()
for i := 0; i < 3; i++ {
fmt.Println(nextFunc2())
}
当你再次调用该函数闭包是会发现此时的local值已经清0重新开始运算。
也可以完成的local变量的封装
4.Function中defer的运用
defer多用于关闭数据库,关闭文件,关闭锁
var mu sync.Mutex
mu.Lock()
defer mu.unLock()//defer后面的代码是会放在函数return之前执行的
关于defer的具体应用
defer fmt.Println("1")
defer fmt.Println("2")
defer fmt.Println("main")
//类似于一个栈的逻辑
return