Go函数高级

1. 函数的数据类型

package main

import "fmt"

func main() {
	/*
	go语言的数据类型:
		基本数据类型:
				int,float,bool,string

		复合数据类型:
				array,slice,map,function,pointer,struct,interface。。。


	函数的类型:
			func(参数列表的数据类型)(返回值列表的数据类型)

	 */

	a := 10
	fmt.Printf("%T\n", a) //int
	b := [4]int{1, 2, 3, 4}
	fmt.Printf("%T\n", b) //[4]int
	/*
	[4]string
	[6]float64
	 */
	c := []int{1, 2, 3, 4}
	fmt.Printf("%T\n", c) //[]int

	d := make(map[int]string)
	fmt.Printf("%T\n", d) //map[int]string
	/*
	map[string]string
	map[string]map[int]string
	 */

	fmt.Printf("%T\n", fun1) //func()
	fmt.Printf("%T\n", fun2) //func(int) int
	fmt.Printf("%T\n", fun3) //func(float64, int, int) (int, int)
	fmt.Printf("%T\n", fun4) //func(string,string,int,int)(string,int ,float64)
}

func fun1() {}

func fun2(a int) int {
	return 0
}

func fun3(a float64, b, c int) (int, int) {
	return 0, 0
}

func fun4(a, b string, c, d int) (string, int, float64) {
	return "", 0, 0
}

 2. 函数的本质

package main

import "fmt"

func main() {
	/*
	Go语言的数据类型:

		数值类型:整数,浮点
			进行运算操作,加减乘除,打印
		字符串:
			可以获取单个字符,截取子串,遍历,strings包下的函数操作。。
		数组,切片,map。。
			存储数据,修改数据,获取数据,遍历数据。。。
		函数:
			加(),进行调用

		注意点:
			函数作为一种复合数据类型,可以看做是一种特殊的变量。
				函数名():将函数进行调用,函数中的代码会全部执行,然后将return的结果返回给调用处
				函数名:指向函数体的内存地址

	 */
	//1.整型
	a := 10
	//运算:
	a += 5
	fmt.Println("a:",a) //a: 15
	//2.数组,切片,map。。容器
	b := [4]int{1,2,3,4}
	b[0] =100
	for i:=0;i<len(b);i++{
		fmt.Printf("%d\t",b[i]) //100	2	3	4
	}
	fmt.Println()

	//3.函数做一个变量
	fmt.Printf("%T\n",fun1) //func(int, int)
	fmt.Println(fun1) //0x493310 看做函数名对应的函数体的地址

	//4.直接定义一个函数类型的变量
	var c func(int,int)
	fmt.Println(c) //<nil> 空

	//var d  string
	//d = "hello"
	c = fun1 //将fun1的值(函数体的地址)赋值给c
	fmt.Println(c) //0x493310

	fun1(10,20) //a:10,b:20
	c(100,200) //a:100,b:200 c也是函数类型的,加小括号也可以被调用

	res1 := fun2 //将fun2的值(函数的地址)赋值给res1,res1和fun2指向同一个函数体
	res2 := fun2(1,2) //将fun2函数进行调用,将函数的执行结果赋值给res2,相当于:a+b
	fmt.Println(res1) //0x4932f0
	fmt.Println(res2)  //3

	fmt.Println(res1(10,20))//30 也可以被调用
	//res2() //cannot call non-function res2 (type int)
}
func fun2(a,b int)int{
	return a + b
}
func fun1(a, b int){
	fmt.Printf("a:%d,b:%d\n",a,b)
}

3. 匿名函数

package main

import "fmt"

