NotePublic/Software/Development/Language/Go/Basic/Go_Plugin.md

85 lines
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# [Go Plugingo 动态库)](https://blog.csdn.net/m0_38132420/article/details/68496881)
- [Go Plugingo 动态库)](#go-plugingo-动态库)
- [1. 简介](#1-简介)
- [2. 使用](#2-使用)
- [3. 注意](#3-注意)
## 1. 简介
在 Go 1.8 出现以前,一直觉得 Go 语言不能像 C/C++一样可以使用动态库的方式动态修改服务。每次升级操作都不得不重新编译整个工程,重新部署服务。这对于很多比较重型的服务来说是一个很致命的弱点。
目前在 Go 1.8 只在 Linux 和 Darwin 系统下支持 Plugin。从 Go 1.8 源码中 plugin 包中 plugin.go 文件开头中有对应的说明。在 Go 1.8 中 plugin 包在操作系统的支持并不十分完善,即使在 Linux 系统下也需要特定 gcc 的编译器及连接器的支持。后续版本应该会有做相应的改进。
## 2. 使用
创建一个提供方法的文件 print.go
```go
package main
import (
"fmt"
)
func PrintTest(strInput string) {
fmt.Println("string in print.so is:", strInput)
}
```
编译 Go 动态库命令:
```bash
go build -trimpath -buildmode=plugin -ldflags="-w -s"
```
其中 -trimpath 用于从二进制文件中删除文件系统路径信息,如果不增加该参数,主程序加载插件时会去匹配 GOPATH如果二者的 GOPATH 不一致则不进行加载。
指定文件编译 Go 动态库命令:
```bash
go build -trimpath -buildmode=plugin -ldflags="-w -s" -o print.so print.go
```
go 动态库方法的使用main.go
```go
package main
import (
"plugin"
)
func main() {
// 打开动态库
pdll, err := plugin.Open("print.so")
if err != nil {
//...
return
}
// 获取动态库方法
funcPrint, err := pdll.Lookup("PrintTest")
if err != nil {
//...
return
}
// 动态库方法调用
funcPrint.(func(string))("hello go plugin")
return
}
```
编译:
```bash
go build -trimpath -ldflags="-w -s"
```
Go 1.8 中 plugin 包只提供 Open 和 Lookup 方法,对应打开动态库和获取动态库中的方法。注意获取到的动态动态库方法其实是一个 interface{} 类型,需要将其进行转换后才可以使用。
## 3. 注意
1. 插件实现和主应用程序都必须使用完全相同的 Go 工具链版本构建。
2. 除非指定 -trimpath 参数,否则插件实现和主应用程序都必须使用完全相同的 GOPATH 构建。
3. 插件中的任何依赖项应该与主应用程序中的依赖项版本相同。
4. 你无法将插件编译为静态二进制文件。