小白学go基础03-了解Go项目的项目结构

这篇具有很好参考价值的文章主要介绍了小白学go基础03-了解Go项目的项目结构。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

我们先来看看第一个Go项目——Go语言自身——的项目结构是什么样的。Go项目的项目结构自1.0版本发布以来一直十分稳定,直到现在Go项目的顶层结构基本没有大的改变。

截至Go项目commit 1e3ffb0c(2019.5.14),Go1.0 项目结构如下:

$ tree -LF 1 ~/go/src/github.com/golang/go
./go
├── api/
├── AUTHORS
├── CONTRIBUTING.md
├── CONTRIBUTORS
├── doc/
├── favicon.ico
├── lib/
├── LICENSE
├── misc/
├── PATENTS
├── README.md
├── robots.txt
├── src/
└── test/

作为Go语言的创世项目,Go的项目结构的布局对后续的Go语言项目具有重要的参考意义,尤其是早期Go项目中src目录下面的结构,更是在后续被Go社区作为Go应用项目结构的模板广泛使用。

以早期的Go 1.3版本的src目录下的结构为例

$ tree -LF 1 ./src
./src
├── all.bash*
├── all.bat
├── all.rc*
├── clean.bash*
├── clean.bat
├── clean.rc*
├── cmd/
├── lib9/
├── libbio/
├── liblink/
├── make.bash*
├── make.bat
├── Make.dist
├── make.rc*
├── nacltest.bash*
├── pkg/
├── race.bash*
├── race.bat
├── run.bash*
├── run.bat
├── run.rc*
└── sudo.bash*

关于上面src目录下的结构,笔者总结了以下三个特点。

1)代码构建的脚本源文件放在src下面的顶层目录下。

2)src下的二级目录cmd下面存放着Go工具链相关的可执行文件(比如go、gofmt等)的主目录以及它们的main包源文件。

3)src下的二级目录pkg下面存放着上面cmd下各工具链程序依赖的包、Go运行时以及Go标准库的源文件。如下所示

$ tree -LF 1 ./pkg
./pkg
...
├── flag/
├── fmt/
├── go/
├── io/
├── log/
├── math/
...
├── syscall/
├── testing/
├── text/
├── time/
├── unicode/
└── unsafe/

在Go 1.3版本以后至今,Go项目下的src目录发生了几次结构上的变动。

● Go 1.4 版本删除了Go源码树中src/pkg/xxx中的pkg这一层级目录,改为直接使用src/xxx。

● Go 1.4版本在src下面增加internal目录,用于存放无法被外部导入、仅Go项目自用的包。

● Go 1.6版本在src下面增加vendor目录,但Go项目自身真正启用vendor机制是在Go 1.7版本中。vendor目录中存放了Go项目自身对外部项目的依赖,主要是golang.org/x下的各个包,包括net、text、crypto等。该目录下的包会在每次Go版本发布时更新。

● Go 1.13版本在src下面增加了go.mod和go.num,实现了Go项目自身的go module迁移。Go项目内所有包被放到名为std的module下面,其依赖的包依然是golang.org/x下的各个包。这个可以算是go 项目目录结构以及包管理的一个重大改动。

// Go 1.13版本Go项目src下面的go.mod
module std
go 1.12
require (
golang.org/x/crypto v0.0.0-20200124225646-8b5121be2f68
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
golang.org/x/sys v0.0.0-20190529130038-5219a1e1c5f8 // indirect
golang.org/x/text v0.3.2 // indirect
)

下面是Go 1.16版本src目录下的完整布局:

├── Make.dist
├── README.vendor
├── all.bash*
├── all.bat
├── all.rc*
├── bootstrap.bash*
├── buildall.bash*
├── clean.bash*
├── clean.bat
├── clean.rc*
├── cmd/
├── cmp.bash
├── go.mod
	├── go.sum
