Loading

golang函数

函数定义

/*
函数定义关键字 func
func 函数名 (参数 参数类型) 函数返回值的类型
*/
func getInfo(name string, age int) string {
	return name
}

// 函数返回多个返回值:则返回类型括号包裹(返回值类型,类型..),即时返回两个int,也需要(int,int)
func getNum(x int, status bool) (int, bool) {
	return x, status

}

// 函数返回值命名:函数定义时给返回值命名,并在函数体内可以直接使用这些变量,最后通过return返回
// 返回值是int类型,给返回值命名为num,并且可以直接调用
func sumNumber(x, y int) (sum int) {
	sum = x + y
	return sum

}

// 函数参数简写:如果参数的类型一样,可以只写一个类型
func setName(name, nickname string, age, height int) string {
	return nickname
}

// 函数可变参数:可变参数是指函数的参数数量不固定,在参数名后加...来标识
func getParam(x ...int) []int {
	// 传递可变参数,传递的参数类型是一个切片
	return x
}



// 函数可以没有参数和返回值
func test(){
  	fmt.Println("t")

}

函数类型

可以使用type关键字来定义一个函数类型

/* 语法 */
//  类型的名字  该函数类型要传递的参数、该函数类型要返回的类型
type name func(string,string) string


// 自定义一个name类型
type name func(string, string) string

// 定义一个yoyo函数
func yoyo(a, b string) string {
	return a
}

func main() {
	// 定义一个test变量,是一个name类型
	var test name

	// 给test赋值的时候,因为上面声明了name类型,如果参数和返回值不符合name类型的条件,就会报错
	test = yoyo
	fmt.Printf("%T", test) // main.name  main文件里面的name类型

	// yoyo赋值给test,可以通过test()来当函数调用
	test("1", "1")

}


/*

也可以自定义其他类型,比如自定义一个myInt类型,需要是int
type myInt int

*/

函数当做参数传递和返回值

当参数传递:

/* 语法一 */

func a(num int) int {
	return num
}

func b(num int) int {
	return num
}

// 定义c方法,传递num参数,然后传递一个函数,这个函数是有一个int参数,返回也是int
func c(num int, f func(int) int) int {
	return f(num)
}

func main() {
	fmt.Println(c(1, a))
}

/* 语法二 */

// 自定义Number类型
type number func(int) int

// 定义c方法,传递num参数,然后传递一个函数,符合Number类型
func c(num int, f number) int {
	return f(num)
}

func main() {
	fmt.Println(c(1, a))
}

函数当做返回值:

/* 语法一 */
func b(num int) int {
	return num
}

// 自定义Number类型
type number func(int) int

// 定义c方法 返回类型是number
func c(num int) number {
	return b
}
/* 语法二 */

func b(num int) int {
	return num
}


// 定义c方法 指定返回值类型为 一个int参数且返回值值为int的函数
func c() func(int) int {
	return b
}

func main() {
	fmt.Println(c()(1))
}

匿名函数

匿名函数就是没有函数名的函数

func main() {

	// 匿名自执行函数,可以传递参数也可以不传
	func() {
		fmt.Println("test")
	}() // 在后面+()调用

	// 匿名函数赋值变量
	var fn = func(x int, y int) int {
		return x + y
	}
	// 调用匿名函数变量
	fn(1, 1)
}



函数递归

func A(n int) {
	fmt.Println("n")
	
	n--
	// n大于1的时候递归调用自身, 递归调用需要注意死循环问题
	if n > 1 {
		A(n)
	} 

}

函数闭包

image-20240220163253405

image-20240220163332001

// 写法:函数里面嵌套一个函数,最后返回里面的函数
func testA() func() int {
   i := 10
   return func() int {
   	i++
   	return i
   }

}

func main() {
   // testA 赋值给a  testA返回的是匿名函数
   var a = testA()
   // 调用a(),调用的是testA中的匿名函数   i常驻内存中,依次++
   fmt.Println(a()) // 11
   fmt.Println(a()) // 12
   fmt.Println(a()) // 13

}

defer语句

image-20240220164320350

	// 执行顺序 1、4、3、2
	fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)
	fmt.Println(4)
// eeee、aaa
func testA() {

	defer func() {
		fmt.Println("aaa")
	}()
	fmt.Println("eeee")
}

defer在命名返回值和匿名返回函数中的区别:

defer注册要延迟执行的函数时该函数所有的参数都要确定其他值,然后执行的时候按照执行顺序

image-20240220165432175

// 匿名返回值
func testA() int {
	var a int
	defer func() {
		a++

	}()
	return a
}
// 命名返回值
func testB() (b int) {
	defer func() {
		b++

	}()
	return b
}

func main() {
	fmt.Println(testA()) // 0
	fmt.Println(testB()) // 1
}

内置函数panic/recover

image-20240220170707925

panic的作用是主动抛出异常并终止程序执行

image-20240220171036425

  • recover()必须放在defer里面执行,recover的作用是监听panic抛出的异常,如果panic没有抛出异常,则是nil,可以以此来判断

  • recover()必须搭配 defer 使用。

  • defer 一定要在可能引发 panic 的语句之前定义

func testA() {
	fmt.Println("A")
	// 使用defer延迟执行
	defer func() {
		// recover 监听panic抛出的异常,如果!=nil,说明panic有抛出的异常,可以进行对应的处理,不终止程序执行
		err := recover()
		if err != nil {
			fmt.Println(err)
		}
	}()
  // 主动使用panic 抛出异常
	panic("抛出异常")

}

func testB() {
	fmt.Println("B")
}

func main() {
	testA()
	testB()
}

func sum(a, b int) int {
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println(err) // runtime error: integer divide by zero

		}
	}()
	// 10 不能 / 0 ,所以会发生错误,go本身会使用panic抛出异常
	return a / b
}

func main() {
	fmt.Println(sum(10, 0))

}

搭配使用:

import (
	"errors"
	"fmt"
)

func name(n string) error {
	if n == "li"{
		return nil
	}	
	return errors.New("名字错误")
	

}

func main() {
	
	defer func() {
		// 3. 监听到抛出的异常
		err := recover()
		if err!=nil{
			fmt.Println("err")
			}
	}()
	//  1.调用name,如果返回nil 说明没有异常,不是nil则有异常
	nick := name("1")
	//  2. 如果有异常 则使用panic主动抛出
	if nick != nil{
		panic("error")
		}

}
posted @ 2024-02-20 17:34  木子七  阅读(39)  评论(0编辑  收藏  举报