用于多平台多语言项目的Golang代码组织

时间:2014-02-06 22:28:53

标签: go organization code-organization project-organization

我正在为一个多平台项目寻找一个好的项目组织,其中包含用Go编写的多个组件。我知道http://golang.org/doc/code.html推荐的布局,但布局显示似乎不符合我的要求。

项目组件是:

  • 服务器(用Go编写)
  • 客户端,跨平台(Go)
  • 库,在服务器和客户端之间共享(Go)
  • 更多客户(iOS,Android)

我的要求是:

  • 单个git存储库中的所有组件
  • 保持组件分离(例如,每个组件一个目录)
  • Go组件可以构建为多个子包

我目前的做法:

project/ (this is the repository root)
  server/
    server.go (package main)
    src/          
      server/
        package1/
          package1.go
        ...
  client/
    client.go (package main)
    src/
      client/
        package2/
          package2.go
        ...
  lib/
    src/
      lib/
         lib.go
         ...
  client-ios/
    ...
  client-android/
    ...

要构建,我使用Makefile

  1. 将lib /复制到server /和client /
  2. 单独构建服务器/客户端/,每次都将GOPATH设置为相应的目录。
  3. 它有效,但感觉非常笨拙,与推荐的代码布局完全不同。

    以下是我正在考虑的替代方案:

    project/ (this is the repository root)
      gospace/
        src/
          server/...
          client/...
          lib/...
      client-ios/
        ...
      client-android/
        ...
    

    使用这种布局我有一个GOPATH(gospace /)并且不需要klunky Makefile。但是,组件没有像第一种方案那样整齐地分开(即通过顶级目录)。

    我的问题:哪种项目布局最适合我的要求和Go约定和工具支持?有没有更好的选择,我还没有看到?

2 个答案:

答案 0 :(得分:6)

这就是我组织类似项目的方式:

$GOPATH/src/project-root/
    lib.go
    lib_test.go

    server/
        server.go
        server_test.go

        main/
            server.go // package main; import "project-root/server"

    client/
        client.go
        client_test.go

        main/
            client.go //package main; import "project-root/client"

    client-ios/
        ....

    client-android/
        ....

虽然大多数server/server.goclient/client.go作为package main应该有效,但最好将其分开,以便将客户端/服务器嵌入到其他项目中。

答案 1 :(得分:2)

回答这个问题已有很长时间了(关于OP的最新评论是2014年2月12日,而最新的回答是2014年4月16日)。当时我并没有去过Go状态,只是在2018/19年才真正了解它,但是看起来已经发生了很多变化。

我认为,影响本文答案的最大变化是Go Modules。

我的作品中有一个类似的项目(Go服务器,Go CLI,Android应用程序,iOS应用程序)。我当前正在使用go版本go1.13.7 darwin / amd64。这是我通过Go模块附带的结构(受this post by Ben Johnson影响很大):

def portfolio_annualised_performance(weights, mean_returns, cov_matrix):
    returns = np.sum(mean_returns * weights)
    std = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
    return std, returns

def neg_sharpe_ratio(weights, mean_returns, cov_matrix):
    p_var, p_ret = portfolio_annualised_performance(weights, mean_returns, cov_matrix)
    return -252*(p_ret) / p_var

def max_sharpe_ratio(mean_returns, cov_matrix):
    num_assets = len(mean_returns)
    args = (mean_returns, cov_matrix)
    def portfolio_volatility(weights):
        return portfolio_annualised_performance(weights, mean_returns, cov_matrix)[0]
    constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1},{'type': 'ineq', 'fun': lambda x: portfolio_volatility(x) - 0.03000000})
    bound = [(0.0,0.5),(0.0,0.5),(0.0,0.5),(0.0,0.4),(0.0,0.3),(0.0,0.4)] 
    bounds = tuple(bound[asset] for asset in range(num_assets))
    result = sco.minimize(neg_sharpe_ratio, num_assets*[1./num_assets,], args=args,
                        method='SLSQP', bounds=bounds, constraints=constraints)

根目录位于GOPATH之外,并包含必要的directory-outside-GOPATH/ go.mod go.sum domaintypes.go cmd/ api/ main.go cli/ main.go postgres/ ...(library Go code)... http/ ...(library Go code)... android/ ...(Android app)... iOS/ ...(iOS app)... ...(other Go code).../ ... go.mod文件。 go.sum文件是为了说明我在根目录中剩下的唯一Go文件是永远不会导入其他内容的代码-例如定义您的域类型/模型/服务接口/等。我个人有多个:domaintypes.gouser.go,等等。

group.gopostgres目录是我编写的库,它们都是分层适配器。每个库目录都应隔离到其域。例如HTTP路由不应直接与数据库连接交互。

所有可执行的Go代码都应存放在http目录中。我想要一个API服务器和一个单独的CLI,所以这就是我的住所。这些文件应保持较小,并调用您编写的所有其他库。

对于非Go代码,我只是在Android和iOS的根目录中创建了单独的目录。