Go:函数、defer
一、函数可赋值给一个变量
示例1:
package main
import "fmt"
func add(a, b int) int {
	return a + b
}
func main() {
	xx := add
	fmt.Println(xx(10, 10)) // 20
}
示例2:
package main import "fmt" // opFunc为自定义的类型名字,这里它是一个函数,接收两个值,返回一个值
type opFunc func(int, int) int func add(a, b int) int {
return a + b
} // op为变量名字,op_func为自己定义的类型
func operator(op opFunc, a, b int) int {
return op(a, b)
} func main() {
xx := add
result := operator(xx, 10, 10)
fmt.Println(result) // 20
}
示例3:示例2也可以写成如下,示例2中为什么使用type自定义类型?这样可以让函数没那么繁琐,更简洁。
package main import "fmt" // opFunc为自定义的类型名字,这里它是一个函数,接收两个值,返回一个值
//type opFunc func(int, int) int func add(a, b int) int {
return a + b
} // op为变量名字,op_func为自己定义的类型
func operator(op func(int, int) int, a, b int) int {
return op(a, b)
} func main() {
xx := add
result := operator(xx, 10, 10)
fmt.Println(result) // 20
}
二、可变参数
// 0个或多个参数
func sumArgs(args …int) int {
}
// 1个或多个参数
func sumArgs(a int, args …int) int {
}
// 2个或多个参数
func sumArgs(a int, b int, args …int) int {
}
注意:其中args是一个slice,我们可以通过args[index]依次访问所有参数,通过len(args)来判断传递参数的个数。
示例:
package main
import "fmt"
func sumArgs(args ...int) int {
	sum := 0
	for i := range args {
		sum += args[i]
	}
	return sum
}
func main() {
	fmt.Println(sumArgs(1, 2, 3, 4, 5)) // 15
}
三、匿名函数
package main
import "fmt"
func add(a, b int) int {
	result := func(a1, b1 int) int {
		return a1 + b1
	}(a, b) // 定义时就调用
	return result
}
func main() {
	fmt.Println(add(10, 10)) // 20
}
或者:
package main
import "fmt"
func add(a, b int) int {
	result := func(a1, b1 int) int {
		return a1 + b1
	}
	return result(a, b)
}
func main() {
	fmt.Println(add(10, 10)) // 20
}
全局匿名函数:
package main import "fmt" var (
//Func就是一个全局匿名函数
Func = func(a, b int) int {
return a * b
}
) func main() {
result := Func(10, 10)
fmt.Println(result)
}
四、defer用途
- 当函数返回时,执行defer语句,因此,可以用来做资源清理;
 - 多个defer语句,按先进后出的方式执行;
 - defer语句中的变量,在defer声明时就决定了。
 
示例:
package main
import "fmt"
func test(a, b int) {
	defer fmt.Println(a)
	defer fmt.Println(b)
	tmp := a + b
	fmt.Println(tmp)
}
func main() {
	test(10, 20)
}
// 输出结果:
// 30
// 20
// 10
在 defer 将语句代码放入到栈时,也会将相关的值拷贝同时入栈:
package main
import "fmt"
func test(a, b int) {
	defer fmt.Println(a)
	defer fmt.Println(b)
	a++
	b++
	tmp := a + b
	fmt.Println(tmp)
}
func main() {
	test(10, 20)
}
// 输出结果:
// 32
// 20
// 10
defer的最主要价值是,当函数执行完毕后,可以及时的释放函数创建的资源(请看如下伪代码):
func test() {
	// 关闭文件资源
	file = openFile(文件名)
	defer file.close()
	// 其他代码
}
func test() {
	// 释放数据库支援
	conn = openDatabase()
	defer conn.close()
	// 其他代码
}
Go:函数、defer的更多相关文章
- Go 延迟函数 defer 详解
		
Go 延迟函数 defer 详解 Go 语言中延迟函数 defer 充当着 try...catch 的重任,使用起来也非常简便,然而在实际应用中,很多 gopher 并没有真正搞明白 defer.re ...
 - Golang入门教程(十三)延迟函数defer详解
		
前言 大家都知道go语言的defer功能很强大,对于资源管理非常方便,但是如果没用好,也会有陷阱哦.Go 语言中延迟函数 defer 充当着 try...catch 的重任,使用起来也非常简便,然而在 ...
 - GO语言延迟函数defer用法分析
		
