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

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

Golang code organization for multi-platform multi-language project

问题

我正在寻找一个适用于多平台项目的良好项目组织结构,该项目由多个使用Go编写的组件组成。我了解到http://golang.org/doc/code.html中推荐的布局,但那里建议的布局似乎不符合我的要求。

项目组件包括:

  • 服务器(使用Go编写)
  • 客户端,跨平台(Go)
  • 库,用于服务器和客户端之间的共享(Go)
  • 其他一些客户端(iOS、Android)

我的要求是:

  • 所有组件在一个git仓库中
  • 保持组件分离(例如,每个组件一个目录)
  • Go组件可以结构化为多个子包

我目前的方法是:

project/(这是仓库根目录)
  server/
    server.go(包main)
    src/
      server/
        package1/
          package1.go
        ...
  client/
    client.go(包main)
    src/
      client/
        package2/
          package2.go
        ...
  lib/
    src/
      lib/
         lib.go
         ...
  client-ios/
    ...
  client-android/
    ...

构建时,我使用一个Makefile:

  1. 将lib/复制到server/和client/中
  2. 分别构建server/和client/,每次都将GOPATH设置为相应的目录。

这个方法可以工作,但感觉很笨拙,并且与推荐的代码布局相差很大。

这是我正在考虑的另一种布局:

project/(这是仓库根目录)
  gospace/
    src/
      server/...
      client/...
      lib/...
  client-ios/
    ...
  client-android/
    ...

使用这种布局,我只有一个GOPATH(gospace/),而且不需要笨拙的Makefile。然而,组件的分离程度不如第一种布局那样清晰(即通过顶级目录)。

我的问题是:哪种项目布局最适合我的要求和Go的约定和工具支持?是否有我尚未看到的更好的选项?

英文:

I am looking for a good project organization for a multi-platform project with multiple components written in Go. I am aware of the recommended layout from http://golang.org/doc/code.html, but the layout suggested there does not seem to fit my requirements.

Project components are:

  • server (written in Go)
  • client, cross-platform (Go)
  • library, shared between server and client (Go)
  • some more clients (iOS, Android)

My requirements are:

  • All components in a single git repository
  • Keep components separate (e.g. one directory per component)
  • Go components can be structured into multiple sub-packages

My current approach:

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/
    ...

To build, I use a Makefile which

  1. Copies lib/ into both server/ and client/
  2. Builds server/ and client/ separately, setting GOPATH every time to the respective directory.

It works, but feels really klunky and is quite different to the recommended code layout.

Here is the alternative I am considering:

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

With this layout I have a single GOPATH (gospace/) and don't need the klunky Makefile. However, the components are not separated as neatly as in the first alternative (i.e. via a top level directory).

My question: Which project layout would be best suited for both my requirements and Go conventions and tooling support? Are there better options which I did not see yet?

答案1

得分: 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就可以工作,但最好将它们分开,这样你就可以将客户端/服务器嵌入到其他项目中。

英文:

This is how I organized a similar project :

$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/
		....

While mostly having server/server.go and client/client.go as package main should work, it's better to separate it so you could embed the client/server in other projects.

答案2

得分: 3

这个问题的回答已经很久了(OP的最后一条评论是2014年2月12日,最新的回答是2014年4月16日)。那个时候我还不了解Go的情况,直到2018/19年才真正接触到它,但看起来有很多变化。

我认为对这个帖子的回答影响最大的变化是Go Modules。

我正在进行一个类似的项目(Go服务器,Go命令行界面,Android应用程序,iOS应用程序)。我目前正在使用go version go1.13.7 darwin/amd64。这是我通过Go Modules得出的结构(受到Ben Johnson的这篇文章的很大影响):

directory-outside-GOPATH/
    go.mod
    go.sum
    domaintypes.go
    cmd/
        api/
            main.go
        cli/
            main.go
    postgres/
        ...(库的Go代码)...
    http/
        ...(库的Go代码)...
    android/
        ...(Android应用程序)...
    iOS/
        ...(iOS应用程序)...
    ...(其他Go代码).../
        ...

根目录位于GOPATH之外,包括必要的go.modgo.sum文件。domaintypes.go文件用于说明我只在根目录中保留永远不会导入其他内容的Go文件,比如定义领域类型/模型/服务接口等。我个人有多个文件,比如user.gogroup.go等。

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

cmd目录是所有可执行的Go代码应该存在的地方。我想要一个API服务器和一个单独的CLI,所以它们就在这里。这些文件应该保持相对较小,并调用你编写的所有其他库。

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

英文:

It's been a long time since this question was answered (last comment on OP was Feb. 12, 2014, and the latest answer was Apr. 16, 2014). I wasn't around for the state of Go at that time, only really being introduced to it in 2018/19, yet it looks like a lot has changed.

The biggest change that influences the answer to this post, I believe, is Go Modules.

I have a similar project in the works (Go server, Go CLI, Android app, iOS app). I am currently using go version go1.13.7 darwin/amd64. Here is the structure I came with via Go Modules (very much influenced by this post by Ben Johnson):

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).../
        ...

The root directory sits outside of the GOPATH and includes the necessary go.mod and go.sum files. The domaintypes.go file is to illustrate that the only Go files I leave in the root directory is code that will never import anything else - such as defining your domain types/models/service-interfaces/etc. I personally have multiple: user.go, group.go, etc.

The postgres and http directories are libraries I have written, both of which are layered adapters. Each library directory should be isolated to its domain. e.g. HTTP routes should not directly interact with database connections.

The cmd directory is where all executable Go code should live. I want an API server and a separate CLI so this is where that lives. These files should remain relatively small and call all of the other libraries you wrote.

As for the non-Go code, I simply created separate directories in the root directory for both Android and iOS.

huangapple
  • 本文由 发表于 2014年2月7日 06:28:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/21615457.html
匿名

发表评论

匿名网友

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

确定