day04 函数

普通函数

  • 定义 : func 函数名 {}
  • 执行函数 : 函数名()
  • 函数 类型
    • 无参数函数
    • 无返回值函数
    • 有1个或者多个 参数 函数
    • 有1个或者多个 返回值 函数
  • 参数的传递
    • 引用传递 切片
    • 值传递
  • 函数作用域
    • 函数内部的定义的变量,只能作用到函数内部
    • 全局变量,函数内也可以使用
go code
package main

import "fmt"

func test1() {
	fmt.Println("执行test1")
}

func compareNum(num1 int, num2 int) int {
	if num1 < num2 {
		return num2
	} else {
		return num1
	}
}
func exchangeString(x string, y string) (string, string) {
	return y, x
}

func funcDefineReturn(x, y float64) (circumference float64, area float64) {
	// 不需要函数定义变量接收结果
	circumference = (x + y) * 2 // 周长
	area = x * y                // 面积
	// 函数定义好返回顺序。return 可以不跟结果,直接按照函数定义顺序返回结果
	return
}
func funcDefineReturnNotUse(x, y float64) (circumference float64, area float64) {
	circumference = (x + y) * 2 // 周长
	area = x * y                // 面积
	// 函数定义好返回顺序。return 可以跟结果。将覆盖函数定义时返回顺序
	return area, circumference
}
func funcNotDefineReturnUse(x, y float64) (float64, float64) {
	// 需要自定义 函数内部变量接收结果
	circumference := (x + y) * 2 // 周长
	area := x * y                // 面积
	// 函数定义好返回顺序。return 可以跟结果。将覆盖函数定义时返回顺序
	return circumference, area
}

func getSum(nums ...int) int {
	// ...any , ...any 表示可变参数。 可变参数必须放在最后面
	// nums 类型
	fmt.Printf("%T\n", nums) // []int 一维数组
	sum := 0

	for i := 0; i < len(nums); i++ {
		sum += nums[i]
	}
	return sum
}
func main() {
	/*  go 中的函数 */
	// 定义 : func 函数名 {}
	// 执行函数  函数名()

	// 1. 函数执行
	test1()

	// 2. 函数 类型
	/*
		- 无参数函数
		- 无返回值函数
		- 有1个或者多个 参数 函数
		- 有1个或者多个 返回值 函数
	*/

	//  多个参数,且1个返回值. 返回值数据类型保持一致
	compareRes := compareNum(1, 2)
	fmt.Println("compareNum func result: ", compareRes)

	// 交换两个string位置
	x := "hello"
	y := "word"
	fmt.Println("exchangeString func before: ", x, y)

	exchangeResX, exchangeResY := exchangeString(x, y)
	fmt.Println("exchangeString func result: ", exchangeResX, exchangeResY)

	// 匿名接收
	exchangeResX1, _ := exchangeString(x, y)
	fmt.Println("exchangeString anonymity func result: ", exchangeResX1)

	// return 结果
	/*
		- 1. 函数定义好返回顺序。return 可以不跟结果,直接按照函数定义顺序返回结果  funcDefineReturn
		- 2. 函数定义好返回顺序。return 可以跟结果。将覆盖函数定义时返回顺序  funcDefineReturnNotUse
		- 3. 函数定义好返回顺序。return 可以跟结果。将覆盖函数定义时返回顺序  funcNotDefineReturnUse
	*/
	fmt.Println("【边长:1, 变长:2. 面积:2,周长:6】")
	circumference1, area1 := funcDefineReturn(1, 2)
	fmt.Println("circumference1:", circumference1, "area1", area1)
	circumference2, area2 := funcDefineReturnNotUse(1, 2)
	fmt.Println("circumference2:", circumference2, "area2", area2)
	circumference3, area3 := funcNotDefineReturnUse(1, 2)
	fmt.Println("circumference3:", circumference3, "area3", area3)

	// 可变参数: 一个函数的参数类型确定,参数的个数不确定。则使用可变参数 : ...any
	fmt.Println(getSum(1, 2, 3, 4, 5))

}

递归函数

  • 递归函数介绍
    • 函数自己调用自己,即:递归函数
    • 递归函数需要 终止条件。 否则形成死循环
    • 压栈
go code
package main

import "fmt"

func recursionFBI(frequency int) int {
	// 递归终止条件
	if frequency <= 1 {
		return frequency
	}
	return recursionFBI(frequency-1) + recursionFBI(frequency-2)
}

