1
iBugOne 2022-04-19 20:56:56 +08:00 via Android 4
我怀疑楼主不懂编译语言和解释执行语言的区别
|
2
westoy 2022-04-19 20:59:56 +08:00
走 cgo 绕一遍 dlopen?
|
3
seakingii 2022-04-19 21:04:42 +08:00
可以在你的程序里内置一个脚本引擎,比如 lua
|
4
mengzhuo 2022-04-19 21:50:32 +08:00
呃……你需要的是恢复“执行栈”?还是仅仅是持久化执行的结果?
不过 python 也不能恢复执行栈吧,所以我怀疑你只是想把当前的执行结果存档一下,可以用 gob (类似 pickle ) 倒是要我设计能 resume status 的话……Go 没办法强制指定 pc 和符号表,要恢复“执行栈”,需要在所有函数出入口记录好参数状态(“表”驱动),函数版本,执行环境变量,通过 offset 指定恢复,应该可以(发现了什么奇怪的用途) |
5
gabon 2022-04-19 21:52:26 +08:00 via iPhone
内置一个编译器,然后启动个子进程。
|
7
GeruzoniAnsasu 2022-04-20 00:00:52 +08:00
@mengzhuo 不可能的,还会有 goroutine 和 GC 的问题
---- OP 换个思路: 在静态语言中,所有函数都是「已持久化」的、嵌在程序中的。借助反射,函数的地址可以通过函数名查到,所以执行体存个名字就好了 job 的另一个组成部分是参数,而保存参数还是比较简单的,毕竟有反射,如果你想,可以把 runtime 对象整个扫描一遍再用反射造回来 |
8
Vegetable 2022-04-20 00:28:37 +08:00
想实现动态脚本?
用 build 代替你的__import__这种思路试试呗 |
9
chaleaochexist OP @mengzhuo 都不是
上下文不需要保存。 我从 redis 里面把函数名和函数参数读取出来然后执行。 大概是这个意思。 python 可以通过保存"module_name.func_name" 然后 ```python func = __import__("module_name.func_name") func() ``` 这样执行。 pickle 也可以,虽然我没试过 但是我觉得 gob 应该也可以。 但是把函数序列化,在反序列化, 应该没人这么干吧。 目前的想法是在 main 启动的时候 配一个 map 将函数名和函数映射起来。 至于参数, 可以用我楼上说的反射实现。 谢谢大佬。 |
10
chaleaochexist OP @GeruzoniAnsasu #7 大佬说的反射是泛指还是特指 Go 的反射。 因为我没想明白 在 go 语言中如何通过函数名查找到函数的地址。 如果能实现的话, 那我的问题其实差不多就解决了。
谢谢大佬。 |
11
learningman 2022-04-20 00:54:42 +08:00
go 的话,你已有的这个想法应该是唯一解了。。。顶多说写个 codegen 不用手动维护 map
|
12
learningman 2022-04-20 00:55:59 +08:00
可以 reflect.ValueOf(func).Call(params)这么整,但是还是要初始化
|
13
275761919 2022-04-20 09:30:32 +08:00 2
可以试试 yaegi ,github.com/traefik/yaegi ,感觉你说的是这个
|
14
GeruzoniAnsasu 2022-04-20 09:53:55 +08:00 1
@chaleaochexist
我之前的想法是: 当你要定义一个新 Job 的时候: Schedule(Callback,time) Callback 必然已经是一个静态的函数了,而要持久化,callback 又不能是闭包。那么比如要求 Callback 写成固定名 struct 的 method ,类似这样: https://go.dev/play/p/cUw99-T55v8 然后又想能不能根据类型信息反射出一个类实例,然后类实例包含一个重写掉的 Run method ,这样函数名就是固定的了,而且定义 Job 的方式能更灵活。 问题集中在怎么得到这个有类型的实例上—— 然而研究了大概 6 个小时之后我发现 1. reflect.Type 也是一个接口,意味着就算把类型信息 dump 出来了,我也没法轻易构造出一个实例化的 Type 2. reflect.rtype 是 reflect.Type 接口最重要的实现,这个结构是有办法 dump 的( unsafe pointer 读),但不能存在覆写一个现存 reflect.rtype 的办法。 通过反射写这个结构会被 reflect.Value.SetXXX 的实现拒绝(有 flag 阻止写回去);而直接得到这个结构的 unsafepointer 尝试给它赋值会触发访问违例,原因不明。由于我也没用更 low level 的调试器去调( goland 而已),所以我也不知道是赋值语义还是类型转换语义的问题 3. 不像 C/++ 有函数地址就可以强制转换出一个函数; golang 是无论如何都先得有 reflect.Type 的(光有地址没有用)。由于 2 ,reflect.Type 不能自由构造,因此在语言范围内能想到的 tricky way 都堵死了。 有点蛋疼,前几天才有其他人说 golang 动态性差,确实是不得不承认的 |
15
chaleaochexist OP |
16
learningman 2022-04-20 10:27:44 +08:00 1
@chaleaochexist 对,所以我说要初始化,但是应该可以用 codegen 来弄
|