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

2 回复

存在一种被称为DLL地狱的情况。据我理解,DLM也是同样的问题。也许更好的方法,也是Go语言中更自然的方式,是创建一个自定义包,就像这样,并在整个程序中使用它。或者使用插件。

这只是我的个人观点!表情

更多关于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/parsergo/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,但无法直接编译执行
}

限制与替代方案

  1. 插件限制:Go插件仅支持Linux、macOS和相同Go版本编译,且无法从字节数组直接加载。
  2. 动态编译:无法在运行时编译并执行任意Go代码,因Go是静态编译语言。
  3. 替代方案:考虑使用WebAssembly(WASM)或嵌入解释型语言(如Lua、Starlark)实现热更新:
    • WASM示例:使用wasmer-go加载预编译WASM模块。
    • Lua示例:使用gopher-lua执行Lua脚本。

总结

虽然Go的静态特性限制了完全动态的模块加载,但通过插件和外部解释器可在特定场景下实现类似功能。若需高度动态化,建议评估其他语言或架构设计。

回到顶部