百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Go 项目的布局:你是怎么组织你的Go代码的?

bigegpt 2024-08-24 23:21 2 浏览

点击上方蓝色“Go语言中文网”关注我们,领全套Go资料,每天学习 Go 语言

本文还是基于 GOPATH,这块忽略,其他部分可以借鉴

读过了 `Tour of Go`[1],在 https://play.studygolang.com/[2] 上把玩过,然后你感觉你准备好写一些代码了。很棒!但是,你不确定该如何组织你的项目。可以将代码放在你想放的任意地方吗?有没有组织代码的标准方式?如果想有多个应用程序的二进制文件呢?“go getable” 是指什么?你可能会问自己这些问题。

首先,你必须了解 Go 的工作空间。`How to Write Go Code`[3] 是个很好的起点。缺省地,Go 将所有代码保管在同一个工作空间,并期望所有代码都在同一个工作空间。这个地方由环境变量 GOPATH 来标识。对你来说这意味着什么?意味着你必须将代码放在默认的工作空间或者必须修改 GOPATH 环境变量,指向你自己的代码位置。不管哪种方式,项目的真正源代码都需要放在 src 子目录下(即 $GOPATH/src/your_project 或 $GOPATH/src/github.com/your_github_username/your_project)。技术上讲,如果你无需导入外部包且使用相对路径导入自己的代码,你的工程不一定非要放在工作空间里,但不推荐这样做。不过玩具项目或概念验证(Poc)项目这么做是可以的。Go 1.1 确实引入了模块的概念,允许你将项目代码放在 GOPATH 之外,且不受上述的导入限制,但直到现在这还是一个实验性的功能。

你已经将你的项目目录放在正确的地方。接下来呢?

对于你是唯一开发者的概念验证(Poc)项目或特别小的项目,将项目代码都写在根目录下的 main.go 里就够了。如果知道你的项目将会变得足够大或者它会上生产环境,而且其他人会贡献代码,那你就应该考虑至少采用这里罗列的项目布局样式中的一些。

有一些项目布局样式在 Go 生态系统中脱颖而出。cmd 和 pkg 目录是最常见的两个样式。你应当采用这些样式,除非你的项目特别小。

cmd 布局样式在你需要有多个应用程序二进制文件时十分有用。每个二进制文件拥有一个子目录(即 your_project/cmd/your_app)。这个样式帮助保持你的项目下的包(project/package) ‘go gettable’。什么意思?这意味着你可以使用 go get 命令拉取(并安装)你的项目,项目的应用程序以及库(比如,go get github.com/your_github_username/your_project/cmd/appxg)。你不必非要拆分应用程序文件,通过设置正确的 go build 标记你可以构建每个应用程序,但是由于不知道该构建哪个应用程序, go get 就无法正常工作了。官方的 Go tools[4] 是 cmd 布局样式的一个例子。很多知名的项目也使用了同样的样式:Kubernetes[5], Docker[6], Prometheus[7], Influxdb[8]。

pkg 布局样式也十分受欢迎。对新手 Go 开发者来讲这是最容易混淆的一个包结构概念,因为 Go 的工作空间就有一个同名的目录但那个目录有不同的用途(用来存储 Go 编译器构建的包的 object 文件)。pkg 目录是放置公共库的地方。它们可以被你的应用内部使用。也可供外部项目使用。这是你和你代码的外部使用者之间的非正式协定。其它项目会导入这些库并期望它们正常工作,所以在把东西放到这里前请三思。很多知名的项目使用了这个样式:Kubernetes[9], Docker[10], Grafana[11], Influxdb[12], Etcd[13].

pkg 目录下的某些库并不总是为了公共使用。为什么呢?因为很多现有的 Go 项目诞生在能隐藏内部包之前。一些项目将内部库放在 pkg 目录下,以便保持与其它部分代码结构的一致。另外一些项目将内部库放置在 pkg 目录之外另外的目录里。Go 1.4[14] 引入了使用 internal 隐藏内部库的能力。什么意思呢?如果你将代码放在 ‘internal’目录,外部项目则无法导入那些代码。即使是项目内部的其它代码,如果不在 internal 目录的父目录里,也无法访问这些内部代码。这个功能使用还不广泛因为它相对较新;但是作为一个额外(在 Go 用大小写区分函数可见性的规则之外)的控制层它有极大价值。很多知名的项目使用了这个样式:Dep[15], Docker[16], Nsq[17], Go Ethereal[18], Contour[19]。

internal 目录是放置私有包的地方。你可以选择性地添加额外的结构来分离内部共享的库(比如,your_project/internal/pkg/your_private_lib)以及不希望别人导入的应用程序代码(比如, your_project/internal/app/your_app)。当你将全部私有代码都放在 ‘internal’ 目录,cmd 目录下的应用程序就可以被约束成一些小文件,其只需定义对应于应用程序二进制文件的 ‘main’ 函数。其余代码都从 internal 或 pkg 目录导入(Heptio 中的 ark[20],以及 Grafana 中的 loki[21],是这个 微型 main 函数 包样式的好例子)。

