V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
suruiran
V2EX  ›  Go 编程语言

关于 Golang 加载动态库的调研报告

  •  
  •   suruiran · 41 天前 · 2506 次点击
    这是一个创建于 41 天前的主题,其中的信息可能已经有所发展或是发生改变。

    至少目前来说此路不通……

    对于 C 的了解仅限于 Hello World ,链接、符号什么的一无所知,所以其实一开始就是抗拒 CGO 的,打算的就是使用 UDS 来实现外部的数据库驱动。但是数据库驱动的 Rows 和 Tx 都是不可恢复对象,如果进程挂了,即使重启之后状态也都对应不上,此时只能强行关闭相关的 UI 。——这体验也太糟糕了。

    所以开始调研使用 CGO 来加载由 Go 编译的动态库。在 github 的 issues 里有一些关于这方面的讨论,都是说不可行。但是看到了 purego ,尝试之后发现真的可以工作! windows 和 linux 上都没有问题。实现方式是,仅暴露了 4 个函数,DllVersion, DllOpenObj, DllCallDllCancel,传递的参数都是 uintptr,且没有返回值。返回值的内存由主程序生成,当作参数传递,然后 Dll 里面使用 JSON 序列化后写入。——至少在 windows/linux 上这么做是可以的。虽然需要序列化,但是还是要比通过 UDS 来做要好。

    我没有 Mac 的设备,但是我觉得 linux 都没有问题,那应该也没事。

    我做好了 Dll 的加载和简单的管理,在准备发布前的测试时,我使用 quckemu 成功的运行了 MacOs 的虚拟机。却发现在 Mac 上不论是 purego 还是 plgin 都不能成功的运行由 Go 编译的动态库。purego 可能是 dll 内部的 Go Runtime 没有初始化,plugin 可能是数据库的驱动是依赖 CGO 的缘故。

    总之,我很失望,至少目前来说此路不通……

    UDS 又有状态不能同步的问题,所以只能取消外部数据库驱动这个功能,全部都打包到一起了……😓

    19 条回复    2025-07-29 00:09:29 +08:00
    assiadamo
        1
    assiadamo  
       41 天前
    不知道你的应用场景使用共享内存 shardmem 如何
    Sendya
        2
    Sendya  
       41 天前
    我这边是用 wasm 替代,但是仅作为插件的用法,替代一些固定阶段生命周期处理
    liaohongxing
        3
    liaohongxing  
       41 天前
    这块关注很久了,可以看下我收藏的这个库 https://github.com/JupiterRider/ffi , 也是 purego 的一个扩展优化
    liaohongxing
        4
    liaohongxing  
       41 天前
    用 libffi 调用 dll 或 so 库比较靠谱
    crackidz
        5
    crackidz  
       41 天前
    purego 主要是用于跨语言调用一些库用的,比如说 std library ,一些其他现成的 C 库。
    suruiran
        6
    suruiran  
    OP
       41 天前
    @liaohongxing 我感觉都差不多,主要是 go 的 dll 里面还有个运行时。……我暂时不想再尝试了。
    ExplodingFKL
        7
    ExplodingFKL  
       41 天前
    我倒是喜欢 hashicorp 这种使用 rpc 来做插件化的 ... 比单进程模型要优雅点 (?

    https://github.com/hashicorp/go-plugin
    suruiran
        8
    suruiran  
    OP
       41 天前
    @ExplodingFKL 这就 UDS 呀。我做的是一个通用的桌面端数据库管理应用。Rows 跟 Tx 这些重启之后没办法恢复呀……这时候 UI 怎么办?
    lysShub
        9
    lysShub  
       41 天前
    你这帖子没前没后的,没有个上下文啊?

    1. “但是数据库驱动的 Rows 和 Tx 都是不可恢复对象,如果进程挂了,即使重启之后状态也都对应不上,此时只能强行关闭相关的 UI 。——这体验也太糟糕了” : 纯属多虑了,不要钻牛角尖

    2. “所以开始调研使用 CGO 来加载由 Go 编译的动态库”:既然两个都是 go 写的,为啥不合在一起 ?

    3. “Mac 上不论是 purego 还是 plgin 都不能成功的运行由 Go 编译的动态库”:最新版本,这两个的文档里都有提到支持 mac 的;多半是你虚拟机问题,搞 cgo 就不要跨平台编译了,更不要用什么虚拟机
    iceheart
        10
    iceheart  
       40 天前 via Android
    把插件功能单跑一个进程,用 grpc 调用不行么?
    Silicon
        11
    Silicon  
       40 天前
    为什么是「调研使用 CGO 来加载由 Go 编译的动态库」而不是直接使用 https://pkg.go.dev/plugin ,从你的描述中我好像没看到和这个能力冲突的需求
    Silicon
        12
    Silicon  
       40 天前
    哦你要支持 windows……那么 go plugin 不行。
    purego 显然也不可以,这里不只是没有 runtime 的问题,还有当两个 runtime 在同一个进程里存活时是不是有打架的风险,我不好说,我觉得至少协程调度的时候如果双方互相不认得对方,可能会有很微妙的问题。
    suruiran
        13
    suruiran  
    OP
       40 天前
    @Silicon 就算是 plugin ,也不能有 CGO……
    bli22ard
        14
    bli22ard  
       40 天前
    没看明白,你想表达什么
    hez2010
        15
    hez2010  
       39 天前
    一个进程内无法加载多个 go 的 runtime ,参考官方仓库的 issue: https://github.com/golang/go/issues/50304#issuecomment-999302888
    并且他们也没有计划修复。
    suruiran
        16
    suruiran  
    OP
       39 天前
    @hez2010 是的,但是用 purego 尝试成功了,就以为至少这种使用方式可能是可以的……没想到再 Mac 上不行。
    hez2010
        17
    hez2010  
       39 天前
    @suruiran Go runtime 的特性其实也决定了 Go 不适合用来做动态链接库。如果一定要做动态链接库的话,建议更换其他语言,比如 C/C++/Rust ,又或者 C# 走 NativeAOT 编译出 native dll ,这些都是没问题的,并且同一个进程多 dll 共存也没有问题。
    sssxyd
        18
    sssxyd  
       38 天前
    go 加载动态库的话,动态库是什么语言写的并没有区别,没理由 mac 上不行;
    我本来也考虑过加载动态库作为插件的方案,不过无法控制权限,改用 wasm ;
    你可以考虑一下 wasmtime-go, 公共 wasmtime 这个 rust 编写的 wasm runtime ,运行 wasm ;
    wasm 应该不会有适配问题
    PungentSauce
        19
    PungentSauce  
       38 天前
    用 grpc 也行的吧。 或者一些动态加载的脚本 ,traefik 的插件是用脚本的方式
    关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   957 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 21:30 · PVG 05:30 · LAX 14:30 · JFK 17:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.