回答

收藏

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

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

我开始变得更加复杂的 go 项目,望以这种方式安排文件系统,以减轻疼痛。
6 j7 V  P0 |) i: r5 l有没有很好的例子来解释什么是有意义的?
+ A4 }# u0 I. @, _: y, a* i$ s: H9 W                                                               
6 _& _& l. x( v# i4 k$ E    解决方案:                                                                $ M0 J8 U+ ]" f
                                                                Go 代码必须保存工作区中
5 l. `+ U# H3 P6 V3 q/ I. h9 X! G% A工作区是目录层次结构,其根目录包括三个目录:2 m$ ]6 H( l9 Z
src 包含组织包装 Go 9 \9 V& \# \8 |
pkg 包含包对象和
8 N1 f! O" ~5 d2 e- h- K# d- nbin 包含可执行命令。
在go tool构建源码包和安装产生的二进制文件pkg和bin目录。
1 d- L, d  O5 g该src子目录通常包含多个版本的控制存储(如 Git 或 Mercurial),开发一个或多个源包进行跟踪。# K2 ~! b3 A4 g* }- V
    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 source9 {9 |% ?  ~, S% E: q+ |: M
那篇文章包括以下提示:/ k5 q4 Q* O  R0 z
将二进制文件与应用程序分开将main.go在同一个包里,文件和我的应用逻辑组合有两个结果:
% d$ ?" O( U3 e$ s* S! R# I- U它使我的应用程序无法用作库。
7 K# w: T$ D/ t9 q8 G( w6 e) i我只能有一个应用程序二进制文件。
我发现解决这个问题的最好方法是cmd在我的项目中简单地使用 目录,每个子目录都是应用程序二进制文件。
  T( J3 l! V* A% _- \, W: J
    camlistore/  cmd/    camget/       main.go    cammount/       main.go    camput/       main.go    camtool/       main.go
    / A1 e& ?9 g9 c
库驱动开发将main.go从根目录中删除文件,允许您从图书馆的角度构建应用程序。您的应用程序二进制文件只是应用程序库的客户端。& P- |" H8 e  k
有时你可能希望用户以多种方式互动,所以你可以创建多个二进制文件。" w6 |  A6 L6 C$ f
例如,如果你有 adder包,可以让用户把数字加在一起,你可能想发布命令行版本和网络版本。
3 t. x& y% s. a; q  v你可以很容易地组织你的项目:) {3 E8 X4 \3 Y
    adder/  adder.go  cmd/    adder/       main.go    adder-server/       main.go
    / ]  R% K8 x, L5 g
用户可以使用省略号通过go get”安装“adder应用程序二进制文件:5 G  M' V  C, ^7 @7 @( ^( k9 }
    $ go get github.com/benbjohnson/adder/...
    % ~, z/ }1 [0 S8 K% V. c
看,您的用户安装了  adder”和“ adder-server”!7 z+ j$ G# D3 i! |
不要对子包发疯通常我的项目类型非常相关,所以从可用性到 API 从角度看更合适。
- e( l5 m7 k1 V! }' g- i( w* Q这些类型也可以使用它们之间未导出的调用来维持 API 小而清晰。
! @# X. p  J" d- u/ q: A[ol]将相关类型和代码组合在每个文件中。如果您的类型和函数组织得很好,我发现文件通常在 200到 500 SLOC 之间。这听起来可能很多,但我发现它很容易导航。1000 SLOC 通常是我对单个文件的上限。
- Z' n. M5 y) s/ ?组织文件顶部最重要的类型,并在文件底部增加重要性递减的类型。
2 r, z! H# e& y, E9 R一旦你的应用程序开始超过 10,000 SLOC,你应该仔细评估它是否可以分解为更小的项目。[/ol]注:最终的做法并不总是好的:
( j5 O3 i. |* d( c8 B6 Q$ {对不起,我不能同意。
1 @5 G0 i: X! x4 h- p) _0 \" A/ s+ T将类型分离到文件有助于代码管理、可读性、可维护性和可测试性。$ v4 f- b( ~! _  u; `( I
还可以保证单一职责,遵循开放/封闭的原则......
; \  J1 V" j, m7 }不允许循环依赖的规则是强迫我们有一个清晰的包结构。) `& K$ |. M$ Q
你能找到你能找到GitHub 代码布局中描述的经典布局:" y3 S% C2 o1 |+ w
两个应用程序和库位于 Github 上,每个仓库都在自己的仓库里。
1 v; _, U4 t0 Y. X  [$GOPATH是项目的根 - 你的每一个 Github 存储库将在以下文件夹中检测到$GOPATH。
+ G1 d/ P& M/ ]: X3 w* T您的代码布局如下所示:: @9 m3 _! u" o* T) d2 T- L1 R
    $GOPATH/    src/          github.com/              jmcvetta/                  useless/                      .git/                      useless.go                    useless_test.go                    README.md                uselessd/                      .git/                      uselessd.go                    uselessd_test.go                    README.md
    % `: ]" t" F1 I$ @4 `  G1 c
下面的每个文件夹src/github.com/jmcvetta都是单独的 git checkout 根目录。- v' B/ y! v2 z9 K
但是,在这里reddit 页面中,这引起了一些批评:, `' P  E) W. c9 R! D- M! B
我强烈建议不要以你的方式建 repo,它会破坏 go get”,这是 Go 最有用的东西之一。( b4 f" F) L% W( U7 ?2 w* ?$ Z4 ^9 e1 Z. H
为了解 Go 的人写代码要好得多,因为他们最有可能是编译它的人。
) R- j5 U: x6 q7 K0 ~, r至少对于那些不这样做的人,他们会感受到这种语言。5 P0 Q, t% n# T5 [
把主包放在 repo 根目录。
- Z7 C+ _1 q' g  A4 h. K将资产放入子目录(以保持清洁)。
: Q. _, ~" g- V6 B& J3 q% \将代码内容保存在子包中(以防有人想在你的二进制文件之外重用)。
( I! d: G* Z! P- E) _在 repo 的根目录包含一个设置脚本,便于搜索。- V3 @% `% u/ a7 W) s  Z/ s7 {
下载、构建、安装和设置仍然只有两个步骤:$ E( a% }8 }9 D( N" u, v' ~
” go get ”: 下载安装 go 代码,资产子目录: W( [% e  W# K: x) K
$GOPATH//setup.sh:将资产分配到正确的位置并安装服务
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则