如果你 fork 并修改了外部项目的一块该如何?有些项目将这些代码放在 pkg 目录下,但更好的做法是将它放在顶层目录下的 third_party 目录,以便将你自己的代码和你从别人那里借用的代码区分开来。

你在项目里导入的外部包呢?它们去哪里?你有几个选项。你可以将它们放在项目以外。使用 go get 安装的包将保存在你的 Go 工作空间。大部分情况下可以正常工作,但视具体包而定,它可能会变得脆弱和不可预测,因为别人在构建你的项目时他们可能会拿到这个包的一个不向后兼容的版本。解决办法是 ‘vendoring’。使用 ‘vendoring’ 你通过将依赖与项目一起提交来将它们固定。Go 1.6[22] 导入了一种标准的方式来 ‘vendor’ 外部包(在 Go 1.5 中是实验性功能)。将外部包放在 vendor 目录。这与 third_party 目录有何区别呢?如果你导入了外部代码且原样使用它就放在 vendor 目录。如果你使用的是修改版的外部包就放在 third_party 目录。

如果你想学习更多关于其他 Go 项目使用的项目结构请阅读 ‘Analysis of the Top 1000 Go Repositories’[23]。它有点陈旧,不过依然有用。

一个真正的项目也会有另外的目录。你可以使用这个布局模版作为你的 Go 项目的起点:https://github.com/golang-standards/project-layout[24]。它涵盖了这篇博客里描述的 Go 项目布局样式并包括很多你需要的支持目录。

现在是时候写些代码了!如果你还没安装 Go 请查看这个 quick setup guide for Mac OS X[25] (其他平台的安装也是类似的)。如果还没浏览过请你浏览 ‘Tour of Go’[26] ,然后读一下 ’50 Shades of Go’[27] 去了解 Go 中最常见的坑,这会在你开始写代码和调试代码时节省很多时间。

  • Golang[28]
  • Go[29]
  • Standards[30]
  • Project Structure[31]

via: https://medium.com/golang-learn/go-project-layout-e5213cdcfaa2

作者:Kyle C. Quest[32]译者:krystollia[33]校对:DingdingZhou[34]

本文由 GCTT[35] 原创编译,Go 中文网[36] 荣誉推出

参考资料

[1]

Tour of Go: https:/tour.studygolang.com

[2]

https://play.studygolang.com/: https://play.studygolang.com/

[3]

How to Write Go Code: https://golang.org/doc/code.html

[4]

Go tools: https://github.com/golang/tools/tree/master/cmd

[5]

Kubernetes: https://github.com/kubernetes/kubernetes/tree/master/cmd

[6]

Docker: https://github.com/moby/moby/tree/master/cmd

[7]

Prometheus: https://github.com/prometheus/prometheus/tree/master/cmd

[8]

Influxdb: https://github.com/influxdata/influxdb/tree/master/cmd

[9]

Kubernetes: https://github.com/kubernetes/kubernetes/tree/master/pkg

[10]

Docker: https://github.com/moby/moby/tree/master/pkg

[11]

Grafana: https://github.com/grafana/grafana/tree/master/pkg

[12]

Influxdb: https://github.com/influxdata/influxdb/tree/master/pkg

[13]

Etcd: https://github.com/coreos/etcd/tree/master/pkg

[14]

Go 1.4: https://golang.org/doc/go1.4

[15]

Dep: https://github.com/golang/dep/tree/master/internal

[16]

Docker: https://github.com/moby/moby/tree/master/internal

[17]

Nsq: https://github.com/nsqio/nsq/tree/master/internal

[18]

Go Ethereal: https://github.com/ethereum/go-ethereum/tree/master/internal

[19]

Contour: https://github.com/heptio/contour/tree/master/internal

[20]

ark: https://github.com/heptio/ark/blob/master/cmd/ark/main.go

[21]

loki: https://github.com/grafana/loki/blob/master/cmd/loki/main.go

[22]

Go 1.6: https://golang.org/doc/go1.6

[23]

‘Analysis of the Top 1000 Go Repositories’: http://blog.sgmansfield.com/2016/01/an-analysis-of-the-top-1000-go-repositories/

[24]

https://github.com/golang-standards/project-layout: https://github.com/golang-standards/project-layout

[25]

quick setup guide for Mac OS X: https://medium.com/golang-learn/quick-go-setup-guide-on-mac-os-x-956b327222b8

[26]

‘Tour of Go’: https://tour.golang.org/

[27]

’50 Shades of Go’: https://tour.golang.org/

[28]

Golang: https://medium.com/tag/golang

[29]

Go: https://medium.com/tag/go

[30]

Standards: https://medium.com/tag/standards

[31]

Project Structure: https://medium.com/tag/project-structure

[32]

Kyle C. Quest: https://medium.com/@CloudImmunity

[33]

