标签 RussCox 下的文章

Go,14周年[译]

本文永久链接 – https://tonybai.com/2023/11/11/go-opensource-14-years

国内的双十一购物狂欢已没有了当年的那种热闹与喧嚣,但大洋彼岸的Go团队却始终保持稳中有增的开发和语言演进节奏。今晨Go核心团队的Russ Cox代表Go语言项目团队在Go官博上发表了《Fourteen Years of Go》的博文,纪念Go语言开源14周年,并对2023年以来Go语言的演进进行了归纳总结,并对Go在其第15个年头将要做的改进给予了很高的期望。这里对博文做简单翻译,供大家参考。


今天,我们欢庆Go语言开源发布十四周年!Go在过去一年中取得了巨大的进步,发布了两个功能特性丰富的版本,并达成了其他一些重要的里程碑。

我们在2月发布了Go 1.20,在8月发布了Go 1.21,在这两个版本中,我们更多地关注实现改进而不是新语言特性。

我们在Go 1.20版本中发布了Profile-guided optimization(PGO)功能的预览版,并在Go 1.21中正式发布了该功能,它允许Go编译器读取程序的Profile,然后花更多时间对程序中运行最频繁的部分进行优化。在Go 1.21中,启用PGO后,工作负载的CPU使用率通常可以提高2%到7%。关于PGO的介绍请参阅“Go 1.21中的Profile-guided optimization”,对PGO的全面说明请参阅“PGO用户指南”。

Go从Go 1.2版本开始就支持在go test期间收集覆盖率profile数据。Go 1.20版本增加了对go build构建的二进制文件收集测试覆盖率profile数据的支持,这样你就可以在集成测试期间收集测试覆盖率数据,详情请参阅“Go集成测试的代码覆盖率”。

兼容性一直是Go的重要组成部分,我们最初对兼容性的承诺始于“Go 1和Go程序的未来”这篇文章。针对那些可能会给现有程序造成破坏但又必须要修正的重要错误,Go 1.21版本通过扩展GODEBUG的约定用法进一步改进了兼容性。请参阅博文“后向兼容性,Go 1.21和Go 2”了解概况,详情请参阅文档“Go、后向兼容性和GODEBUG”。

Go 1.21还发布了对内置工具链管理的支持,允许你像改变其他依赖的版本一样轻松地改变特定模块(module)中使用的Go工具链版本。请参阅博文“Go 1.21中的向前兼容性和工具链管理”,更多详情请参阅文档“Go工具链”。

另一个在工具链方面的重要成就是将磁盘索引集成到gopls(Go语言服务器)。这将gopls的启动延迟和内存使用缩短了3-5倍。“扩展gopls以适应不断增长的Go生态系统”一文解释了其中的技术细节。你可以通过运行以下命令确保运行最新的gopls:

$go install golang.org/x/tools/gopls@latest

Go 1.21引入了新的cmpmapsslices包 —— Go的第一个泛型标准库 —— 以及扩展了可比较类型(comparable)的集合。详情请参阅博文“所有可比较的类型”。

总体而言,我们继续完善泛型,并通过会议演讲和撰写博文来解释重要细节。今年两篇值得关注的博文是“分解类型参数”和“关于类型推断你一直想知道的事情 —— 以及更多”。

Go 1.21中另一个重要的新包是log/slog,它为标准库添加了结构化日志的官方API。请参阅“使用slog实现结构化日志”了解概况。

在对WebAssembly(Wasm)的移植方面,Go 1.21增加了在WebAssembly System Interface(WASI) preview1版本上运行的支持。WASI preview1是一种新的“操作系统”接口,支持大多数服务器端的Wasm环境。详情请参阅“Go对WASI的支持”一文。