这篇文章主要介绍了GO语言延迟函数defer用法,较为详细的分析了GO语言的特性与具体用法,并给出了一个比较典型的应用实例,具有一定的参考借鉴价值,需要的朋友可以参考下 本文实例讲述了GO语言延迟 ...
 - Go-延时函数defer
		
关于延时调用函数(Deferred Function Calls) 延时调用函数基本语法如下: defer func_name(param-list) {} 当一个函数前有关键字 defer ...
 - Golang错误处理函数defer、panic、recover、errors.New介绍
		
在默认情况下,当发生错误(panic)后,程序就会终止运行 如果发生错误后,可以捕获错误,并通知管理人员(邮件或者短信),程序还可以继续运行,这当然无可厚非 errors.New("错误信息 ...
 - GO学习笔记:函数defer
		
Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句.当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回.特别是当你在进行一些打开资源的操作时,遇 ...
 - go:defer
		
defer:延迟. 假设有调用函数A.被调用函数B,其关系如下: func A(){//调用函数 ... defer B()//被调用函数 ... return//B将延迟到return前执行 } * ...
 - Golang tips ----- 函数
		
1.在函数调用时,Golang没有默认参数值 2.一个函数声明如果没有函数体,表面该函数不是由Golang实现的,这样的声明定义了函数标识符 3.拥有函数名的函数只能在包级语法块中被声明 4.函数值( ...
 - go基础之--函数和map
		
在整理函数之前先整理一下关于指针 指针 普通类型变量存的就是值,也叫值类型.指针类型存的是地址,即指针的值是一个变量的地址.一个指针指示值所保存的位置,不是所有的值都有地址,但是所有的变量都有.使用指 ...
 - Golang中defer、return、返回值之间执行顺序的坑
		
原文链接:https://studygolang.com/articles/4809 Go语言中延迟函数defer充当着 cry...catch 的重任,使用起来也非常简便,然而在实际应用中,很多go ...
 
随机推荐
- kentico7中设置site的default page
			
在SiteManager中,Settings中,选择好站点,然后Content,Default alias path
 - hive使用
			
运行hadoop [root@hadoop0 ~]# start-all.sh 进入命令行[root@hadoop0 ~]# hive 查询昨天的表 hive> select * from st ...
 - html使用css让文字超出部分用省略号三个点显示的方法案例
			
html使用css让文字超出部分用省略号三个点显示的方法: 我正确使用的就是下面的代码,li里面是a标记.在IE和google中使用是正常的,火狐不知道,我也不在意,等你来测 li{ display: ...
 - Code First: 五大映射模式
			
映射一 Mapping the Table-Per-Hierarchy (TPH) Inheritance 模型文件 using System.Data.Entity; using System.Da ...
 - c#.net常用函数列表
			
.DateTime 数字型 System.DateTime currentTime=new System.DateTime(); 1.1 取当前年月日时分秒 currentTime=System.Da ...
 - bzoj 4809: 皇后【dfs】
			
爆搜卡线过 并不知道正解是啥 #include<iostream> #include<cstdio> using namespace std; const int N=40; ...
 - bzoj 3942: [Usaco2015 Feb]Censoring【kmp+栈】
			
好久没写kmp都不会写了-- 开两个栈,s存当前串,c存匹配位置 用t串在栈s上匹配,栈每次入栈一个原串字符,用t串匹配一下,如果栈s末尾匹配了t则弹栈 #include<iostream> ...
 - bzoj 2060: [Usaco2010 Nov]Visiting Cows 拜访奶牛【树形dp】
			
设f[u][0/1]为u这个点不选/选,转移的时候从儿子转移,f[u][1]=sum(f[son][0])+1,f[u][0]=sum(max(f[son][0],f[e[i].to][1])) #i ...
 - git merge合并时遇上refusing to merge unrelated histories的解决方案
			
如果git merge合并的时候出现refusing to merge unrelated histories的错误,原因是两个仓库不同而导致的,需要在后面加上--allow-unrelated-hi ...
 - while和for的内嵌
			
迭代,从初始情况按照规律不断求解中间情况,最终推导出结果.(折纸珠峰) 穷举:把所有情况都列举一遍,选择符合条件的选项(百鸡百钱) 循环四要素:初始条件,循环条件,循环体,状态改变. While的使用 ...