Golang中如何实现使用-buildmode=shared构建的库中的Init()类函数

Golang中如何实现使用-buildmode=shared构建的库中的Init()类函数 当使用 -buildmode=c-shared 构建 Go 库时,可以调用 init() 函数,但在使用 -buildmode=shared 构建时,似乎无法调用相同的函数。是否有其他类似 init() 的函数会被自动调用?

3 回复

我认为没有,但我很好奇你想要实现什么。

更多关于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 共享库,最可靠的方式是提供显式的初始化函数,由调用方控制初始化时机。

回到顶部