您没有完全按照自己的想法去做。
您的 plugin1 导入并使用一个 软件包 ,即
github.com/vimal/testplugin1/plug。这与
plugin2 不相等!
这里发生的是,当您构建 plugin1时 ,其所有依赖项都被构建到插件文件中,包括
.../testplugin1/plug软件包。并且当您加载
plugin1时 ,其所有依赖项也将从插件文件(包括
plug软件包)中加载。此后,无论 plugin2 的加载状态如何 都
可以正常工作 也就不足为奇了 。这两个插件彼此独立。
该
-buildmode=plugin指令指示编译器要构建插件而不是独立应用程序,但这并不意味着必须不包含依赖项。它们必须是这样,因为插件不能完全保证Go应用程序将加载它,以及Go应用程序将拥有什么软件包。因为可运行的应用程序甚至仅包含应用程序本身明确引用的标准库中的程序包。
保证插件具有所需一切的唯一方法,并且如果它还包含其所有依赖项(包括来自标准库的依赖项),则它将可以正常工作。(这就是为什么构建简单的插件会生成相对较大的文件的原因,类似于构建简单的Go可执行文件会生成大文件的原因。)
几乎不需要添加到插件中的东西都包括Go运行时,例如,因为将要加载插件的正在运行的Go应用程序已经在运行Go运行时。(请注意,您只能从使用相同版本的Go编译的应用程序中加载插件。)但是除此之外,该插件还必须包含所需的一切。
Go是一种静态链接的语言。编译Go应用或插件后,它们将不再依赖或检查的值
GOPATH,仅在构建它们时由Go工具使用。
更深刻的见解
您的主应用程序和插件可能引用相同的程序包(导入路径“相同”)。在这种情况下,将仅使用包装的一个“实例”。
如果此通用包具有“状态”,例如全局变量,则可以对此进行测试。让我们假设一个通用的共享软件包
mymath:
package mymathvar S stringfunc SetS(s string) { S = s}还有一个
pg使用它的插件:
package mainimport ( "C" "mymath" "fmt")func Start() { fmt.Println("pg:mymath.S", mymath.S) mymath.SetS("pghi") fmt.Println("pg:mymath.S", mymath.S)}以及使用
mymath和加载
pg(使用它)的主应用程序:
package mainimport ( "plugin" "mymath" "fmt")func main() { fmt.Println("mymath.S", mymath.S) mymath.SetS("hi") fmt.Println("mymath.S", mymath.S) p, err := plugin.Open("../pg/pg.so") if err != nil { panic(err) } start, err := p.Lookup("Start") if err != nil { panic(err) } start.(func())() fmt.Println("mymath.S", mymath.S)}构建插件:
cd pggo build -buildmode=plugin
运行主应用程序,输出为:
mymath.S mymath.S hipg:mymath.S hipg:mymath.S pghimymath.S pghi
分析:首先,主应用程序开始运行
mymath.S,然后将其设置为
"hi"最终。然后是插件,它会打印它(我们看到了主应用程序设置的值
"hi"),然后将其更改为
"pghi"。然后再次出现主应用程序并打印
mymath.S,然后再次看到插件设置的最后一个值:
"pghi"。
因此,仅存在一个“实例”
mymath。现在,如果继续进行更改
mymath,例如将重命名
myMath.SetS()为
mymath.SetS2(),然后在主应用程序中将调用更新为
mymath.SetS2("hi"),而无需重新构建插件,只需运行主应用程序,您将获得以下输出:mymath.S mymath.S hipanic: plugin.Open: plugin was built with a different version of package mymathgoroutine 1 [running]:main.main() <GOPATH>/src/play/play.go:16 +0x4b5exit status 2
如您所见,在构建主应用程序和插件时,将记录软件包版本(很可能是哈希),如果它们的导入路径在主应用程序和插件中匹配,则必须匹配。
(请注意,如果您不更改使用过的
mymath包的导出标识符(和签名),而仅更改实现,则也会出现上述错误;例如
func SetS(s string) {S = s + "+" }。)


