golang学习之go plugin 调用动态库

一、插件库开发

插件库导出信息需位于main包内

package main

import "fmt"

func init() {
    
    
	fmt.Println("I'm in plugin init()")
}

func MyPrin(a, b int) int {
    
    
	fmt.Println("I'm in plugin func")
	return a + b
}

二、插件库打包

1·、go plugin 打包依赖gcc,如果环境没有安装gcc,需安装gcc

sudo apt-get install gcc

2、插件库打包,我打的库名包含了依赖的go版本1.19及库版本01

go build -buildmode=plugin -o myplugin-v1.19-01.so plugin.go

三、插件库调用

1、加载库,多次加载同一个库返回同一个库引用。
2、查找库导出信息,使用Lookup查找库导出信息。
3、类型转换,Lookup查询到的是抽象类型Symbol,需要转换为实际需要使用的类型。
4、实际类型调用。

package main

import (
	"log"
	"plugin"
)

func main() {
    
    
	// 根据库的存放路径加载库
	p, err := plugin.Open("myplugin.so")
	if err != nil {
    
    
		log.Fatal(err)
	}
	// 查找库导出信息
	s, err := p.Lookup("MyPrin")
	if err != nil {
    
    
		log.Fatal(err)
	}
	// 类型转换
	f := s.(func(a, b int) int)
	// 实际类型调用
	v := f(4, 5)
	println(v)
}

四、增量部署与热部署

1、http服务,打包部署 go build main.go ,运行 ./main

package main

import (
	"net/http"
	"plugin"
)

func main() {
    
    

	http.HandleFunc("/plugin", func(w http.ResponseWriter, r *http.Request) {
    
    
		defer func() {
    
    
			recover()
		}()
		values := r.URL.Query()
		version := values.Get("version")
		if version == "" {
    
    
			w.Write([]byte("默认实现,更多精彩敬请期待"))
			return
		}

		p, err := plugin.Open(version + ".so")
		if err != nil {
    
    
			w.Write([]byte("功能暂未上线,敬请期待"))
		}
		s, err := p.Lookup("MyPrin")
		if err != nil {
    
    
			w.Write([]byte("功能暂未上线,敬请期待"))
		}
		f := s.(func() string)
		v := f()
		w.Write([]byte(v))

	})
	http.ListenAndServe(":8080", nil)
}

2、模块1,打包 go build -buildmode=plugin -o myplugin-v1.so pluginv1.go

package main

import (
	"fmt"
)

func init() {
    
    
	fmt.Println("版本v1初始化")
}

func MyPrin() string {
    
    
	return "版本v1应答"
}

3、模块2,打包 go build -buildmode=plugin -o myplugin-v2.so pluginv2.go

package main

import (
	"fmt"
)

func init() {
    
    
	fmt.Println("版本v2初始化")
}

func MyPrin() string {
    
    
	return "版本v2应答"
}

4、访问 http://localhost:8080/plugin
默认实现,更多精彩敬请期待
5、http://localhost:8080/plugin?version=myplugin-v1
版本v1应答
6、http://localhost:8080/plugin?version=myplugin-v2
版本v2应答
7、http://localhost:8080/plugin?version=myplugin-v3
功能暂未上线,敬请期待

五、总结

1、go插件目前支持Linux, FreeBSD, macOS。
2、go插件与调用者依赖的go版本及第三方库版本需要一致。
3、使用go plugin 动态库加载可以实现go项目的增量部署、插件热部署。

猜你喜欢

转载自blog.csdn.net/weixin_56349119/article/details/127704115