这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战
1. 函数的返回值
一个函数被调用后,返回调用处的执行结果,叫做函数的返回值
调用处需要使用变量接收该结果
1. 一个函数可以返回多个值
- 一个函数可以没有返回值,也可以有一个返回值,也可以有多个返回值
pageage main
import "fmt"
func local(s, y string)(string, string) {
return y, x
}
func main() {
a, b := local("xiaohe", "afei")
fmt.Println(a, b)
} // afei, xiaohe
func product(A, B int) (add int, multiplied int) {
add = A + B
multiplied = A + B
return
} // nil
2. 空白标识符
_是go中的空白标识符。
它可以代替任何类型的任何值
比如rectPoints函数返回的结果是面积和周长,如果我们只要面积,不要周长,就可以使用空白标识符
package main
import "fmt"
func rectPoints(length, width float64) (float64, float64) {
var area = length * width
var perimeter = (length + width) * 2
return area, perimeter
}
func main() {
area, _ := rectPoints(10, 5)
fmt.Printf("area is %f", area)
} // 50
2. 函数中变量的作用域
作用域:变量可以使用的范围
局部变量
一个函数内部定义的变量,就叫做局部变量 变量在哪里定义,就只能在哪个范围内使用,超出这个范围,我们认为变量就被销毁了
// 定义函数[testScope], 分析函数的作用域
func testScope(args int) {
args = 100
fmt.Println(args)
}
// 调用
var args int
testScope(args)
fmt.Println(args)
// 100
// nil
全局变量
一个函数外部定义的变量,就叫做全局变量 所有的函数都可以使用,而且共享这一份数据
递归函数
什么是递归函数,在一个循环体当中执行,必须有一个条件可以在满足某个条件时终止当前的循环,否则死循环 例如: 斐波那契数列
/*
位置 值
1 1
2 1
3 2
4 3
.. ..
n func(n-1) + func(n-2)
*/
传递一个位置,返回当前位置的值
- 1.定义函数[fibonaci]实现
func fibonaci(index int64) int64 {
if index == 1 || index == 2 {
return 1
} else {
return fibonaci(index-1) + fibonaci(index-2)
}
}
- 2.调用
//第20位置对应的值
fmt.Println(fibonaci(2))
defer
延迟是什么
即延迟(defer)语句,延迟语句被用于执行一个函数调用,在这个函数之前,延迟语句返回
延迟函数
你可以在函数中添加多个defer语句。被函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄漏等问题
- 如果有很多调用defer,那么defer是采用
后进先出模式 - 在离开所在的方法时,执行(报错也会执行)
func reader() bool {
file.Open("file")
defer file.close()
if failureX {
return false
}
if failureY {
return false
}
return true
}
// 最后才执行file.close()
示例:
package main
import "fmt"
func main() {
a := 1
b := 2
defer fmt.Println(b)
fmt.Println(a)
}
// 结果
// 1
// 2
示例:
package main
import "fmt"
func finished() {
fmt.Println("Finished finding largest")
}
func largest(nums []int) {
defer finished()
fmt.Println("started finding largest")
max := nums[0]
for _, v := range nums {
if v > max {
max = v
}
}
fmt.Println("largest number in", nums, "is", max)
}
func main() {
nums := []int{1, 2, 3, 4, 5}
largest(nums)
}
// Started finding largest
// largest number in [1 2 3 4 5] is 5
// Finished finding largest
延迟方法
延迟并不仅仅局限于函数。延迟一个方法调用也是完全合法的。
package main
import "fmt"
type person struct {
firstName string
lastName string
}
func (p person) fullName() {
fmt.Printf("%s %s", p.firstName.p.lastName)
}
func main() {
p := person {
firstName: "xiaohe",
lastName: "afei"
}
defer p.fullName()
fmt.Printnf("Welcome")
}
// Welcome xiaohe afei
延迟参数
延迟函数的参数在执行延迟语句时被执行,而不是在执行时记得函数调用时执行
package main
import "fmt"
func printA(a int) {
fmt.Println("value of a in deferred function", a)
}
func main() {
a := 5
defer printA(a)
a = 10
fmt.Println("value of a befored function call", a)
}
// 后进,先出
// value of a befored function call 10
// value of a in deferred function 5
堆栈的推迟
当一个函数有多个延迟调用时,它们被添加到一个堆栈中,并在last in first out(LIFO)后进先出的顺序中执行
package main
import "fmt"
func main() {
name := "afei"
fmt.Printf("name string %s\n", string(name))
fmt.Printf('reversed string:")
for _, v := range []rune(name) {
defer fmt.Printf("%c", v)
}
}
// name string: afei
// reversed string: AFEI
defer注意点:
- 当外围函数中的语句正常执行完毕时,只有其中所有的延迟函数都执行完毕,外围函数才会真正的结束执行。
- 当执行外围函数中的return语句时,只有其中所有的延迟函数都执行完毕后,外围函数才会真正返回。
- 当外围函数中的代码引发运行恐慌时,只有其中所有的延迟函数都执行完毕后,该运行时恐慌才会真正被扩展至调用函数。