在安全方面,我们将继续确保Go在帮助开发人员了解其依赖关系和漏洞方面处于领先地位,7月发布的Govulncheck 1.0正是这样的例子。如果你使用VS Code,可以通过Go扩展直接在编辑器中运行govulncheck。请参阅govulncheck IDE教程了解如何开始使用govulncheck。如果你使用GitHub,可以使用GitHub Action for govulncheck将运行govulncheck作为CI/CD流程的一部分。有关检查依赖项漏洞问题的更多信息,请参阅今年的Google I/O大会的演讲“使用Go和Google构建更安全的应用程序”。

另一个重要的安全里程碑是Go 1.21的高度可重现的工具链构建。详情请参阅“完全可重现的经验证的Go工具链”,包括在没有使用任何Linux工具的情况下在Mac上重现Ubuntu Linux Go工具链的演示。

这是非常繁忙的一年!

在Go的第15个年头,我们将继续努力使Go成为最佳的大规模软件工程环境。我们特别兴奋的一个变化是重新定义for循环中”:=”的语义,以消除意外别名bug的可能性。详情请参阅“在Go 1.22中修复For循环”,其中包括在Go 1.21中对此更改的预览版的说明。

感谢!

Go项目一直远不止我们在Google的Go小组。感谢所有贡献者和Go社区中的每一个人,使得今天的Go成为可能。我们衷心祝愿大家在未来一年中一切顺利。


“Gopher部落”知识星球旨在打造一个精品Go学习和进阶社群!高品质首发Go技术文章,“三天”首发阅读权,每年两期Go语言发展现状分析,每天提前1小时阅读到新鲜的Gopher日报,网课、技术专栏、图书内容前瞻,六小时内必答保证等满足你关于Go语言生态的所有需求!2023年,Gopher部落将进一步聚焦于如何编写雅、地道、可读、可测试的Go代码,关注代码质量并深入理解Go核心技术,并继续加强与星友的互动。欢迎大家加入!

img{512x368}
img{512x368}

img{512x368}
img{512x368}

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻) – https://gopherdaily.tonybai.com

我的联系方式:

  • 微博(暂不可用):https://weibo.com/bigwhite20xx
  • 微博2:https://weibo.com/u/6484441286
  • 博客:tonybai.com
  • github: https://github.com/bigwhite
  • Gopher Daily归档 – https://github.com/bigwhite/gopherdaily

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

Go项目目录该怎么组织?官方终于出指南了!

本文永久链接 – https://tonybai.com/2023/10/05/the-official-guide-of-organizing-go-project

长久以来,在Go语言进阶的学习和实践之路上,Go项目目录究竟如何布局一直是困扰大家的一个问题,这是因为Go官方针对这个问题迟迟没有给出说法,更没有提供标准供大家参考。仅有Go语言项目技术负责人Russ Cox在一个开源项目的issue中给出了他关于Go项目结构的最小标准布局的想法

熟悉我的博客/公众号的读者可能会知道,关于Go项目目录布局,我在以往文章中曾写过多次。在我的纸版书《Go语言精进之路》、极客时间的专栏Go语言第一课以及Go高级工程师训练营中,对Go项目目录组织与布局方式也都有过全面系统地说明。

我虽然很努力为大家答疑,提供的建议也很具参考价值,但这仅是我的个人观点,权威性有限,大家依然期待Go官方的说法。

近期Go官方文档集合中新增了一篇名为“Organizing a Go module”的文档,细读之后,我发现这不就是大家期待已久的Go项目目录布局的官方指南吗!

在这篇文章中,我们就来看看这份官方指南,看看官方推荐的Go项目目录布局是什么样子的。

1. Go项目的类型

我们知道Go项目(project)一般有两类:library和executable。library是以构建库为目的的Go项目,而executable则是以构建二进制可执行文件为目的的Go项目。

“Organizing a Go module”这篇文档也是按照Go项目类型为Gopher提供项目布局建议的。这篇文档将library类的项目叫作package类,executable类的项目叫作command。下面的示意图展示了“Organizing a Go module”这篇文档的说明顺序:

从图中看到,“Organizing a Go module”这篇文档总共给出7种项目的布局建议。接下来,我们就来逐一看一下。

2. 官方版Go项目目录布局指南

2.1 basic package