func main() {
	/*
	匿名:没有名字
		匿名函数:没有名字的函数。

	定义一个匿名函数,直接进行调用。通常只能使用一次。也可以使用匿名函数赋值给某个函数变量,那么就可以调用多次了。

	匿名函数:
		Go语言是支持函数式编程:
		1.将匿名函数作为另一个函数的参数,回调函数
		2.将匿名函数作为另一个函数的返回值,可以形成闭包结构。
	 */

	fun1()
	fun2 := fun1
	fun2()

	//匿名函数
	func() {
		fmt.Println("我是一个匿名函数。。")
	}()

	fun3 := func() {
		fmt.Println("我也是一个匿名函数。。")
	}
	fun3()
	
	//定义带参数的匿名函数
	func(a, b int) {
		fmt.Println(a, b)
	}(1, 2)

	//定义带返回值的匿名函数
	res1 := func(a, b int) int {
		return a + b
	}(10, 20) //匿名函数调用了,将执行结果给res1
	fmt.Println(res1)

	res2 := func(a, b int) int {
		return a + b
	} //将匿名函数的值,赋值给res2
	fmt.Println(res2)

	fmt.Println(res2(100, 200))
}

func fun1() {
	fmt.Println("我是fun1()函数。。")
}

4. 高阶函数/回调函数

package main

import "fmt"

func main() {
	/*
	高阶函数:
		根据go语言的数据类型的特点,可以将一个函数作为另一个函数的参数。

	fun1(),fun2()
	将fun1函数作为了fun2这个函数的参数。
			fun2函数:就叫高阶函数
				接收了一个函数作为参数的函数,高阶函数
			fun1函数:回调函数
				作为另一个函数的参数的函数,叫做回调函数。
	 */
	//设计一个函数,用于求两个整数的加减乘除运算
	fmt.Printf("%T\n", add)  //func(int, int) int
	fmt.Printf("%T\n", oper) //func(int, int, func(int, int) int) int

	res1 := add(1, 2)
	fmt.Println(res1)

	res2 := oper(10, 20, add)
	fmt.Println(res2)

	res3 := oper(5,2,sub)
	fmt.Println(res3)

	fun1:=func(a,b int)int{
		return a * b
	}

	res4:=oper(10,4,fun1)
	fmt.Println(res4)


	res5 := oper(100,8,func(a,b int)int{
		if b == 0{
			fmt.Println("除数不能为零")
			return 0
		}
		return a / b
	})
	fmt.Println(res5)

}

//fun func(int, int) int
//这是一个函数类型
//接收两个int类型的参数,返回值是int类型
func oper(a, b int, fun func(int, int) int) int {
	fmt.Println(a, b, fun) //打印3个参数
	res := fun(a, b)
	return res
}

//加法
func add(a, b int) int {
	return a + b
}

//减法
func sub(a, b int) int {
	return a - b
}

5. 闭包

package main

import "fmt"

func main() {
	/*
	go语言支持函数式编程:
		支持将一个函数作为另一个函数的参数,
		也支持将一个函数作为另一个函数的返回值。

	闭包(closure):
		一个外层函数中,有内层函数,该内层函数中,会操作外层函数的局部变量(外层函数中的参数,或者外层函数中直接定义的变量),
		并且该外层函数的返回值就是这个内层函数。

		这个内层函数和外层函数的局部变量,统称为闭包结构。
	
		局部变量的生命周期会发生改变,正常的局部变量随着函数调用而创建,随着函数的结束而销毁。
		但是闭包结构中的外层函数的局部变量并不会随着外层函数的结束而销毁,因为内层函数还要继续使用。


	 */
	res1 := increment() //res1 = fun
	fmt.Printf("%T\n", res1) //func() int
	fmt.Println(res1) //0x493020 函数体的地址
	v1 := res1()
	fmt.Println(v1) //1
	v2 := res1()
	fmt.Println(v2) //2
	fmt.Println(res1()) //3

}

//因为闭包外层函数要返回内层函数
//func() int 就是内层函数的数据类型
func increment() func() int { //外层函数
	//1.定义了一个局部变量
	i := 0
	//2.定义了一个匿名函数,给变量自增并返回
	fun := func() int { //内层函数
		i++
		return i
	}
	//3.返回该匿名函数
	return fun
}

  

posted @ 2020-02-01 06:55  1769987233  阅读(154)  评论(0编辑  收藏  举报