学习目标
- 记录自己的学习
- 重温自己的学习成果
defer
-
包含该defer语句的函数执行完毕时,defer后的函数才会被执行
-
四字:推迟调用
-
在一个函数中执行多条defer语句,它们的执行顺序和声明顺序相反(栈的缘故)
-
原理
- 推迟的函数调用会被压入一个
栈中。 - 当外层函数返回时,被推迟的函数会按照后进先出的顺序调用。
- 推迟的函数调用会被压入一个
-
defer、return、返回值的执行顺序
- return最先给返回值赋值
- defer开始执行一些收尾工作
- 若为有名返回值
a()(i int)则直接赋值,defer可以访问这个返回值 - 若为匿名返回值
b()int则先声明再赋值,defer访问的值来自于其他变量的赋值,修改的也是其他变量的值,defer无法直接访问到我们需要的返回值
- 若为有名返回值
- RET指令(返回指令前先检查是否存在defer语句)携带返回值退出函数
-
注意:
- defer声明时会先计算确定参数的值,defer推迟执行的仅是其函数体。
- 如time.Now(),虽然defer,但是实际上time.Now已经存起来了
- 作用域
-
defer 只对当前协程有效(main 可以看作是主协程)
-
当任意一条(主)协程发生 panic 时,会执行当前协程中 panic 之前已声明的 defer
-
在发生 panic 的协程中,如果没有一个 defer 调用
recover()进行恢复,则会在执行完最后一个已声明(已经入栈)的 defer 后,引发整个进程崩溃 -
主动调用 os.Exit(int) 退出进程时,defer 将不再被执行。
-
-
-
匿名函数:func(){语句}() 最后的括号很重要
结构体转map
-
json包的marshal,unmarshal
- 先将结构体序列化成
[]byte数组,再从[]byte数组序列化成结构体。 -
data, _ := json.Marshal(&user) m := make(map[string]interface{}) json.Unmarshal(data, &m) - 简单但是效率低
- 先将结构体序列化成
-
反射
- 使用反射将结构体转成
map的方法。通过标签(tag)和反射-
标签识别
- 使用
readTag方法读取域(field)的标签,如果没有标签,使用域的名字。然后读取tag中的选项。目前支持3个选项- '-':忽略当前这个域
- 'omitempty' : 当这个域的值为空,忽略这个域
- 'dive' : 递归地遍历这个结构体,将所有字段作为键
- 通过传入结构体反射,读tag,然后去遍历
- 使用
-
结构体的域(field)的遍历
- 遍历结构体的每一个与,然后通过swithc存值
-
内嵌结构体的转换
- 如果时检查有没有传入参数的方法,实现了调用这个方法
- 没有实现,递归调用StructToMap,根据是否展开(dive)把结果写入map中
-
- 使用反射将结构体转成