如何为动态包组织Go代码

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

Go - how to organize code for dynamic packages

问题

我有一个用Go语言编写的小型Web应用程序。它是一个更大系统的基础,我希望它可以扩展,可以添加/删除组件,而不需要修改基础部分。

目前的结构如下:

       App
         Modules
             Core
                 ... 这里是核心文件 ...
       app.go
   main.go

app.go将包含一个路由方法,根据请求路径确定哪个模块负责处理请求。每个模块/组件都有自己的控制器。

每个组件都有自己的包名,所以我认为这是不可能的,因为Go语言要求显式导入。

例如,我可以添加一个名为"blog"的新模块/组件,如下所示:

       App
         Modules
             Core
                 ... 这里是核心文件 ...
                 controller.go
             Blog
                 ... 这里是博客文件 ...
                 controller.go
       app.go
   main.go
英文:

I have a small web application written in Go. It is created a base for a larger system and I would like it to be extendable where components can be added/removed without needing this base to be modified in any way.

The structure is currently:

       App
         Modules
             Core
                 ... Core Files Here ...
       app.go
   main.go

app.go will contain a routing method which should take a web request and based on the request path know which module is responsible for handling the request. Each module/component having its on controller.

Each component will have its own package name so i think this is going to be impossible since go forces an explicit import.

For example i may add a new module/component called say blog such as:

       App
         Modules
             Core
                 ... Core Files Here ...
                 controller.go
             Blog
                 ... Blog Files Here ...
                 controller.go
       app.go
   main.go

答案1

得分: 3

有几种方法可以实现你的目标。由于Go目前不支持动态加载库,所以当你添加或删除任何组件时,可能需要重新编译你的应用程序。因此,最简单的方法是创建一个yourapp/core包,其中包含以下内容:

  • 一个Application类型,具有作为主应用程序的ServeHTTP方法
  • 一个Component接口,所有组件都必须实现该接口。你可能还想在接口中包含一个BaseUrl() string和一个ServeHTTP方法。
  • 一个Register方法,用于向Application类型添加新组件。

然后,你可以在单独的包中实现你的组件(例如yourapp/blog),它们可能依赖于你的yourapp/core包。

唯一仍然需要"用户可编辑"的是main.go文件,它可能如下所示:

func main() {
    app := core.NewApplication()
    app.Register(blog.Blog{
        Title: "My Personal Blog",
    })
    app.Register(...)
    app.Run()
}

另一种方法可能是为你的组件定义一个RPC接口(可能包括RegisterComponentUnregisterComponentGetGlobalConfig等函数)。

然后,你可以在单独的进程中运行这些组件,这样做的好处是你可以动态地启动/停止/重新加载这些组件,而它们不会破坏你的主应用程序。如果你想使用这种方法,可以查看一下net/rpc包,甚至可能还有httputil.NewSingleHostReverseProxy

英文:

There are several ways to achieve your goal. Since Go does not support dynamically loaded libraries at the moment, you need to probably recompile your application whenever you add/remove any components. The simplest way therefore would be a yourapp/core package with the following:

  • an Application type with an ServeHTTP method that acts as your main application
  • a Component interface that all your components have to implement. Your might want include a BaseUrl() string and a ServeHTTP method there.
  • a Register method to your Application type, that can be used to add new components to your app.

Your components can then be implemented in separate packages (e.g. yourapp/blog) and they will probably depend on your yourapp/core package.

The only thing that still needs to be "user-editable" is the main.go file, which might look like this:

func main() {
    app := core.NewApplication()
    app.Register(blog.Blog{
        Title: "My Personal Blog",
    })
    app.Register(...)
    app.Run()
}

Another approach might be to define an RPC interface for your components (which might include functions like RegisterComponent, UnregisterComponent and a GetGlobalConfig).

Then, you can run those components in separate processes which has the advantage that you can start/stop/reload those components dynamically and they can not break your main app. Take a look at the net/rpc package and maybe even httputil.NewSingleHostReverseProxy if you want to use this approach instead.

huangapple
  • 本文由 发表于 2013年8月10日 03:11:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/18153971.html
匿名

发表评论

匿名网友

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

确定