我们先从package类开始。最简单的package类的Go项目是basic package,下面就是一个basic package类的项目目录布局的示例:

project-root-directory/
├── go.mod
├── modname.go
└── modname_test.go

或

project-root-directory/
├── go.mod
├── modname.go
├── modname_test.go
├── auth.go
├── auth_test.go
├── hash.go
└── hash_test.go

我们看到basic package类项目非常简单,repo下面只有一个导出package,这个package包含一个或多个包源文件。以repo托管在github上为例,如果这个repo的url为github.com/someuser/modname,那么该repo下的module root和导出package的导入路径通常与repo url一致,都为github.com/someuser/modname。

你的代码要依赖该module,直接通过下面import语句便可以将该module导入:

import "github.com/someuser/modname"

注:本文的Go项目目录布局示例均来自或改自“Organizing a Go module”那篇文档。

2.2 basic command

和basic package一样,basic command类项目是以构建可执行二进制程序为目的的Go项目中最简单的一类。下面是basic command类项目的一个示例:

project-root-directory/
├── go.mod
└── main.go

或

project-root-directory/
├── go.mod
├── main.go
├── auth.go
├── auth_test.go
├── hash.go
└── hash_test.go

从示例我们可以看到,basic command类项目的repo下面只可构建出一个可执行文件,main函数放在main.go中,其他源文件也在repo根目录下,并同样放在main包中。

还是以repo托管在github上为例,如果这个repo的url为github.com/someuser/modname,那么我们可以通过下面命令安装这个command的可执行程序:

$go install github.com/someuser/modname@latest

2.3 package with supporting packages

稍复杂或规模稍大的一些package类项目,会将很多功能分拆到supporting packages中,并且通常项目作者是不希望导出这些supporting packages的,这样这些supporting packages便可以不作为暴露的API的一部分,后续重构和优化起来十分方便,对package的用户也是无感的。这样Go官方建议将这些supporting packages放入internal目录

注:internal目录是Go 1.4版本引入的机制,简单来说放在internal中的包是local的,不能导出到module之外,但module下的某些内部代码可以导入internal下的包。如今一般都会将internal放在项目的根目录下,所以项目下的所有代码都可以导入internal下的包。

下面是一个带有supporting packages的package类项目的目录布局示例:

project-root-directory/
├── go.mod
├── modname.go
├── modname_test.go
└── internal/
    ├── auth/
    │   ├── auth.go
    │   └── auth_test.go
    └── hash/
        ├── hash.go
        └── hash_test.go

modname.go或modname_test.go可以通过下面导入语句使用internal下面的包:

import "github.com/someuser/modname/internal/auth"

2.4 command with supporting packages

有了package with supporting packages的说明后,再来看command with supporting packages就更简单了,下面是一个示例:

project-root-directory/
├── go.mod
├── main.go
└── internal/
    ├── auth/
    │   ├── auth.go
    │   └── auth_test.go
    └── hash/
        ├── hash.go
        └── hash_test.go

和package with supporting packages不同的是,main.go使用的包名为main,这样Go编译器才能将其构建为command。

2.5 multiple packages

作为一个库项目,作者可能要暴露不止一个package,可能是多个packages。这不会给Go项目目录布局带来过多复杂性,我们只需多建立几个导出package的目录就ok了。下面是一个multiple packages的示例:

project-root-directory/
├── go.mod
├── modname.go
├── modname_test.go
├── auth/
│   ├── auth.go
│   ├── auth_test.go
│   └── token/
│       ├── token.go
│       └── token_test.go
├── hash/
│   ├── hash.go
│   └── hash_test.go
└── internal/
    └── trace/
        ├── trace.go
        └── trace_test.go

我们看到这个示例在repo(以托管在github.com/user/modname下为例)顶层放置了多个导出包:

github.com/user/modname
github.com/user/modname/auth
github.com/user/modname/hash

并且顶层的auth目录下还有一个二级的导出包token,其导入路径为:

github.com/user/modname/auth/token

