Golang断言与闭包使用解析

Golang断言与闭包使用解析

目录

1. Go断言的使用

2. 闭包的解读

2.1 指针传递

2.2 延迟绑定

2.3 Go Routine的延迟绑定

1. Go断言的使用

Go中的断言用于判断变量的类型,其使用形式如下所示:

value, ok := x.(T)

上面的代码是判断x是否为T类型的变量:

如果 T 的某个具体的类型,断言会检查 x 是否为该类型,如果是的话买就返回 x 以及一个布尔值true,反之返回一个false

如果 T 是接口类型,类型断言会检查 x 的动态类型是否满足 T。如果检查成功,返回值是一个类型为 T 的接口值,以及一个布尔值true,反之返回一个false

我们也可以不接受返回的布尔值,在这种情况下,如果断言失败,会直接panic,所以非常不推荐这种处理方式

另外,断言和可以与switch配合使用

switch a.(type) { case int: fmt.Println("the type of a is int") case string: fmt.Println("the type of a is string") case float64: fmt.Println("the type of a is float") default: fmt.Println("unknown type") } 2. 闭包的解读

闭包是由函数和与其相关的引用环境组合而成的实体。

概念上说起来有些抽象,下面我们以一个具体的例子来理解。

func foo1(x int) func() { return func() { x = x + 1 fmt.Printf("foo2 val = %d\n", x) } } f1 := foo1(1) f1() // 2 f1() // 3

在上面的例子中,f1() 与他的变量x(值为1)共同组成了一个闭包,每次调用f1(),x的值就会+1并且打印。

从某种意义上来说,闭包延长了变量的生命周期(栈上分配改为了堆上分配)。

2.1 指针传递 func foo2(x *int) func() { return func() { *x = *x + 1 fmt.Printf("foo2 val = %d\n", *x) } } x := 1 f1 := foo2(&x) f2 := foo2(&x) f1() // 2 f2() // 3

通过第一个例子,我们知道,函数以及其环境(传入的变量)组成了闭包,这个时候,如果传入的是一个指针,那么就会存在多个闭包共用一个变量的情况。

2.2 延迟绑定

闭包的延迟绑定,通俗地说,就是闭包的函数在第一次调用的时候才会与环境的变量进行绑定,我们依然以上面提到的两个函数为例子:

func foo1(x int) func() { return func() { x = x + 1 fmt.Printf("foo2 val = %d\n", x) } } func foo2(x *int) func() { return func() { *x = *x + 1 fmt.Printf("foo2 val = %d\n", *x) } } x := 1 f1 := foo1(x) f2 := foo2(&x) f2() // 2 f1() // 3

我们创建了f1与f2两个闭包函数,以及变量 x 的值为1

在f1与f2创建的时候,变量并没有与函数绑定

第一次调用f2()时,&x与其绑定,x的值+1,变为2

第一次调用f1()时,x与其绑定,这时x已经变为2了,再+1,所以变为3

2.3 Go Routine的延迟绑定

我们在一个函数中启动 Go Routine 调用另一个函数:

func show(v interface{}) { fmt.Printf("foo4 val = %v\n", v) } func foo4() { values := []int{1, 2, 3, 5} for _, val := range values { go show(val) } } ​ foo4() //foo3 val = 2 //foo3 val = 3 //foo3 val = 1 //foo3 val = 5

因为Go Routine的执行顺序是随机并行的,因此执行多次foo4()输出的顺序不一行相同,但是一定打印了“1,2,3,5”各个元素。

但是,如果我们以匿名函数的形式尝试复现上面的逻辑,会发现:

func foo5() { values := []int{1, 2, 3, 5} for _, val := range values { go func() { fmt.Printf("foo5 val = %v\n", val) }() } } foo5() //foo3 val = 5 //foo3 val = 5 //foo3 val = 5 //foo3 val = 5

其实这个问题的本质同闭包的延迟绑定,或者说,这段匿名函数的对象就是闭包。在我们调用go func() { xxx }()的时候,只要没有真正开始执行这段代码,那它还只是一段函数声明。而在这段匿名函数被执行的时候,才是内部变量寻找真正赋值的时候。for-loop的遍历几乎是“瞬时”完成的,4个Go Routine真正被执行在其后,所以会产生上面的情况。

到此这篇关于Golang 断言与闭包使用解析的文章就介绍到这了,更多相关Go 断言与闭包内容请搜索易知道(ezd.cc)以前的文章或继续浏览下面的相关文章希望大家以后多多支持易知道(ezd.cc)!

推荐阅读

    golang代理怎么设置

    golang代理怎么设置,代理,请求,设置,语言,客户端,应用程序,Go语言(或称Golang)是一种广受欢迎的编程语言,尤其适用于网络编程。在创建Web应用程序

    闭包是什么

    闭包是什么,闭包,函数,引用,变量,语言,运行,闭包是什么?计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),

    什么是golang

    什么是golang,语言,执行,编程语言,机器语言,高级语言,运行,golang是一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言;它可以在不损

    Python中的闭包详解

    Python中的闭包详解,函数,闭包,状态,参数,事件,变量,Python中的闭包是一种高级特性,它可以让我们更加灵活地使用函数。在这篇文章中,我们将详细介

    Golang之wait.Until 简单测试用例

    Golang之wait.Until 简单测试用例,结束,主程序,测试目的,验证wait.Until的用法 //测试wait.Until() 的用途package mainimport ( "fmt

    函数本质、闭包函数

    函数本质、闭包函数,函数,名字,python三大神器,装饰器,迭代器,生成器time模块------时间模块print(time.time())时间戳----------->这个时间

    使用Golang实现简单Ping过程

    使用Golang实现简单Ping过程,报文,字节,摘要: Ping的基本原理是发送和接受ICMP请求回显报文,利用Go语言可以轻松实现这一过程,较之C/C++语言

    关于lua的闭包(Closure)和Upvalue

    关于lua的闭包(Closure)和Upvalue,函数,变量, 关于lua的闭包(Closure)和Upvalue upvalue:嵌套函数的外部函数的局部变量 function func(a) <=

    Java是否需要闭包?

    Java是否需要闭包?,Java是否需要闭包?,闭包,支持,我想,不出,Does Java need closures?最近,我一直在阅读有关下一版Java可能支持闭包的内容。

    JS的闭包与定时器

    JS的闭包与定时器,的,闭包,与,定时器,什么,是,闭包,有,作用,,  什么是闭包?有什么作用  闭包就是能够读取其他函数内部变量的函数。 

    golang二进制读写文件-二进制文件

    golang二进制读写文件-二进制文件有些时候,我突然想知道MySQL的如何存储数据的.她是如何完整的获取某行的数据,并且获得每个字段的值.比如,我