回答

收藏

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

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

我开始变得更加复杂的 go 项目,望以这种方式安排文件系统,以减轻疼痛。
6 I9 H3 q, W8 o% k有没有很好的例子来解释什么是有意义的?
" Q1 N: N* X  d/ z: F6 B7 V                                                                ; l' K" B' L5 Z% `9 l. w
    解决方案:                                                               
8 A9 V3 U$ B, @+ {+ q" a                                                                Go 代码必须保存工作区中! I* T# C; q+ Z  G. _' P
工作区是目录层次结构,其根目录包括三个目录:
8 E1 T6 ]  ~) Xsrc 包含组织包装 Go $ Y4 @* f' A! [9 @7 i( `
pkg 包含包对象和" p, T. L9 \; a( x& q
bin 包含可执行命令。
在go tool构建源码包和安装产生的二进制文件pkg和bin目录。$ x% t9 D; Q+ y% Z- g; x" Y
该src子目录通常包含多个版本的控制存储(如 Git 或 Mercurial),开发一个或多个源包进行跟踪。
2 a4 l- u* ^; m, {. R
    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
    2 j/ j# K. N- Y3 p4 x$ h% Y
那篇文章包括以下提示:  M, g& k- p8 W4 m: C( X& Q% K4 A. R
将二进制文件与应用程序分开将main.go在同一个包里,文件和我的应用逻辑组合有两个结果:
7 M) \3 ~! A3 z4 t: U8 K它使我的应用程序无法用作库。
: z, U7 b1 e& Q; O1 G  O我只能有一个应用程序二进制文件。
我发现解决这个问题的最好方法是cmd在我的项目中简单地使用 目录,每个子目录都是应用程序二进制文件。% {& q: |# u+ v' C% W
    camlistore/  cmd/    camget/       main.go    cammount/       main.go    camput/       main.go    camtool/       main.go# {2 q1 n  @- N" F3 G: k8 ]
库驱动开发将main.go从根目录中删除文件,允许您从图书馆的角度构建应用程序。您的应用程序二进制文件只是应用程序库的客户端。
3 S8 v7 u+ w2 D8 ^. ?有时你可能希望用户以多种方式互动,所以你可以创建多个二进制文件。* |# J, m/ c4 q5 [; r& K. H$ }
例如,如果你有 adder包,可以让用户把数字加在一起,你可能想发布命令行版本和网络版本。
) `( B4 h) I% ^4 W7 w, O. A你可以很容易地组织你的项目:
3 [3 G: l: B2 y2 O, t  D* ^2 d7 f
    adder/  adder.go  cmd/    adder/       main.go    adder-server/       main.go+ o; i: s0 w5 Y- h# g3 j/ i: p3 ^
用户可以使用省略号通过go get”安装“adder应用程序二进制文件:# n, R0 o/ V- `% a- [
    $ go get github.com/benbjohnson/adder/...+ @1 ]9 `0 s1 y+ d* ]
看,您的用户安装了  adder”和“ adder-server”!$ x, ?8 I& a0 U# @
不要对子包发疯通常我的项目类型非常相关,所以从可用性到 API 从角度看更合适。; D% H1 o/ _6 G! W5 @3 D) [# l: K8 R
这些类型也可以使用它们之间未导出的调用来维持 API 小而清晰。
5 f7 X" a  ^& N( ~5 D3 j[ol]将相关类型和代码组合在每个文件中。如果您的类型和函数组织得很好,我发现文件通常在 200到 500 SLOC 之间。这听起来可能很多,但我发现它很容易导航。1000 SLOC 通常是我对单个文件的上限。
8 h3 T0 `) W% o! S) R组织文件顶部最重要的类型,并在文件底部增加重要性递减的类型。- @& t, x& e# g) _6 K# @5 J
一旦你的应用程序开始超过 10,000 SLOC,你应该仔细评估它是否可以分解为更小的项目。[/ol]注:最终的做法并不总是好的:
  x8 Q; L* z& w/ x; F; N3 e对不起,我不能同意。& I* G$ V/ i6 W( @: r' R/ R
将类型分离到文件有助于代码管理、可读性、可维护性和可测试性。& C5 q3 x7 A0 [8 g& X
还可以保证单一职责,遵循开放/封闭的原则......
+ e5 \+ |2 `9 J不允许循环依赖的规则是强迫我们有一个清晰的包结构。4 d7 u4 I" }$ F8 y
你能找到你能找到GitHub 代码布局中描述的经典布局:
7 G4 U$ t. w8 B2 S. n5 M两个应用程序和库位于 Github 上,每个仓库都在自己的仓库里。
9 S: g: v1 z# R1 e& P0 `* O, z$GOPATH是项目的根 - 你的每一个 Github 存储库将在以下文件夹中检测到$GOPATH。0 f. ^0 D; g) o
您的代码布局如下所示:* v! g; e+ B: ^5 q
    $GOPATH/    src/          github.com/              jmcvetta/                  useless/                      .git/                      useless.go                    useless_test.go                    README.md                uselessd/                      .git/                      uselessd.go                    uselessd_test.go                    README.md
    * V! _& f- l' m* {+ B4 ~
下面的每个文件夹src/github.com/jmcvetta都是单独的 git checkout 根目录。& K9 \) C% @; [4 N0 x# J
但是,在这里reddit 页面中,这引起了一些批评:
5 i  a) ~4 s) h3 G5 `7 q. E7 J我强烈建议不要以你的方式建 repo,它会破坏 go get”,这是 Go 最有用的东西之一。
  B% R6 i+ i" U1 r* p1 a为了解 Go 的人写代码要好得多,因为他们最有可能是编译它的人。
( j: O0 T+ ^5 T& n0 K3 K5 S至少对于那些不这样做的人,他们会感受到这种语言。
/ Q! d& t8 L2 r8 [5 d1 N: x# C把主包放在 repo 根目录。
$ q6 [/ w# o5 j0 S将资产放入子目录(以保持清洁)。; `& L" h6 N- w& ?* R% W' j$ ?
将代码内容保存在子包中(以防有人想在你的二进制文件之外重用)。
# H6 R- K0 C5 \" Z2 y' F在 repo 的根目录包含一个设置脚本,便于搜索。5 @) i2 b$ x3 D: `. r
下载、构建、安装和设置仍然只有两个步骤:9 @: I( h; K0 W* Z' b" Z
” go get ”: 下载安装 go 代码,资产子目录
! g  _! b# h0 @; ~" Q( m0 `$GOPATH//setup.sh:将资产分配到正确的位置并安装服务
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则