Golang中如何实现使用-buildmode=shared构建的库中的Init()类函数
Golang中如何实现使用-buildmode=shared构建的库中的Init()类函数
当使用 -buildmode=c-shared 构建 Go 库时,可以调用 init() 函数,但在使用 -buildmode=shared 构建时,似乎无法调用相同的函数。是否有其他类似 init() 的函数会被自动调用?
我认为没有,但我很好奇你想要实现什么。
更多关于Golang中如何实现使用-buildmode=shared构建的库中的Init()类函数的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
我想为Go插件实现此功能,而不是针对buildmode=shared。目的是在插件中初始化一些参数。
在使用 -buildmode=shared 构建的 Go 库中,init() 函数确实不会自动执行。这是因为共享库模式(shared)与 C 共享库模式(c-shared)的设计目标不同:-buildmode=shared 生成的是供其他 Go 程序动态链接的共享库,而 -buildmode=c-shared 则是生成供 C 程序调用的共享库。
在 -buildmode=shared 模式下,Go 运行时初始化由主程序控制,因此库中的 init() 函数只有在库被主程序显式导入时才会执行。如果你需要在共享库加载时执行初始化逻辑,可以考虑以下方法:
1. 导出显式初始化函数
在库中导出一个专门的初始化函数,由调用方在合适的时候调用。
package mylib
import "fmt"
var initialized bool
// 库中的 init 函数不会自动执行
func init() {
fmt.Println("This won't execute automatically in -buildmode=shared")
}
// 导出显式初始化函数
func InitLibrary() {
if !initialized {
fmt.Println("Library initialization")
initialized = true
}
}
// 其他库函数
func DoSomething() {
if !initialized {
panic("library not initialized")
}
fmt.Println("Doing something")
}
调用方需要这样使用:
package main
import "mylib"
func main() {
mylib.InitLibrary() // 显式初始化
mylib.DoSomething()
}
2. 使用包级变量初始化
如果初始化不涉及复杂逻辑,可以使用包级变量的初始化来替代 init() 函数。
package mylib
import "fmt"
// 包级变量初始化会在导入时执行
var (
initialized = func() bool {
fmt.Println("Package-level initialization")
return true
}()
)
func DoSomething() {
fmt.Println("Doing something")
}
3. 使用 sync.Once 确保单次初始化
对于需要线程安全的初始化,可以使用 sync.Once。
package mylib
import (
"fmt"
"sync"
)
var (
initOnce sync.Once
)
func initialize() {
fmt.Println("One-time initialization")
}
func DoSomething() {
initOnce.Do(initialize)
fmt.Println("Doing something")
}
构建和测试示例
构建共享库:
go install -buildmode=shared mylib
主程序构建:
go build -linkshared -o main main.go
需要注意的是,-buildmode=shared 主要用于减少多个 Go 程序的内存占用,通过共享公共库的代码段。如果你的主要目标是与 C 代码交互,应该使用 -buildmode=c-shared,这样 init() 函数会在库加载时自动执行。
对于 -buildmode=shared 的 Go 共享库,最可靠的方式是提供显式的初始化函数,由调用方控制初始化时机。