├── internal/
├── make.bash*
├── make.bat
├── make.rc*
├── race.bash*
├── race.bat
├── run.bash*
├── run.bat
├── run.rc*
├── testdata/
...
└── vendor/

1. Go项目结构的最小标准布局

关于Go应用项目结构的标准布局是什么样子的,Go官方团队始终没有给出参考标准。不过作为Go语言项目的技术负责人,Russ Cox在一个开源项目的issue中给出了他关于Go项目结构的最小标准布局 的想法。他认为Go项目的最小标准布局应该是这样的

// 在Go项目仓库根路径下
- go.mod
- LICENSE
- xx.go
- yy.go
...- go.mod
- LICENSE
- package1
	- package1.go
- package2
	- package2.go
...

pkg、cmd、docs这些目录不应该成为Go项目标准结构的一部分,至少不是必需的。笔者认为Russ
Cox给出的最小标准布局与Go一贯崇尚的“简单”哲学是一脉相承的,这个布局很灵活,可以满足各种Go项目的需求。

但是在Russ Cox阐述上述最小标准之前,Go社区其实是处于“无标准”状态的,早期Go语言自身项目的结构布局对现存的大量Go开源项目的影响依然存在,对于一些规模稍大些的Go应用项目,我们势必会在上述“最小标准布局”的基础上进行扩展。而这种扩展显然不会是盲目的,还是会参考Go语言项目自身的结构布局,于是就有了下面的非官方标准的建议结构布局。

2. 以构建二进制可执行文件为目的的Go项目结构

基于Go语言项目自身的早期结构以及后续演进,Go社区在多年的Go语言实践积累后逐渐形成了一种典型项目结构,这种结构与Russ Cox的最小标准布局是兼容的,如下图所示:

小白学go基础03-了解Go项目的项目结构,go,goland,go实战,golang,开发语言,后端
上图所示就是一个支持(在cmd下)构建二进制可执行文件的典型Go项目的结构,我们分别来看一下各个重要目录的用途。

cmd目录:存放项目要构建的可执行文件对应的main包的源文件。如果有多个可执行文件需要构建,则将每个可执行文件的main包单独放在一个子目录中,比如图中的app1、app2。cmd目录下的各app的main包将整个项目的依赖连接在一起,并且通常来说,main包应该很简洁。我们会在main包中做一些命令行参数解析、资源初始化、日志设施初始化、数据库连接初始化等工作,之后就会将程序的执行权限交给更高级的执行控制对象。有一些Go项目将cmd这个名字改为app,但其功用并没有变。

pkg目录:存放项目自身要使用并且同样也是可执行文件对应main包要依赖的库文件。该目录下的包可以被外部项目引用,算是项目导出包的一个聚合。有些项目将pkg这个名字改为lib,但该目录的用途不变。由于Go语言项目自身在1.4版本中去掉了pkg这一层目录,因此有一些项目直接将包平铺到项目根路径下,但笔者认为对于一些规模稍大的项目,过多的包会让项目顶层目录不再简洁,显得很拥挤,因此个人建议对于复杂的Go项目保留pkg目录。

Makefile:这里的Makefile是项目构建工具所用脚本的“代表”,它可以代表任何第三方构建工具所用的脚本。Go并没有内置如make、bazel等级别的项目构建工具,对于一些规模稍大的项目而言,项目构建工具似乎不可缺少。在Go典型项目中,项目构建工具的脚本一般放在项目顶层目录下,比如这里的Makefile;对于构建脚本较多的项目,也可以建立build目录,并将构建脚本的规则属性文件、子构建脚本放入其中。

go.mod和go.sum:Go语言包依赖管理使用的配置文件。类似java 项目中pom.xml 文件。Go 1.11版本引入Go module机制,Go 1.16版本中,Go module成为默认的依赖包管理和构建机制。因此对于新的Go项目,建议基于Go module进行包依赖管理。对于没有使用Go module进行包管理的项目(可能主要是一些使用Go 1.11以前版本的Go项目),这里可以换为dep的Gopkg.toml和Gopkg.lock,或者glide的glide.yaml和glide.lock等。

