Objective
Recently in the learning Fabric 1.2 version of the new features, one of them is implemented the transaction endorsement and block result verification which are both originally by the system chain Code escc
and the vscc
responsible module pluggable. Their pluggable use of Go's plugin technology, which is the first time I know the concept of Go plugin (although it's in Go 1.8), is ready to explore what go plugin is and how to use it.
What is Go Plugin
Golang is a statically compiled language that loads all referenced packages (libraries) into the final executable (or library file) at compile time, so it is not possible to dynamically load other shared libraries at run time. Go Plugin provides a way for you to dynamically load external features at run time.
Why use Go Plugin
In fact, I should ask why to use plugin, I think there are many reasons, such as:
- Pluggable: With plugin, my program can replace some of these parts at any time without modifying my program;
- Dynamic loading needs: Some modules can only be determined at run time, the external function modules need to be loaded dynamically;
- Independent development: Plugin can be independently built with the main program, the main program only need to set up a good framework, to achieve the default (template) function. Plugin can be customized according to user needs at any time to expand their own development, the operation of arbitrary replacement, improve the program's customizable;
How to use Go Plugin
Golang the implementation of Plugin in the standard library plugin
. The entire interface can be said to be quite concise.
type Plugin struct{ ... } func Open(path string) (*Plugin, error) func (p *Plugin) Lookup(symName string) (Symbol, error)type Symbol interface{}
Yes, you are not mistaken, there are only two type
and two methods.
Plugin
The type Plugin
is the Golang loaded plug-in, with two methods associated with it:
Open
: path
loads the plugin from the plug-in path provided by the parameter and returns a pointer to the plug-in structure.*Glugin
Lookup
: *Plugin
the only way to find the symName
corresponding variable or method in the plug-in by name, in Symbol
the form of return
Symbol
By definition type Symbol interface{}
, Symbol
it is interface
an alias, that is, we can get any type of exportable element from the plugin.
Small trial Sledgehammer
Understand the plugin
basic functions of the package, according to the Convention, we need to use hello world
the test.
Prepare plugin source code pluginhello.go
:
package mainimport ( "fmt")func Hello() { fmt.Println("Hello World From Plugin!")}
Here in the plugin, an exportable method is defined for Hello
printing Hello World From Plugin!
.
With the source code, how to compile him into a plug-in?
➜ plugin go1.10 build --buildmode=plugin -o pluginhello.so pluginhello.go➜ plugin lsinvokeplugin.go pluginhello.go pluginhello.so
Use go build
the command and make it buildmode
as well plugin
. So easy!
Note : In particular, it is important to note that the plugin source code needs to be in the main
package, otherwise it cannot be compiled.
The following call this plugin:
package mainimport ( "fmt" "os" "plugin")func main() { p, err := plugin.Open("./pluginhello.so") if err != nil { fmt.Println("error open plugin: ", err) os.Exit(-1) } s, err := p.Lookup("Hello") if err != nil { fmt.Println("error lookup Hello: ", err) os.Exit(-1) } if hello, ok := s.(func()); ok { hello() }}
First Open
, the plugin is opened by means of the method, and then Hello
the method in the plugin is found by name func Hello
.
Note that since any element found in the plugin is Symbol
returned in form (that is interface{}
), we need to judge and transform the result in the form of an assertion to get the type we need.
Let's see how it works:
➜ plugin go1.10 run invokeplugin.goHello World From Plugin!
Perfect call for plugins!
Description: The Plugin support for Linux and MacOS when Go 1.8, but because the bug removed support for MacOS at 1.9, it resumed support for MacOS at 1.10.
My machine is loaded with more than one version, and development requires go 1.9, so when you use Go 1.10, the command uses go1.10
this soft connection