博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go编程基础 - 函数function
阅读量:6714 次
发布时间:2019-06-25

本文共 4636 字,大约阅读时间需要 15 分钟。

  hot3.png

函数function

  • Go函数不支持嵌套、重载和默认参数

  • 但是支持以下特性

    • 无需声明函数原型(C\C++需要)
    • 不定长度变量参数
    • 多返回值
    • 命名返回值参数
    • 匿名函数
    • 闭包
  • 定义函数使用关键字func,且左大括号不能另起一行

  • 函数也可以作为一种类型使用

函数基本写法

func func01() {	fmt.Println("package lesson file lesson/lesson09.go function func01")}

一般的函数参数

func func02(a int, b string) {	fmt.Println("package lesson file lesson/lesson09.go function func02")	fmt.Println("func get value [a]:", a, " [b]:", b)}

函数参数省略写法

func func03(a, b, c int) {	fmt.Println("package lesson file lesson/lesson09.go function func03")	fmt.Println("func get value [a]:", a, " [b]:", b, " [c]:", c)}

多返回值 - 建议使用这种

func func04() (int, int, int) {	fmt.Println("package lesson file lesson/lesson09.go function func04")	a, b, c := 1, 2, 3	return a, b, c}

多返回值省略写法

func func05() (a, b, c int) {	fmt.Println("package lesson file lesson/lesson09.go function func05")	a, b, c = 1, 2, 3	return}

不定长度变量参数

func func06(a ...int) {	fmt.Println("package lesson file lesson/lesson09.go function func06")	fmt.Println("[a]:", a, " [a.type]:", reflect.TypeOf(a))}

固定变量与不定长度变量参数混合使用

func func07(b string, a ...int) {	fmt.Println("package lesson file lesson/lesson09.go function func07")	fmt.Println("[b]:", b, " [a]:", a, " [a.type]:", reflect.TypeOf(a))}

不定长度变量的函数,不会对外发生变更

func func08(slice ...int) {	fmt.Println("package lesson file lesson/lesson09.go function func08")	fmt.Println("[slice]:", slice)	slice[0] = 3	slice[1] = 4	fmt.Println("[slice]:", slice)}

定常Slice作为变量传入函数

// 定常的slice作为变量传入函数,会造成外部的slice发生变更

// 这种方式进行的拷贝是slice当中地址的拷贝,也就是说操作其中的数据直接产生影响

func func09(slice []int) {	fmt.Println("package lesson file lesson/lesson09.go function func09")	fmt.Println("[func09.slice]:", slice)	slice[0] = 3	slice[1] = 4	fmt.Println("[func09.slice]:", slice)}

引用类型的传递

func func10(a *int) {	fmt.Println("package lesson file lesson/lesson09.go function func10")	*a = 2	fmt.Println("[a.address]:", a, "[a.value]:", *a)}

函数名称作为变量

fmt.Println()	fmt.Println("test func11")	function01 := func01	function01()

匿名函数

fmt.Println()	fmt.Println("test func12")	function02 := func() {		fmt.Println("package lesson file lesson/lesson09.go function Anonymous Function ")	}	function02()

闭包

func closure(x int) func(int) int {	fmt.Println("[&x]:", &x)	return func(y int) int {		fmt.Println("[&x]:", &x)		return x + y	}}

闭包调用

// 闭包	fmt.Println()	function03 := closure(10)	fmt.Println(function03(1))	fmt.Println(function03(2))

defer

  • defer的执行方式类似其他预演中的析构函数,在函数体执行结束后按照调用顺序的相反顺序逐个执行
  • 即使函数发生严重错误也会执行
  • 支持匿名函数的调用
  • 常用语资源清理、文件关闭、解锁一级记录时间等操作
  • 通过与匿名函数配合可在return之后修改函数计算结果
  • 如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷贝,否则则是引用某个变量的地址

defer倒序打印

func func11(){	fmt.Println("a")	defer fmt.Println("b")	defer fmt.Println("c")}

打印输出

acb

循环中使用defer

for index:=0; index < 3;index++  {		defer fmt.Println("[index]:",index)	}

输出

2,1,0

循环中对函数使用defer

这里实际是闭包,在func里面的index是引用,但是由于defer是在循环的最后进行引用,

for index := 0;index < 3;index++{		defer func() {			fmt.Println("[index]:",index)		}() // 调用这个函数	}

输出

3,3,3

panic/recover

panic/recover 可以理解为try catch

  • Go没有异常机制,但是panic/recover模式来处理错误
  • Panic可以在任何地方引发,但recover只有在defer调用的函数中有效
func defer04() {	fmt.Println()	fmt.Println("package lesson file lesson/lesson09.go function defer04")	functionPrintA()	functionPanicB()	functionPrintC()}func functionPrintA() {	fmt.Println("package lesson file lesson/lesson09.go function functionPrintA")}func functionPanicB() {	// 在panic之前设置defer函数,才能够让defer被访问到	defer func() {		if err := recover(); err != nil {			fmt.Println("Recover in B")		}	}()	panic("package lesson file lesson/lesson09.go panic functionPanicB")}func functionPrintC() {	fmt.Println("package lesson file lesson/lesson09.go function functionPrintC")}

程序输出

package lesson file lesson/lesson09.go function defer04package lesson file lesson/lesson09.go function functionPrintARecover in Bpackage lesson file lesson/lesson09.go function functionPrintC

程序首先运行panic,出现故障,此时跳转到包含recover()的defer函数执行,recover捕获panic,此时panic就不继续传递.但是recover之后,程序并不会返回到panic那个点继续执行以后的动作,而是在recover这个点继续执行以后的动作,即执行上面的defer函数,输出1

课堂作业

分析以下程序输出结果

func homework() {	fmt.Println("package lesson file lesson/lesson09.go function homework")	var fs = [4]func(){}	for index := 0; index < 4; index++ {		defer fmt.Println("defer [index]:", index)		defer func() {			fmt.Println("defer_closure [index]:", index)		}()		fs[index] = func() {			fmt.Println("closure [index]:", index)		}	}	for _, f := range fs {		f()	}}

输出结果

package lesson file lesson/lesson09.go function homeworkclosure [index]: 4closure [index]: 4closure [index]: 4closure [index]: 4defer_closure [index]: 4defer [index]: 3defer_closure [index]: 4defer [index]: 2defer_closure [index]: 4defer [index]: 1defer_closure [index]: 4defer [index]: 0

转载于:https://my.oschina.net/hava/blog/1552169

你可能感兴趣的文章
Java学习lesson 08
查看>>
MarkDown入门
查看>>
项目经理 与 敏捷开发
查看>>
安卓软件开发你知道需要学什么吗,看这里?
查看>>
必读的Python入门书籍,你都看过吗?(内有福利)
查看>>
alibaba.fastjson 乱序问题
查看>>
django 反向关联--blog.entry_set.all()查询
查看>>
网工之路
查看>>
linux 查看发行版本信息
查看>>
数据结构之二叉树遍历
查看>>
Linux rpm 命令参数使用详解[介绍和应用]
查看>>
tr的使用详解
查看>>
CentOS 6.4下PXE+Kickstart无人值守安装操作系统
查看>>
2.5 alias命令
查看>>
arp
查看>>
小博浅谈MVC
查看>>
前端技术学习之选择器(四)
查看>>
Ubuntu与windows的远程控制/远程桌面
查看>>
2016年4月4日中项作业
查看>>
ARP欺骗
查看>>