Go语言其他高级特性
如何实现Go语言调用C代码
defer的底层原理
思路
- 思路:协程记录defer信息,函数退出时调用。
- 思路:将defer代码直接编译进函数尾部。
思路一:堆上分配
- 1.12之前使用
- 在堆上开辟一个sched.deferpool
- 遇到defer语句,将信息放入deferpool
- 函数返回时,从deferpool取出执行
recover如何在panic中拯救程序
func main() {
go func() {
panic("")
fmt.Println("end g")
}()
time.Sleep(time.Second)
fmt.Println("end main")
}
运行结果
panic:
goroutine 6 [running]:
main.main.func1()
D:/GoProject/Go_implement_Redis/practice/10.3.go:10 +0x27
created by main.main
D:/GoProject/Go_implement_Redis/practice/10.3.go:9 +0x25
Process finished with the exit code 2
- panic会抛出错误
- 终止协程运行
- 如果不处理,会带崩整个go程序
panic + defer
func main() {
defer fmt.Println("main g")
go func() {
defer fmt.Println("defer g")
panic("")
fmt.Println("end g")
}()
time.Sleep(time.Second)
fmt.Println("end main")
}
运行结果
defer g
panic:
goroutine 19 [running]:
main.main.func1()
D:/GoProject/Go_implement_Redis/practice/10.3.go:12 +0x73
created by main.main
D:/GoProject/Go_implement_Redis/practice/10.3.go:10 +0x77
Process finished with the exit code 2
- panic在退出协程前会执行所有已注册的defer
- 不会执行其他协程的defer
panic+defer+recover
func main() {
defer fmt.Println("main g")
go func() {
defer func() {
recover()
}()
panic("")
fmt.Println("end g")
}()
time.Sleep(time.Second)
fmt.Println("end main")
}
运行结果
end main
main g
- 在defer中执行recover,可以拯救panic的协程。
- 如果涉及recover,defer会使用堆上分配(deferpool)
- 如果遇到panic,panic会从deferpool取出defer语句,执行
- defer中调用recover,可以终止panic的过程。
Go是怎么实现反射的?
需求
- 获取对象的类型
- 对任意类型变量赋值
- 调用任意方法
元数据
- 元数据就是“数据的数据”或者说 数据的属性。
- 把对象的类型表示成一个数据类型
- 把对象的值表示成一个数据类型
对象的类型
- 接口reflect.Type
- 把对象的类型表示成一个接口
- 就能对类型做各种操作
对象的值
- 结构体reflect.Value
- 把对象的值表示成一个结构体
- 就能对值做各种操作
type 葛诗颖 struct {
name string
age int
}
func main() {
var girl = 葛诗颖{name: "诗诗", age: 23}
fmt.Println(reflect.TypeOf(girl))
fmt.Println(reflect.ValueOf(girl))
}
运行结果
main.葛诗颖
{诗诗 23}
实战:使用反射调用方法
func BrushTeeth(name string) string {
return name + "在刷牙"
}
func PlayFootball(name string) string {
return name + "在踢足球"
}
func CallAdd(f func(s string) string) {
v := reflect.ValueOf(f)
if v.Kind() != reflect.Func {
return
}
argv := make([]reflect.Value, 1)
argv[0] = reflect.ValueOf("葛诗颖")
reslut := v.Call(argv)
fmt.Println(reslut[0].String())
}
func main() {
CallAdd(BrushTeeth)
CallAdd(PlayFootball)
}
运行结果
葛诗颖在刷牙
葛诗颖在踢足球
Process finished with the exit code 0