这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战
函数是一块执行特定任务的代码。一个函数是在输入源基础上,通过执行一系列的算法,生成预期的输出。我们接着之前没讲完的函数模块继续学习。
空白标识符
_是Go中的空白标识符。它可以代替任何类型的任何值。让我们看看这个空白标识符的用法。
比如以下函数返回的结果是面积和周长,如果我们只要面积,不要周长,就可以使用空白标识符。
示例代码:
package main
import (
"fmt"
)
func rectProps(length, width float64) (float64, float64) {
var area = length * width
var perimeter = (length + width) * 2
return area, perimeter
}
func main() {
area, _ := rectProps(10.8, 5.6) // perimeter is discarded
fmt.Printf("Area %f ", area)
}
变量的作用域
局部变量
一个函数内部定义的变量,就叫做局部变量
全局变量
一个函数外部定义的变量,就叫做全局变量
示例代码:
package main
import "fmt"
//n := 1000 //全局变量,不能省略var
var n = 1000
func main() {
/*
变量的作用域:
1.局部变量和全局变量
局部变量:函数内部,或者{}里定义的变量
if,switch,for。。。{}
全局变量:函数外定义的变量,叫全局变量。
所有的函数都可以使用,而且是大家共享一份数据。
*/
for i := 0; i < 3; i++ {
fmt.Println("for....i", i)
}
j := 100
fmt.Println(j)
if j > 0 {
fmt.Println(j) //100
j := 200
fmt.Println(j) // 200
}
fmt.Println(j) //100
{
//代码块
fmt.Println(j)
m := 300
fmt.Println(m)
}
fun1()
fun2()
//fmt.Println(k)
}
func fun1() {
k := 1//函数内部定义的变量,局部变量,随着函数的调用而创建,随着函数的结束而销毁。
fmt.Println(k)
n = 2000
fmt.Println(n) // 2000
}
func fun2(){
//fmt.Println(k)
fmt.Println(n) // 2000
}
递归函数
什么是递归函数
一个函数自己调用自己,就叫做递归调用
递归函数的出口
一个递归函数一定要有出口,否则会陷入死循环
示例代码:
package main
import "fmt"
func main() {
/*
递归函数:一个函数自己调用自己
递归函数都有出口。
*/
r1:= getSum(5) // r1:= getSum(4)+5
fmt.Println(r1)
fmt.Println(jieCheng(5))
fmt.Println(fibonacci(12))
}
func getSum(n int) int{
fmt.Println("*********")
if n == 1{
return 1
}
return getSum(n-1) + n
}
func jieCheng(n int) int{
if n == 1{
return 1
}
return jieCheng(n - 1) * n
}
func fibonacci(n int)int{
if n == 1 ||n == 2{
return 1
}
return fibonacci(n -1) + fibonacci(n-2)
}
运行结果:
*********
*********
*********
*********
*********
15
120
144
defer函数
什么是延迟
即延迟(defer)语句,延迟语句被用于执行一个函数调用,在这个函数之前,延迟语句返回。
延迟函数
你可以在函数中添加多个defer语句。当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回。特别是当你在进行一些打开资源的操作时,遇到错误需要提前返回,在返回前你需要关闭相应的资源,不然很容易造成资源泄露等问题
- 如果有很多调用defer,那么defer是采用
后进先出模式 - 在离开所在的方法时,执行(报错的时候也会执行)
func ReadWrite() bool {
file.Open("file")
defer file.Close()
if failureX {
return false
} i
f failureY {
return false
}
return true
}
最后才执行file.Close()
示例代码:
package main
import "fmt"
func main() {
a := 1
b := 2
defer fmt.Println(b)
fmt.Println(a)
}
运行结果:
12
示例代码:
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{78, 109, 2, 563, 300}
largest(nums)
}
运行结果:
Started finding largest
Largest number in [78 109 2 563 300] is 563
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: "John",
lastName: "Smith",
}
defer p.fullName()
fmt.Printf("Welcome ")
}
运行结果:
Welcome John Smith
延迟参数
延迟函数的参数在执行延迟语句时被执行,而不是在执行实际的函数调用时执行。
让我们通过一个例子来理解这个问题。
示例代码:
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 before deferred function call", a)
}
运行结果:
value of a before deferred function call 10
value of a in deferred function 5
堆栈的推迟
当一个函数有多个延迟调用时,它们被添加到一个堆栈中,并在Last In First Out(LIFO)后进先出的顺序中执行。
我们将编写一个小程序,它使用一堆defers打印一个字符串。示例代码:
package main
import (
"fmt"
)
func main() {
name := "Naveen"
fmt.Printf("Orignal String: %s\n", string(name))
fmt.Printf("Reversed String: ")
for _, v := range []rune(name) {
defer fmt.Printf("%c", v)
}
}
运行结果:
Orignal String: Naveen
Reversed String: neevaN
defer注意点
defer函数:
当外围函数中的语句正常执行完毕时,只有其中所有的延迟函数都执行完毕,外围函数才会真正的结束执行。
当执行外围函数中的return语句时,只有其中所有的延迟函数都执行完毕后,外围函数才会真正返回。
当外围函数中的代码引发运行恐慌时,只有其中所有的延迟函数都执行完毕后,该运行时恐慌才会真正被扩展至调用函数。
示例代码:
package main
import "fmt"
func main(){
/*
defer:词意"延迟,推迟"
延迟执行函数。。等到其他的程序结束才能够执行。。
如果多个函数被defer了,先延迟的后执行,后延迟的先执行。。
如果一个被延迟的函数中涉及到了参数的传递:
函数在defer的时候就已经传递了。只是延迟执行而已。
o:=open(""...)
defer o.close()
o.exec()
//..
*/
defer printString("hello")
fmt.Println("main中执行了。。。。")
defer printString("world")
a := 1
defer fun1(a) //将a传递参数,只是暂时不执行。。
a = 100
fmt.Println(a) // 100
}
func fun1(num int){
fmt.Println("我是fun1函数。。num:",num)
}
func printString(letter string){
fmt.Println(letter)
}