回答

收藏

什么是布局 Go 项目的明智方法

技术问答 技术问答 168 人阅读 | 0 人回复 | 2023-09-12

我开始变得更加复杂的 go 项目,望以这种方式安排文件系统,以减轻疼痛。
" c* r- B% e. [1 W有没有很好的例子来解释什么是有意义的?
- k/ T7 X) N7 |& c                                                               
; g, f- {1 Q, ]! N6 @# h, i    解决方案:                                                                / u1 B. G- }5 \* _: p1 s8 q/ y
                                                                Go 代码必须保存工作区中( X+ Q. Q5 Y) ~
工作区是目录层次结构,其根目录包括三个目录:  b! _8 ?/ |4 m* h: t' F2 @
src 包含组织包装 Go
" G' s. m) M9 L! K: b) M9 i, Ypkg 包含包对象和
8 P! d) d- E- W2 vbin 包含可执行命令。
在go tool构建源码包和安装产生的二进制文件pkg和bin目录。  i- J4 ]; G8 n, N
该src子目录通常包含多个版本的控制存储(如 Git 或 Mercurial),开发一个或多个源包进行跟踪。
1 \5 l- B0 r2 ^6 o* D
    bin/    streak                         # command executable    todo                           # command executablepkg/    linux_amd64/     code.google.com/p/goauth2/          oauth.a                # package object        github.com/nf/todo            task.a                 # package objectsrc/    code.google.com/p/goauth2/           .hg                       # mercurial repository metadata        oauth            oauth.go               # package source            oauth_test.go          # test source
    % X1 e( f5 K. B- }
那篇文章包括以下提示:
# D( [2 }/ Z0 y( G将二进制文件与应用程序分开将main.go在同一个包里,文件和我的应用逻辑组合有两个结果:- N7 T& ]/ A7 ]3 ?2 p
它使我的应用程序无法用作库。" v7 S9 V3 N) |% _' J
我只能有一个应用程序二进制文件。
我发现解决这个问题的最好方法是cmd在我的项目中简单地使用 目录,每个子目录都是应用程序二进制文件。2 f) ]8 d( b4 H8 u
    camlistore/  cmd/    camget/       main.go    cammount/       main.go    camput/       main.go    camtool/       main.go
    / E& F/ x9 |& A: K) S! f
库驱动开发将main.go从根目录中删除文件,允许您从图书馆的角度构建应用程序。您的应用程序二进制文件只是应用程序库的客户端。
5 k+ d4 K4 z$ _* ]& }: e有时你可能希望用户以多种方式互动,所以你可以创建多个二进制文件。3 n  v4 W0 S# L8 @; t. o/ |7 q: q0 w  P
例如,如果你有 adder包,可以让用户把数字加在一起,你可能想发布命令行版本和网络版本。
& E, J' n! |$ r6 F' [& L' K+ c你可以很容易地组织你的项目:
& m4 u2 q& D2 ^0 ^
    adder/  adder.go  cmd/    adder/       main.go    adder-server/       main.go
    # e1 D3 z! B6 Q5 N1 s5 n0 Q) m7 f
用户可以使用省略号通过go get”安装“adder应用程序二进制文件:9 `, ]) i+ S( ?% K6 l* _3 ~
    $ go get github.com/benbjohnson/adder/...( w& Z/ ?1 m; L0 |
看,您的用户安装了  adder”和“ adder-server”!
0 k' E1 }/ {2 L. c& U不要对子包发疯通常我的项目类型非常相关,所以从可用性到 API 从角度看更合适。
; E7 [5 U) {, b! `/ Z& b" i这些类型也可以使用它们之间未导出的调用来维持 API 小而清晰。2 N' Q& M. |0 g0 d% `  E
[ol]将相关类型和代码组合在每个文件中。如果您的类型和函数组织得很好,我发现文件通常在 200到 500 SLOC 之间。这听起来可能很多,但我发现它很容易导航。1000 SLOC 通常是我对单个文件的上限。
  |2 T4 {( b) Y& a+ y组织文件顶部最重要的类型,并在文件底部增加重要性递减的类型。: Z+ x# ^& t; Y1 A" V
一旦你的应用程序开始超过 10,000 SLOC,你应该仔细评估它是否可以分解为更小的项目。[/ol]注:最终的做法并不总是好的:
0 L8 Z. u0 A) Y+ z+ a  _对不起,我不能同意。
$ y, X( h/ X+ y$ D& c& _将类型分离到文件有助于代码管理、可读性、可维护性和可测试性。
: ]- L( [+ j* J! M$ z# ~+ s4 K# u还可以保证单一职责,遵循开放/封闭的原则......& C  v+ a2 `+ i
不允许循环依赖的规则是强迫我们有一个清晰的包结构。+ d5 `/ F8 J0 W( P# u5 u+ A
你能找到你能找到GitHub 代码布局中描述的经典布局:
( V' J" d8 d/ R1 n& W- i两个应用程序和库位于 Github 上,每个仓库都在自己的仓库里。
$ m) Q3 P  d7 i* X$GOPATH是项目的根 - 你的每一个 Github 存储库将在以下文件夹中检测到$GOPATH。% G0 I! H8 c+ }. O$ A( j1 d  l* x
您的代码布局如下所示:
4 D5 o. T$ V6 p0 H
    $GOPATH/    src/          github.com/              jmcvetta/                  useless/                      .git/                      useless.go                    useless_test.go                    README.md                uselessd/                      .git/                      uselessd.go                    uselessd_test.go                    README.md' _# o: d$ T  o4 d, Y' {! H( c3 J: @
下面的每个文件夹src/github.com/jmcvetta都是单独的 git checkout 根目录。
+ L  C, R+ @$ ~- E- T! N0 o! C但是,在这里reddit 页面中,这引起了一些批评:) p. R  M7 |% A% p
我强烈建议不要以你的方式建 repo,它会破坏 go get”,这是 Go 最有用的东西之一。
6 r2 e" g; R, g5 v' L为了解 Go 的人写代码要好得多,因为他们最有可能是编译它的人。
, P# V) y3 {: u至少对于那些不这样做的人,他们会感受到这种语言。& i! C9 ?. F6 o! z9 z/ [5 _
把主包放在 repo 根目录。
4 z/ C7 _8 O6 J, e. A将资产放入子目录(以保持清洁)。1 e, k! N+ k! n; z
将代码内容保存在子包中(以防有人想在你的二进制文件之外重用)。# g- }5 V( a* j. z' M" ]9 u' c0 G
在 repo 的根目录包含一个设置脚本,便于搜索。  G$ G7 `; i. p
下载、构建、安装和设置仍然只有两个步骤:
; G6 |1 z4 |9 ^6 `” go get ”: 下载安装 go 代码,资产子目录
) {! Y8 n- }8 ?# h: b: J$GOPATH//setup.sh:将资产分配到正确的位置并安装服务
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则