● vendor目录(可选):vendor是Go 1.5版本引入的用于在项目本地缓存特定版本依赖包的机制。在引入Go module机制之前,基于vendor可以实现可重现的构建(reproducible build),保证基于同一源码构建出的可执行程序是等价的。Go module本身就可以实现可重现的构建而不需要vendor,当然Go module机制也保留了vendor目录(通过go mod vendor可以生成vendor下的依赖包;通过go build -mod=vendor可以实
现基于vendor的构建),因此这里将vendor目录视为一个可选目录。一般我们仅保留项目根目录下的vendor目录,否则会造成不必要的依赖选择的复杂性。

Go 1.11引入的module是一组同属于一个版本管理单元的包的集合。Go支持在一个项目/仓库中存在多个module,但这种管理方式可能要比一定比例的代码重复引入更多的复杂性。因此,如果项目结构中存在版本管理的“分歧”,比如app1和app2的发布版本并不总是同步的,那么笔者建议将项目拆分为多个项目(仓库),每个项目单独作为一个module
进行版本管理和演进

3. 以只构建库为目的的Go项目结构

Go 1.4发布时,Go语言项目自身去掉了src下的pkg这一层目录,这个结构上的改变对那些以只构建库为目的的Go库类型项目结构有一定的影响。我们来看一个典型的Go语言库类型项目的结构布局,如下图所示:

小白学go基础03-了解Go项目的项目结构,go,goland,go实战,golang,开发语言,后端
我们看到库类型项目结构与Go项目的最小标准布局也是兼容的,但比以构建二进制可执行文件为目的的Go项目要简单一些。

● 去除了cmd和pkg两个子目录:由于仅构建库,没必要保留存放二进制文件main包源文件的cmd目录;由于Go库项目的初衷一般都是对外部(开源或组织内部公开)暴露API,因此也没有必要将其单独聚合到pkg目录下面了。

● vendor不再是可选目录:对于库类型项目而言,不推荐在项目中放置vendor目录去缓存库自身的第三方依赖,库项目仅通过go.mod(或其他包依赖管理工具的manifest文件)明确表述出该项目依赖的模块或包以及版本要求即可。

4. 关于internal目录

无论是上面哪种类型的Go项目,对于不想暴露给外部引用,仅限项目内部使用的包,在项目结构上可以通过Go
1.4版本中引入的internal包机制来实现。

以库项目为例,最简单的方式就是在顶层加入一个internal目录,将不想暴露到外部的包都放在该目录下,比如下面项目结构中的ilib1、ilib2:

// 带internal的Go库项目结构
$tree -F ./chapter2/sources/GoLibProj
GoLibProj
├── LICENSE
├── Makefile
├── README.md
├── go.mod
├── internal/
│ ├── ilib1/
│ └── ilib2/
├── lib.go
├── lib1/
│ └── lib1.go
└── lib2/
└── lib2.go

这样,根据Go internal机制的作用原理,internal目录下的ilib1、ilib2可以被以GoLibProj目录为根目录的其他目录下的代码(比如lib.go、lib1/lib1.go等)所导入和使用,但是却不可以为GoLibProj目录以外的代码所使用,从而实现选择性地暴露API包

所以了解完不同的项目类型所对应的项目结构,开发者可以在这样上面的项目结构核心的基础上根据实际需要进行扩展。文章来源地址https://www.toymoban.com/news/detail-700999.html