func main() {

	// 递归函数,
	/*
		- 函数自己调用自己,即:递归函数
		- 递归函数需要 终止条件。 否则形成死循环
		- 压栈
	*/

	// 练习题:斐波那契 结果:1,1,2,3,5,8,13,21,34,55
	/*
		斐波那契(前两个相加等于新值)递归思路:
		循环 :1  结果 :1	n=1 r=1    终止条件(n-1)+ (n-2) = recursionFBI(frequency-1) + recursionFBI(frequency-2)
		循环 :2  结果 :1	n=1 r=1		1+0	(n-1)+ (n-2) = recursionFBI(frequency-1) + recursionFBI(frequency-2)
		循环 :3  结果 :2	n=2 r=2		2+0	(n-1)+ (n-2) = recursionFBI(frequency-1) + recursionFBI(frequency-2)
		循环 :4  结果 :3	n=3 r=3		3+0	(n-1)+ (n-2) = recursionFBI(frequency-1) + recursionFBI(frequency-2)
		循环 :5  结果 :5	n=1 r=1		4+1	(n-1)+ (n-2) = recursionFBI(frequency-1) + recursionFBI(frequency-2)
		循环 :6  结果 :8	n=1 r=1		5+3	(n-1)+ (n-2) = recursionFBI(frequency-1) + recursionFBI(frequency-2)
		循环 :7  结果 :13	n=1 r=1		7+6	(n-1)+ (n-2) = recursionFBI(frequency-1) + recursionFBI(frequency-2)
		......
	*/

	for i := 1; i <= 10; i++ {
		res := recursionFBI(i)
		fmt.Printf("循环次数:%d。斐波那契数:%d\n", i, res)

	}
}

defer 延时函数

  • defer 延时函数。 多个defer时,按照逆向顺序执行。
  • defer 场景: 文件流关闭,错误error,网络关闭等
go code
package main

import "fmt"

func test(s string) {
	fmt.Println(s)
}

func main() {
	/*
		- defer 延时函数。 多个defer时,按照逆向顺序执行。
		- defer 场景: 文件流关闭,错误error,网络关闭等
	*/

	//  defer 延时执行+逆序执行
	test("1")
	defer test("2")
	test("3")
	defer test("4")
	defer test("5")
	test("6")
	// 1 , 3, 6 , 5, 4 , 2

}

defer 函数中的调用

go code
package main

import "fmt"

func test2(n int) {
	fmt.Println("test2 函数中 defer n结果:", n)
}
func main() {
	// defer 在函数中延时执行
	n := 1
	fmt.Println("main n result start : ", n)
	defer test2(n) // n =1 已经传入到函数中。类似于驻留机制
	n++
	fmt.Println("main n result end : ", n)

}

函数类型

  • func
go code
package main

import (
	"fmt"
	"reflect"
)

// 无参无返回值
func test3() {

}

// 有参数,有返回值
func test4(n1, n2 int) (int, int) {

	return 0, 0
}

// 有参数,有返回值. ...any
func test5(n1, n2 int, c ...string) (int, int, string) {

	return 0, 1, "2"

}
func main() {

	// 函数在go中。也属于一种数据类型。  函数也可以赋值给变量,该变量定义时为函数原类型
	fmt.Printf("test3 函数类型: %T\n", test3) // test3 函数类型: func()
	fmt.Printf("test4 函数类型: %T\n", test4) // test4 函数类型: func(int, int) (int, int)
	fmt.Printf("test5 函数类型: %T\n", test5) //  test5 函数类型: func(int, int, ...string) (int, int, string)

	// 定义 变量接收函数
	var test6 func(int, int) (int, int)
	test6 = test4
	fmt.Printf("test6 函数类型: %T\n", test6)                             //  test6 函数类型: func(int, int, ...string) (int, int, string)
	fmt.Println("test6 函数内存地址: \n", reflect.ValueOf(test6).Pointer()) //  test6 函数内存地址:20792352
	fmt.Println("test4 函数内存地址: \n", reflect.ValueOf(test4).Pointer()) //  test4 函数内存地址:20792352

	f3, f4 := test6(1, 2)
	fmt.Println(f3, f4)

}

匿名函数

  • 匿名函数。没有函数名的函数
go code
package main

import "fmt"

func main() {
	// 匿名函数。没有函数名的函数
	anonymityFunc1 := func() {
		fmt.Println("123")
	}
	anonymityFunc1()

	// 匿名函数传参,且有返回值.  传递参数必须要有结果。 形成:`闭包结构`. 类似于 前端 js 的闭包结构
	anonymityFunc3 := func(a1, b1 int) int {
		fmt.Println("匿名函数参数:a1", a1, "b1", b1)
		return a1 + b1
	}(1, 2)
	fmt.Println("匿名函数 传参 的返回值:", anonymityFunc3)
}

回调函数

  • 回调函数就是一个被作为参数传递的函数

package main

