在golang上进行插件编程

huangapple go评论105阅读模式
英文:

Plugin programming on golang

问题

我正在使用Go语言编写我的项目。我想要设计我的项目像插件编程一样,但是我对Go语言感到困惑。我的项目有数据分析任务,我打算创建一个包含分析模块的文件夹,如果我有新的模块,只需要将其复制到文件夹中,主应用程序将会将数据传递给新的模块而无需修改。
你能帮助我吗?谢谢关注!

英文:

I am coding my project with golang. I want to design my project like plugin programming but I have confused with golang. My project have data analysis task, I purpose make a folder that contain modules analysis, if I have new modules after, I just need copy it to folder and main application will pass data to the new modules without modified.
Can you help me? Thanks for watching!

答案1

得分: 2

使用Go的接口是构建可插拔组件的好选择。

接口

在Go中,接口是一种类型抽象的方式。

Go中的接口提供了一种指定对象行为的方式:如果某个对象可以执行某个行为,那么它可以在这里使用。

这意味着一件简单但非常强大的事情——如果不同的复合字面量实现了接口,那么你可以将它们作为接口类型使用。这已经是一个可插拔的系统,如果你正在寻找一些简单的东西,只需付出最小的努力即可构建。

最简单的实现

假设你有这样一个原始的架构:

▾ pluggable/       
  ▾ app/           
      pusher.go    
  ▾ plugins/       
      green_button.go   
      plugin_interface.go
      red_button.go   
    main.go        

plugins/plugin_interface.go

这是一个将用作插件类型抽象的接口。

package plugins        
                   
type Button interface {
    Push()             
}                     

plugins/green_button.go

现在可以通过实现接口来扩展应用程序。

package plugins              
                         
import (                     
    "fmt"                    
)                            
                         
type GreenButton struct {    
    Msg string               
}                            
                         
func (b GreenButton) Push() {
    fmt.Println(b.Msg)       
}                            

plugins/red_button.go

另一个插件...

package plugins            
                       
import (                   
    "fmt"                  
)                          
                       
type RedButton struct {    
    Err error              
}                          
                       
func (b RedButton) Push() {
    fmt.Println(b.Err)     
}                          

app/pusher.go

接口类型嵌入在复合字面量中。任何实现了该接口的复合字面量都可以在Pusher实例中使用。Pusher不关心具体的插件实现,它只是推送。它具有良好的抽象和封装性。

package app                            
                                   
import (                               
    "github.com/I159/pluggable/plugins"
)                                      

type Pusher struct {                   
    plugins.Button                     
}                                      

main.go

使用所有这些东西。

package main                                                                
                                                                        
import (                                                                    
    "errors"                                                                
    "github.com/I159/pluggable/app"                                         
    "github.com/I159/pluggable/plugins"                                     
)                                                                           
                                                                        
func main() {                                                               
    alert_pusher := app.Pusher{plugins.RedButton{Err: errors.New("Alert!")}}
    success_pusher := app.Pusher{plugins.GreenButton{Msg: "Well done!"}}    
                                                                        
    alert_pusher.Push()                                                     
    success_pusher.Push()                                                   
}                                                                           

你可以添加更多功能,例如更多层次的隔离,使用单个按钮配置为一个或另一个特定实现等等。

插件作为库

使用插件库的相同技巧。在插件库中声明的复合字面量必须实现主应用程序的插件接口。但在这种情况下,你需要注册一个函数和一个包含库导入的文件,因此它看起来已经像一个微型插件框架。

英文:

Go with it's interfaces is a good choice to build something pluggable.

Interfaces

Interface in Go is a way of types abstraction.

> Interfaces in Go provide a way to specify the behavior of an object: if something can do this, then it can be used here.

It means a simple but very powerful thing - you can use different composite literals as an interface type if they implement the interface. This is already a pluggable system and if are looking for something simple it is possible to build with minimal effort.

Simplest implementation

Let's say you have such a primitive architecture:

▾ pluggable/       
  ▾ app/           
      pusher.go    
  ▾ plugins/       
      green_button.go   
      plugin_interface.go
      red_button.go   
    main.go        

plugins/plugin_interface.go

An interface which will be used as a type abstraction for plugins.

package plugins        
                   
type Button interface {
    Push()             
}                     

plugins/green_button.go

Now it is possible to extend your application with plugins implement the interface.

package plugins              
                         
import (                     
    "fmt"                    
)                            
                         
type GreenButton struct {    
    Msg string               
}                            
                         
func (b GreenButton) Push() {
    fmt.Println(b.Msg)       
}                            

plugins/red_button.go

One more plugin...

package plugins            
                       
import (                   
    "fmt"                  
)                          
                       
type RedButton struct {    
    Err error              
}                          
                       
func (b RedButton) Push() {
    fmt.Println(b.Err)     
}                          

app/pusher.go

An interface type embedded in the composite literal. Any cl implementing the interface could be used in the Pusher instance. Pusher doesn't care about particular plugin implementation it just pushes. It is well abstracted and encapsulated.

package app                            
                                   
import (                               
    "github.com/I159/pluggable/plugins"
)                                      
                                   
type Pusher struct {                   
    plugins.Button                     
}                                      

main.go

Usage of all the stuff.

package main                                                                
                                                                        
import (                                                                    
    "errors"                                                                
    "github.com/I159/pluggable/app"                                         
    "github.com/I159/pluggable/plugins"                                     
)                                                                           
                                                                        
func main() {                                                               
    alert_pusher := app.Pusher{plugins.RedButton{Err: errors.New("Alert!")}}
    success_pusher := app.Pusher{plugins.GreenButton{Msg: "Well done!"}}    
                                                                        
    alert_pusher.Push()                                                     
    success_pusher.Push()                                                   
}                                                                           

You can add more sugar, for example one more level of isolation to use a single button configured to be a one or another particular implementation and so on.

Plugins as libraries

Same trick with plugin-libraries. A composite literals declared in a plugin-libraries must implement a plugin interface of the main application. But in this case you will need a register a function and a file with libs imports, so it already looks like a nano plugin framework.

答案2

得分: 1

Go 1.8支持插件:https://beta.golang.org/pkg/plugin/。如果你可以等几个月,你可以使用它(或者直接使用beta版1.8)。

英文:

Go 1.8 has support for plugins: https://beta.golang.org/pkg/plugin/. If you can wait a couple months you could use that (or just use the beta 1.8).

huangapple
  • 本文由 发表于 2016年12月7日 11:28:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/41008918.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定