krystollia: https://github.com/krystollia

[34]

DingdingZhou: https://github.com/DingdingZhou

[35]

GCTT: https://github.com/studygolang/GCTT

[36]

Go 中文网: https://studygolang.com/

相关推荐

AI「自我复制」能力曝光,RepliBench警示:大模型正在学会伪造身份

科幻中AI自我复制失控场景,正成为现实世界严肃的研究课题。英国AISI推出RepliBench基准,分解并评估AI自主复制所需的四大核心能力。测试显示,当前AI尚不具备完全自主复制能力,但在获取资源...

【Python第三方库安装】介绍8种情况,这里最全看这里就够了!

**本图文作品主要解决CMD或pycharm终端下载安装第三方库可能出错的问题**本作品介绍了8种安装方法,这里最全的python第三方库安装教程,简单易上手,满满干货!希望大家能愉快地写代码,而不要...

pyvips,一个神奇的 Python 库!(pythonvip视频)

大家好,今天为大家分享一个神奇的Python库-pyvips。在图像处理领域,高效和快速的图像处理工具对于开发者来说至关重要。pyvips是一个强大的Python库,基于libvips...

mac 安装tesseract、pytesseract以及简单使用

一.tesseract-OCR的介绍1.tesseract-OCR是一个开源的OCR引擎,能识别100多种语言,专门用于对图片文字进行识别,并获取文本。但是它的缺点是对手写的识别能力比较差。2.用te...

实测o3/o4-mini:3分钟解决欧拉问题,OpenAI最强模型名副其实!

号称“OpenAI迄今为止最强模型”,o3/o4-mini真实能力究竟如何?就在发布后的几小时内,网友们的第一波实测已新鲜出炉。最强推理模型o3,即使遇上首位全职提示词工程师RileyGoodsid...

使用Python将图片转换为字符画并保存到文件

字符画(ASCIIArt)是将图片转换为由字符组成的艺术作品。利用Python,我们可以轻松实现图片转字符画的功能。本教程将带你一步步实现这个功能,并详细解释每一步的代码和实现原理。环境准备首先,你...

5分钟-python包管理器pip安装(python pip安装包)

pip是一个现代的,通用、普遍的Python包管理工具。提供了对Python包的查找、下载、安装、卸载的功能,是Python开发的基础。第一步:PC端打开网址:选择gz后缀的文件下载第二步:...

网络问题快速排查,你也能当好自己家的网络攻城狮

前面写了一篇关于网络基础和常见故障排查的,只列举了工具。没具体排查方式。这篇重点把几个常用工具的组合讲解一下。先有请今天的主角:nslookup及dig,traceroute,httping,teln...

终于把TCP/IP 协议讲的明明白白了,再也不怕被问三次握手了

文:涤生_Woo下周就开始和大家成体系的讲hadoop了,里面的每一个模块的技术细节我都会涉及到,希望大家会喜欢。当然了你也可以评论或者留言自己喜欢的技术,还是那句话,希望咱们一起进步。今天周五,讲讲...

记一次工控触摸屏故障的处理(工控触摸屏维修)

先说明一下,虽然我是自动化专业毕业,但已经很多年不从事现场一线的工控工作了。但自己在单位做的工作也牵涉到信息化与自动化的整合,所以平时也略有关注。上一周一个朋友接到一个活,一家光伏企业用于启动机组的触...

19、90秒快速“读懂”路由、交换命令行基础

命令行视图VRP分层的命令结构定义了很多命令行视图,每条命令只能在特定的视图中执行。本例介绍了常见的命令行视图。每个命令都注册在一个或多个命令视图下,用户只有先进入这个命令所在的视图,才能运行相应的命...

摄像头没图像的几个检查方法(摄像头没图像怎么修复)

背景描述:安防监控项目上,用户的摄像头运行了一段时间有部分摄像头不能进行预览,需要针对不能预览的摄像头进行排查,下面列出几个常见的排查方法。问题解决:一般情况为网络、供电、设备配置等情况。一,网络检查...

小谈:必需脂肪酸(必需脂肪酸主要包括)

必需脂肪酸是指机体生命活动必不可少,但机体自身又不能合成,必需由食物供给的多不饱和脂肪酸(PUFA)。必需脂肪酸主要包括两种,一种是ω-3系列的α-亚麻酸(18:3),一种是ω-6系列的亚油酸(18:...

期刊推荐:15本sci四区易发表的机械类期刊

  虽然,Sci四区期刊相比收录在sci一区、二区、三区的期刊来说要求不是那么高,投稿起来也相对容易一些。但,sci四区所收录的期刊中每本期刊的投稿难易程度也是不一样的。为方便大家投稿,本文给大家推荐...

be sick of 用法考察(be in lack of的用法)

besick表示病了,做谓语.本身是形容词,有多种意思.最通常的是:生病,恶心,呕吐,不适,晕,厌烦,无法忍受asickchild生病的孩子Hermother'sverysi...