所有这些导出包的supporting packages还是按惯例放在了internal目录下,比如:github.com/user/modname/internal/trace,这些包是local的,不能被该module之外的代码所依赖。

2.6 multiple commands

有multiple packages类型的项目,就会有multiple commands类的项目,下面是一个这类项目的示例:

project-root-directory/
├── go.mod
├── prog1/
│   └── main.go
├── prog2/
│   └── main.go
└── internal/
    └── trace/
        ├── trace.go
        └── trace_test.go

这个示例将每个command放置在一个单独的目录下(比如prog1、prog2等),supporting packages和之前的建议一样,统一放到internal下面。这样我们可以通过下面步骤来编译command:

$go build github.com/someuser/modname/prog1
$go build github.com/someuser/modname/prog2

command的用户通过下面步骤可以安装这些命令:

$go install github.com/someuser/modname/prog1@latest
$go install github.com/someuser/modname/prog2@latest

2.7 multiple packages and commands

最后我们来看看最复杂的一种项目类型:multiple packages and commands,即在同一个项目下面,既有多个可导出的packages,又有多个commands。下面是一个此类复杂项目的示例:

project-root-directory/
├── go.mod
├── modname.go
├── modname_test.go
├── auth/
│   ├── auth.go
│   ├── auth_test.go
│   └── token/
│       ├── token.go
│       └── token_test.go
├── hash/
│   ├── hash.go
│   └── hash_test.go
├── internal/
│       └── trace/
│           ├── trace.go
│           └── trace_test.go
└── cmd/
    ├── prog1/
    │   └── main.go
    └── prog2/
        └── main.go

我们看到:为了区分导出package和command,这个示例增加了一个专门用来存放command的cmd目录,prog1和prog2两个command都放在这个目录下。这也是Go语言的一个惯例。

这样,这个示例项目既导出了下面的包:

github.com/user/modname
github.com/user/modname/auth
github.com/user/modname/hash

又包含了两个可安装使用的command,用户按下面步骤安装即可:

$go install github.com/someuser/modname/cmd/prog1@latest
$go install github.com/someuser/modname/cmd/prog2@latest

3. 小结

经过对“Organizing a Go module”的文档这篇Go官方项目目录布局指南的学习,我发现指南中的建议与我个人在以往文章、书和专栏中对Go项目目录布局的建议非常相近,几乎一致,唯独不同的是在pkg目录的使用上。

在multiple packages类型项目中,如果要导出的package非常多,那么项目顶层目下会有大量的目录,这让项目顶层目录显得很“臃肿”,我个人建议将这些导出包统一放置到project-root-directory/pkg下面,这样项目顶层目录就会显得很简洁。

注:无论是“Organizing a Go module”这篇文档中的官方建议,还是我个人对Go项目目录布局的建议,针对的都是Go项目的基础布局。而像很多Gopher经常问的采用DDD、clean architecture或Hexagonal Architecture(六边形架构)设计的项目的目录布局是一种业务层面的布局,是在基础布局之上进行再设计的,不在本篇的说明范围之内。


“Gopher部落”知识星球旨在打造一个精品Go学习和进阶社群!高品质首发Go技术文章,“三天”首发阅读权,每年两期Go语言发展现状分析,每天提前1小时阅读到新鲜的Gopher日报,网课、技术专栏、图书内容前瞻,六小时内必答保证等满足你关于Go语言生态的所有需求!2023年,Gopher部落将进一步聚焦于如何编写雅、地道、可读、可测试的Go代码,关注代码质量并深入理解Go核心技术,并继续加强与星友的互动。欢迎大家加入!

img{512x368}
img{512x368}

img{512x368}
img{512x368}

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻) – https://gopherdaily.tonybai.com

我的联系方式:

  • 微博(暂不可用):https://weibo.com/bigwhite20xx
  • 微博2:https://weibo.com/u/6484441286
  • 博客:tonybai.com
  • github: https://github.com/bigwhite
  • Gopher Daily归档 – https://github.com/bigwhite/gopherdaily

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats