一、函数可赋值给一个变量

示例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的更多相关文章

  1. Go 延迟函数 defer 详解

    Go 延迟函数 defer 详解 Go 语言中延迟函数 defer 充当着 try...catch 的重任,使用起来也非常简便,然而在实际应用中,很多 gopher 并没有真正搞明白 defer.re ...

  2. Golang入门教程(十三)延迟函数defer详解

    前言 大家都知道go语言的defer功能很强大,对于资源管理非常方便,但是如果没用好,也会有陷阱哦.Go 语言中延迟函数 defer 充当着 try...catch 的重任,使用起来也非常简便,然而在 ...

  3. GO语言延迟函数defer用法分析

    这篇文章主要介绍了GO语言延迟函数defer用法,较为详细的分析了GO语言的特性与具体用法,并给出了一个比较典型的应用实例,具有一定的参考借鉴价值,需要的朋友可以参考下   本文实例讲述了GO语言延迟 ...

  4. Go-延时函数defer

    关于延时调用函数(Deferred Function Calls)      延时调用函数基本语法如下: defer func_name(param-list) {} 当一个函数前有关键字 defer ...

  5. Golang错误处理函数defer、panic、recover、errors.New介绍

    在默认情况下,当发生错误(panic)后,程序就会终止运行 如果发生错误后,可以捕获错误,并通知管理人员(邮件或者短信),程序还可以继续运行,这当然无可厚非 errors.New("错误信息 ...

  6. GO学习笔记:函数defer

    Go语言中有种不错的设计,即延迟(defer)语句,你可以在函数中添加多个defer语句.当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回.特别是当你在进行一些打开资源的操作时,遇 ...

  7. go:defer

    defer:延迟. 假设有调用函数A.被调用函数B,其关系如下: func A(){//调用函数 ... defer B()//被调用函数 ... return//B将延迟到return前执行 } * ...

  8. Golang tips ----- 函数

    1.在函数调用时,Golang没有默认参数值 2.一个函数声明如果没有函数体,表面该函数不是由Golang实现的,这样的声明定义了函数标识符 3.拥有函数名的函数只能在包级语法块中被声明 4.函数值( ...

  9. go基础之--函数和map

    在整理函数之前先整理一下关于指针 指针 普通类型变量存的就是值,也叫值类型.指针类型存的是地址,即指针的值是一个变量的地址.一个指针指示值所保存的位置,不是所有的值都有地址,但是所有的变量都有.使用指 ...

  10. Golang中defer、return、返回值之间执行顺序的坑

    原文链接:https://studygolang.com/articles/4809 Go语言中延迟函数defer充当着 cry...catch 的重任,使用起来也非常简便,然而在实际应用中,很多go ...

随机推荐

  1. linux下的C语言开发(静态库/动态库)

    动态链接库不是Linux独有的特性,在windows下面也存在这样的特性.一般来说,windows下面的动态连接库是以*.dll作为结尾的,而linux下面的动态连接库是以*.so结尾的.和静态链接库 ...

  2. Python 返回多个值+Lambda的使用

    def MaxMin(a,b): if(a>b): return a,b else: return b,a max,min=MaxMin(8,95) print "最大值为:" ...

  3. 深入浅出Android makefile(1)--初探(转载)

    转载:http://nfer-zhuang.iteye.com/blog/1752368 一.说明 android build system是一个非常庞大的系统,要编译Android工程.修改或新增A ...

  4. 关于Jedis无法连接上Linux上Redis问题

    环境:CentOS7.Redis 主要解决Jedis客户端无法连接Linux上Redis服务问题 1.修改Redis目录下的redis.conf配置文件 注释掉bind本地回环地址:bind 127. ...

  5. SQL Server触发器创建、删除、修改、查看示例步骤

    一﹕ 触发器是一种特殊的存储过程﹐它不能被显式地调用﹐而是在往表中插入记录﹑更新记录或者删除记录时被自动地激活.所以触发器可以用来实现对表实施复杂的完整性约`束. 二﹕ SQL Server为每个触发 ...

  6. SeasLog的日志

    https://github.com/Neeke/SeasLog/blob/master/README_zh.md 中文文档地址, 这是一个很好用的记录日志扩展,可以用于项目之中

  7. nginx+thinkPhp配置虚拟主机和伪静态规则重写

    /usr/local/nginx/conf/nginx.conf 进行配置 server    {        listen 80 default_server;        #listen [: ...

  8. daily_journal_3 the game of thrones

    昨晚追完了最爱的美剧(the game of thrones),哇,看到结局有点崩溃.果然还是美帝淫民开放,各种乱伦,在七夕收到的万点暴击就祝天下有情人就像剧中一样终是血亲. 昨天算是完成了git的复 ...

  9. 题解报告:hdu 3501 Calculation 2 (欧拉函数的扩展)

    Description Given a positive integer N, your task is to calculate the sum of the positive integers l ...

  10. SpringMVC实现Action的两种方式以及与Struts2的区别

    4.程序员写的Action可采用哪两种方式? 第一.实现Controller接口第二.继承自AbstractCommandController接口 5.springmvc与struts2的区别? 第一 ...