defer 的执行顺序
答案- 多个 defer 语句,遵从后进先出(Last In First Out,LIFO)的原则,最后声明的 defer 语句,最先得到执行。
- defer 在 return 语句之后执行,但在函数退出之前,defer 可以修改返回值。
例如:
1 |
func test() int { |
这个例子中,可以看到 defer 的执行顺序:后进先出。但是返回值并没有被修改,这是由于 Go 的返回机制决定的,执行 return 语句后,Go 会创建一个临时变量保存返回值,因此,defer 语句修改了局部变量 i,并没有修改返回值。那如果是有名的返回值呢?
1 |
func test() (i int) { |
这个例子中,返回值被修改了。对于有名返回值的函数,执行 return 语句时,并不会再创建临时变量保存,因此,defer 语句修改了 i,即对返回值产生了影响
再看下面一个题
import "fmt" var name string = "go" func myfunc() string { defer func() { name = "python" }() fmt.Printf("myfunc 函数里的name:%s\n", name) return name } func main() { myname := myfunc() fmt.Printf("main 函数里的name: %s\n", name) fmt.Println("main 函数里的myname: ", myname) }
输出如下
myfunc 函数里的name:go main 函数里的name: python main 函数里的myname: go
Q11 如何交换 2 个变量的值?
答案Q12 Go 语言 tag 的用处?
答案Q13 如何判断 2 个字符串切片(slice) 是相等的?
答案Q14 字符串打印时,%v
和 %+v
的区别
答案
Q15 Go 语言中如何表示枚举值(enums)
答案Q16 空 struct{} 的用途
答案专题: Go 语言面试题
本文发表于 2020-09-04,最后修改于 2022-02-25。
本站永久域名「 geektutu.com 」,也可搜索「 极客兔兔 」找到我。
上一篇 « Go 语言笔试面试题汇总下一篇 » Go 语言笔试面试题(实现原理)
赞赏支持推荐阅读
Go2 新特性简明教程发表于2019-08-15, 阅读约17分钟
TensorFlow 2 中文文档 - 过拟合与欠拟合发表于2019-07-12, 阅读约19分钟
Pandas 数据处理(三) - Cheat Sheet 中文版发表于2019-06-16, 阅读约4分钟
#关于我 (9) #Go (48) #百宝箱 (2) #Cheat Sheet (1) #Go语言高性能编程 (20) #友链 (1) #Pandas (3) #机器学习 (9) #Python (10) #Rust (1) #TensorFlow (9) #mnist (5) #强化学习 (3) #OpenAI gym (4) #DQN (1) #Q-Learning (1) #CNN (1) #TensorFlow 2 (10) #官方文档 (10) 6 条评论 未登录用户 lisgroup发表于超过 1 年前新手有两个问题想请教下:
1. Q7 什么是 rune 类型
代码中 []rune("Go语言")
意思是使用 rune
强制转换类型是吧?
2. Q13 如何判断 2 个字符串切片(slice) 是相等的?
其中代码块中的第10行
b = b[:len(a)]
这么操作的目的是什么?保证数组切片一样长吗?
geektutu发表于超过 1 年前第一个问题,你的理解是对的,字符串类型转换为 rune 切片类型。
第二个问题,这种写法是为了优化边界检查从而提升运行时效率的。在go语言中称之为 Bounds Check Elimination
,简称为 BCE。简言解释下,如果没有这一句,在运行时,Go 语言每次都会对 b[i] 做边界检查,看看是否越界了,如果越界了,就 panic。但是如果加上这一句,Go语言在编译时,能够做一些简单的静态分析,发现 b[i] 是不可能越界的,编译时就能将没必要的边界检查给优化了,那么运行时,就不会对 b[i] 做边界检查,从而提升运行时效率。
这篇文章提供了更多的示例,帮助理解。Bounds Check Elimination - go101.org
givetimetolife发表于超过 1 年前_ = b[:len(a)]
geektutu发表于超过 1 年前@givetimetolife 我觉得这种写法应该也是OK的,Go 的切片底层对应的数组是一样的,切片只是改变指针的位置,这一步检查几乎是没有损耗的。
zzhaolei发表于大约 1 年前2. Q13 如何判断 2 个字符串切片(slice) 是相等的?
针对这个中的b = b[:len(a)]
,使用go 1.15.6
编译,已经没有效果了,在len判断
的时候就已经做了优化
@zzhaolei 感谢指出问题,新版本将 b = b[:len(a)]
去掉后,也不会产生边界检查(Bounds Check)了。
是否产生边界检查,可以用下面的命令验证。
go build -gcflags="-d=ssa/check_bce/debug=1" main.go
例如针对下面的例子,如果 s[2] 没有越界,那么 s[1] 和 s[0] 肯定是合法,因此只需要对 s[2] 做一次边界检查即可:
package main func f(s []int) { _ = s[2] _ = s[1] _ = s[0] } func main() {}
go build -gcflags="-d=ssa/check_bce/debug=1" main.go # command-line-arguments ./main.go:4:7: Found IsInBounds
动手写分布式缓存 - GeeCache第五天 分布式节点
61 评论 ● 1月前
yinhuanyi —— 博主,Group的getFromPeer方法返回的ByteView必须是指针,好像写错了 ``` func (g *Group) getFromPeer(peer PeerGetter, key string) (*ByteView, error) { bytes, err := peer.Get(g.name, key) if err != nil { return &ByteView{}, err } return &ByteView{b: bytes}, nil } ```