作者简介:C/C++ 、Golang 领域耕耘者,创作者
个人主页:作者主页
专栏地址:go语言专栏
算法题专栏:刷题专栏
如果感觉博主的文章还不错的话,还请关注➕ 、点赞👍 、收藏🧡三连支持一下博主哦~~~
因为cgo 需要用到gcc,而gcc 在windows平台上支持不是很好,这里直接在linux 平台演示
假设在go中加一个c代码的注释,图中的sum函数
假如在项目中有一个很复杂的c代码,在go中不好复现,现在需要用go去调用它

在goland中出现下图这样的颜色说明调用就正确了

go tool cgo main.go (用命令看cgo底层做了什么)运行上面命令之后就生成了一个obj文件夹

在main.cgo1.go 文件中,是这样的代码

cgo_gotypes.go 文件中

通过上面两个文件,根据func_sum函数可知,跳转到main.cgo2.c文件中

在上面就是c代码,在c中申请了两个入参,一个出参, 上面的代码就是用的c语言中的栈(这里就跳出go中的内存管理了)
原理步骤归纳:
最终的过程也需要runtime 中的一些配合(也就是go中的配合)
从前面的文章可知,在go中M(系统级线程)和G(go的协程)的关系如图:

那调度器在cgo程序过程中做了什么呢,大致做了以下工作:
在go中调用cgo程序时,当中涉及到了协程栈的切换,切换后,有以下两点需要知道

可以输入这条命令查看: go build -gcflags -S main.go


实际上,执行了runtime包里面的函数
实际上,在go官方源码中,defer 在功能上有两种思路
1.12 之前使用
在堆上开辟一个sched.deferpool ,遇到defer 语句,将信息放入deferpool,函数返回时,从deferpoll取出执行(deferpoll数据结构在p结构体中)
上面两个思路其实都是差不多的(都是上面思路中第一种方法)
1.14 之后出现

panic 之后,不光当前的协程会退,而且会带崩启动它的协程,最后会退到这个主协程崩。所以两个打印都不会打印
panic 在程序中的调用流程:

执行结果:
程序解释:

如果在上述代码中增加红色框框中的代码,主协程就不会被触发的panic 带崩溃了
在go 的源码中,有这样一段代码:

在panic.go 中,如果有recover的话,就不会带崩上一级协程
原理:
见代码:


场景1: 在println 中就用到了反射判断类型在打印出来的
场景2: 见代码
package main
import (
"fmt"
"reflect"
)
func Add(a int, b int) int {
return a + b
}
func Sub(a int, b int) int {
return a - b
}
func CallFunc(f func(a int, b int) int) {
v := reflect.ValueOf(f)
if v.Kind() != reflect.Func {
return
}
argv := make([]reflect.Value, 2)
argv[0] = reflect.ValueOf(1)
argv[1] = reflect.ValueOf(2)
re := v.Call(argv)
fmt.Println(re[0].Int())
}
func main() {
CallFunc(Add)
CallFunc(Sub)
}
如果觉得对你有帮助的话:
👍 点赞,你的认可是我创作的动力!
🧡 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富!