到了这里,关于小白学go基础03-了解Go项目的项目结构的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 小白学Go基础01-Go 语言的介绍

    Go 语言对传统的面向对象开发进行了重新思考,并且提供了更高效的复用代码的手段。Go 语言还让用户能更高效地利用昂贵服务器上的所有核心,而且它编译大型项目的速度也很快。 Go 语言开发团队花了很长时间来解决当今软件开发人员面对的问题。开发人员在为项目选择语

    2024年02月10日
    浏览(29)
  • 【Go学习之 go mod】gomod小白入门,在github上发布自己的项目(项目初始化、项目发布、项目版本升级等)

    Go语言基础之包 | 李文周的博客 Go mod的使用、发布、升级 | wei Go Module如何发布v2及以上版本 1.2.7. go mod命令 — 新溪-gordon V1.7.9 文档 golang go 包管理工具 go mod的详细介绍-腾讯云开发者社区-腾讯云 Go Mod 常见错误的原因 | walker的博客 oceanweave/testgomod 用于发布 go 包,v1 v2 版本等

    2024年02月03日
    浏览(53)
  • goland setup go env

    go env -w设置的变量,在goland中不生效,需要额外配置。 点击goland-preference,在go module里,设置go环境变量即可。

    2024年02月08日
    浏览(43)
  • 【Go】Goland下载与安装教程(详细)

    一、GoLand官网下载安装 开发环境:https://www.jetbrains.com/go/ 软件激活ToolBox: 一键Activate,激活后出现success,开发工具即可直接使用: 二、下载go语言sdk(go的标准库) 下载地址:https://golang.google.cn/dl/ 三、创建工程目录 创建一个工程目录,如 D:SoftwaresGOGoWorkstation ,这个目录

    2024年02月04日
    浏览(33)
  • MacOS goland go1.21 debug问题

    brew install dlv 安装之后在终端会显示所在目录 类似/usr/local/Cellar/delve/1.21.0/bin 在文件系统中找到goland 右击选择show package contents - Contents - plugins - go 尝试替换 其中对应系统 的 dlv 结果还是不行 然后打开应用goland Help → Edit Custom Properties 增加以下代码: dlv.path=/usr/local/Cellar/del

    2024年02月11日
    浏览(29)
  • go基础07-了解map实现原理并高效使用

    对于C程序员出身的Gopher来说,map类型是和切片、interface一样能让他们感受到Go语言先进性的重要语法元素。map类型也是Go语言中最常用的数据类型之一。 一些有关Go语言的中文教程或译本将map称为字典或哈希表,但在这里我选择不译,直接使用map。map是Go语言提供的一种抽象数

    2024年02月09日
    浏览(44)
  • Go语言集成开发环境(IDE):GoLand 2023中文

    GoLand 2023是一款由JetBrains开发的现代化、功能丰富的Go语言集成开发环境(IDE) 。它提供了智能代码提示和自动完成、强大的内置调试器以及代码重构工具,帮助开发者提高编码效率并确保代码质量。GoLand 2023还支持多种版本控制系统,集成了测试工具,并提供了代码审查功能

    2024年02月06日
    浏览(39)
  • Go 开发IDE全览:GoLand VS VSCode全面解析

    在软件开发的世界里,开发环境的选择与配置是成功项目的基础之一。特别是在Go(又名Golang)这样一个逐渐获得主流认同、在微服务和云计算领域有着广泛应用的编程语言中,选择合适的开发工具就显得尤为重要。虽然Go语言自身具有简洁、高效的特点,但好的开发工具能极

    2024年02月08日
    浏览(39)
  • Go开发IDE全览:GoLand vs VSCode全面解析

    关注【TechLeadCloud】,分享互联网架构、云服务技术的全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收AI产品研发负责人。 在软件开发的世界里

    2024年02月08日
    浏览(37)
  • 【Go 基础篇】Go语言结构体基本使用

    在Go语言中,结构体是一种重要的数据类型,用于定义和组织一组不同类型的数据字段。结构体允许开发者创建自定义的复合数据类型,类似于其他编程语言中的类。本文将深入探讨Go语言中结构体的定义、初始化、嵌套、方法以及与其他语言的对比,以便全面了解如何在Go中

    2024年02月10日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包