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 ...
随机推荐
- Recyclerview 顶部悬停 stick
activity布局 ll_top代表要悬停的部分 这里面我放了 图片和文本 1 <?xml version="1.0" encoding="utf-8&qu ...
- SYSUCPC2017 1007 Tutu’s Array II
题目大意:有A个0和B个1,每次取两个出来进行{XNOR,NAND,NOR}操作生成一个新的0/1,直到只剩一个元素.问最后是否可能剩下一个0,是否可能剩下一个1. XNOR 比较特殊 a XNOR ...
- "Hello world" of ML
#!/usr/bin/python import os import pandas as pd from sklearn.datasets import fetch_openml import mat ...
- 关于file文件操作的头文件 【LINUX】 (转载)
转自:http://blog.csdn.net/figo77ll/article/details/3156052 Linux下如果要对文件进行读取访问,需要包含至少以下两个头文件: #inlcude ...
- IDEA Artifacts问题
如果你使用的IDEA并且无论如何都ClassNotFound异常的话,可以看看其中一种可能的解决方案 第一步:打开Project Struture-->Modules-->点击项目--&g ...
- 源码阅读之LinkedList(JDK8)
inkedList概述 LinkedList是List和Deque接口的双向链表的实现.实现了所有可选列表操作,并允许包括null值. LinkedList既然是通过双向链表去实现的,那么它可以被当作 ...
- [LOJ#10132]异象石
Description Adera 是 Microsoft 应用商店中的一款解谜游戏. 异象石是进入 Adera 中异时空的引导物,在 Adera 的异时空中有一张地图.这张地图上 有 N 个点,有 ...
- 图论 HDOJ 5348 MZL's endless loop
题目传送门 /* 题意:给一个n个点,m条边的无向图,要求给m条边定方向,使得每个定点的出入度之差的绝对值小于等于1. 输出任意一种结果 图论:一个图,必定存在偶数个奇度顶点.那么从一个奇度定点深搜, ...
- 理解 CSS 布局和块级格式上下文
前言 BFC 的概念始于 CSS2,是个蛮古老的 CSS 话题了,网上也到处能搜到 BFC 的介绍,但是都不够简洁.本文系翻译自 Rachel Andrew 女士的博文 Understanding C ...
- Debug技巧(1)
首先声明,以下有些是自己遇到的问题自己解决了,其它里面包括了网上看到的Debug经验和书里看到的经验,时间问题就不一一说明,如有侵权,私信我进行删除,我会道歉.我写这个的本意是记录我学习中遇到的问题, ...