Golang进阶指南:下一步该学什么
Golang进阶指南:下一步该学什么 入门
这段文字已通过翻译器翻译 https://translate.yandex.ru/?clid=2270456&win=320
如果遇到错误,那不是我))——这是翻译器的问题。
据说 Golang 开发者会分享他们的想法。让我畅想一下我希望在语言中看到什么。所有这些都很容易想到,并且显而易见。
我知道插件(https://golang.org/pkg/plugin/#pkg-overview),但这已经不是新鲜事物了。
我希望在 Golang 语言中拥有类似 DLL 的东西。但 DLL 技术是针对 C++ 的,而且它不方便、不时尚,就像消化了的猛犸象食物一样古老。
Golang 需要一些新的酷技术 DLM!!!DLM – 动态链接模块。
第一步
目录:c:\mygoproject\client5\
文件:Discount_customer.GODLM
func calculate_discount() int {
// 函数名称永不改变
// 复杂的算法是什么
//
return 6 // 算法经常改变
}
编译并得到:Discount_customer.DLM – 二进制代码。
文件:start.go
package main
import ("fmt"
"dlm"
)
func main() {
MyModule := dlm.LoadDLM_file("Discount_customer.DLM")
discount := MyModule.calculate_discount()
fmt.Println("discount =", discount)
}
编译并得到 start.exe
这很简单。就像 DLL 一样。
第二步
func main() {
// …
address_module_in_database = "discount_calculation"
MyArrayByte := ReadFromDataBase(address_module_in_database)
MyModule := dlm.LoadDLM(MyArrayByte)
// …
}
这样,我们不仅可以连接一个作为模块的文件到我们的主程序,还可以连接一个作为模块的字节数组。字节数组本身可以位于任何地方,无论是在数据库中、文件中,甚至是在主程序的主体中。
第三步
我在磁盘上有一个文本文件:Discount_customer.GODLM
或者我从数据库中读取了程序文本
在我们主程序执行期间进行编译,然后将编译后的代码连接到主程序
func main() {
// …
MyText := ReadTextFile("Discount_customer.GODLM")
MyArrayByte := dlm.Compile(MyText)
MyModule := dlm.LoadDLM(MyArrayByte)
// …
}
这就是所谓的扩展性))
无需停止主服务器或重新编译来修复任何问题
这比 LUA 更酷
这比 LUA 更快,因为我们的代码将被编译成字节码,而不是解释执行。
Python 在一旁紧张地抽烟
第四步
现在语言 golang 在 go.exe 中
接下来我们将 go.exe 分成:go.exe 和 go.dlm
编译器现在位于 go.dlm 中
现在我可以将 go.dlm 放入我的程序中,以便在我的程序中连接 go.dlm 并即时编译。
更多关于Golang进阶指南:下一步该学什么的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang进阶指南:下一步该学什么的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中实现动态模块加载和代码热更新的需求确实存在,但需要明确的是,Go的设计哲学强调静态链接和部署简单性。不过,可以通过现有技术部分实现类似功能。以下是针对您描述的DLM概念的实现思路和示例代码。
使用Go插件系统实现动态加载
Go标准库提供了plugin包,支持加载预编译的共享库(.so文件),这类似于您设想的DLM功能。以下是一个基本示例:
第一步:创建插件模块
创建文件 discount_module.go:
// discount_module.go
package main
func CalculateDiscount() int {
return 6 // 可替换算法逻辑
}
// 必须导出为符号
var Symbol CalculateDiscount
编译为插件:
go build -buildmode=plugin -o discount_module.so discount_module.go
第二步:主程序加载插件
创建文件 main.go:
package main
import (
"fmt"
"plugin"
)
func main() {
// 加载插件文件
p, err := plugin.Open("discount_module.so")
if err != nil {
panic(err)
}
// 查找符号
sym, err := p.Lookup("Symbol")
if err != nil {
panic(err)
}
// 类型断言并调用函数
calculateDiscount, ok := sym.(func() int)
if !ok {
panic("invalid function type")
}
discount := calculateDiscount()
fmt.Println("discount =", discount)
}
实现字节数组加载和动态编译
对于从数据库或文本加载代码并动态编译的需求,Go标准库不直接支持,但可通过以下方式模拟:
使用go/parser和go/types进行代码分析(注意:这无法直接执行,仅用于演示解析):
package main
import (
"fmt"
"go/parser"
"go/token"
)
func main() {
srcCode := `package main; func CalculateDiscount() int { return 6 }`
fset := token.NewFileSet()
// 解析代码
f, err := parser.ParseFile(fset, "", srcCode, parser.AllErrors)
if err != nil {
panic(err)
}
fmt.Printf("Parsed package: %s\n", f.Name.Name)
// 此处可进一步处理AST,但无法直接编译执行
}
限制与替代方案
- 插件限制:Go插件仅支持Linux、macOS和相同Go版本编译,且无法从字节数组直接加载。
- 动态编译:无法在运行时编译并执行任意Go代码,因Go是静态编译语言。
- 替代方案:考虑使用WebAssembly(WASM)或嵌入解释型语言(如Lua、Starlark)实现热更新:
- WASM示例:使用
wasmer-go加载预编译WASM模块。 - Lua示例:使用
gopher-lua执行Lua脚本。
- WASM示例:使用
总结
虽然Go的静态特性限制了完全动态的模块加载,但通过插件和外部解释器可在特定场景下实现类似功能。若需高度动态化,建议评估其他语言或架构设计。