import "fmt"

func main() {

	// 回调函数。回调函数就是一个被作为参数传递的函数

	// 1. 定义一个 sum 加法函数
	fmt.Println("sum:", sum(1, 2))
	sum1 := theReckonerFunc(1, 2, sum)
	fmt.Println("theReckonerFunc 加法:", sum1)
	fmt.Println()

	// 2. 定义一个 变量 sub 减法函数
	sub := func(a, b int) int {
		return a - b
	}
	sub1 := theReckonerFunc(1, 2, sub)
	fmt.Println("theReckonerFunc 减法:", sub1)
	fmt.Println()

	// 3. 定义 一个 匿名函数 乘法函数
	multiplication1 := theReckonerFunc(2, 3, func(a, b int) int {
		return a * b
	})
	fmt.Println("theReckonerFunc 乘法:", multiplication1)
	fmt.Println()
	// 4. 定义 一个 匿名函数 除法函数
	punishment1 := theReckonerFunc(6, 3, func(a, b int) int {
		if b == 0 {
			return 0
		}
		return a / b
	})
	fmt.Println("theReckonerFunc 处法:", punishment1)

}

// 计算器函数
func theReckonerFunc(a, b int, fc func(a, b int) int) int {
	fmt.Println("计算器函数计算方法:", fc)
	return fc(a, b)
}

// sum 函数
func sum(a, b int) int {
	return a + b
}

go函数 闭包

  • 一个外层函数中,有内层函数,该内层函数中,会操作外层函数的局部变量并且该外层函数的返回值就是这个内层函数。
    • 在闭包结构中:局部变量的生命周期就会发生改变,
    • 正常的局部变量会随着函数的调用而创建,随着函数的结束而销毁
    • 但是闭包结构中的外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还在继续使用.
package main

import "fmt"

func main() {

	cf1 := closureFunc()
	fmt.Printf("调用【closureFunc】函数。变量 cf1 内存地址:%p\n", &cf1)
	fmt.Printf("调用【closureFunc】函数。变量 cf1 值:%d\n\n", cf1)

	//cf3 := closureFunc()
	//fmt.Printf("调用【closureFunc】函数。变量 cf3 内存地址:%p\n", &cf3)
	//fmt.Printf("调用【closureFunc】函数。变量 cf3 值:%d\n\n", cf3)

	// cf1,cf2,cf3  指向同一个匿名函数内存地址

	cf1Res := cf1()
	fmt.Printf("调用【cf1】函数。结果 cf1 内存地址:%p\n", &cf1Res)
	fmt.Printf("调用【cf1】函数。结果 cf1 值:%d\n\n", cf1Res)
	cf1Resclosure := cf1()
	fmt.Printf("调用【cf1 cf1Resclosure】函数。结果 cf1 cf1Resclosure 内存地址:%p\n", &cf1Resclosure)
	fmt.Printf("调用【cf1 cf1Resclosure】函数。结果 cf1 cf1Resclosure 值:%d\n\n", cf1Resclosure)
	fmt.Println("'-----------------'")
	cf2 := closureFunc()
	fmt.Printf("调用【closureFunc】函数。变量 cf2 内存地址:%p\n", &cf2)
	fmt.Printf("调用【closureFunc】函数。变量 cf2 值:%d\n\n", cf2)

	cf2Res := cf2()
	fmt.Printf("调用【cf2】函数。结果 cf2 内存地址:%p\n", &cf2Res)
	fmt.Printf("调用【cf2】函数。结果 cf2 值:%d\n\n", cf2Res)

	//cf3Res := cf3()
	//
	//fmt.Printf("调用【cf3】函数。结果 cf3 内存地址:%p\n", &cf3Res)
	//fmt.Printf("调用【cf3】函数。结果 cf3 值:%d\n\n", cf3Res)

}

func closureFunc() func() int {
	i := 0
	fmt.Printf("外层函数 内 i 变量 内存地址:%p\n", &i)
	fmt.Printf("外层函数 内 i 变量 :%d\n\n", i)

	retFunc := func() int {

		fmt.Printf("调用 【前】函数。全局变量 i 内存地址:%p\n", &i)
		fmt.Printf("调用 【前】函数。全局变量 i 值:%d\n\n", i)
		i++
		fmt.Printf("调用 【后】函数。全局变量 i 内存地址:%p\n", &i)
		fmt.Printf("调用 【后】函数。全局变量 i 值:%d\n\n", i)
		return i
	}
	fmt.Printf("内层函数 retFunc 内存地址:%p\n", &retFunc)

	return retFunc // 返回函数

}
posted @ 2024-07-02 00:24  染指未来  阅读(3)  评论(0编辑  收藏  举报