Go Wiki: 经验报告
此页面收集有关 Go 遇到的问题的经验报告,以便为这些问题的解决方案设计提供参考。这些报告应侧重于问题:不必侧重于或无需提出解决方案。要提出解决方案,请参阅提案流程。
我们希望通过这些经验报告来了解人们在编写 Go 时遇到的困难,以帮助我们确定 Go 生态系统的未来改进的优先级。(我们不承诺回复这些报告。如果您需要关于 Go 的即时帮助,请参阅https://go-lang.org.cn/help/获取资源。)
最好的经验报告应该说明:(1)您想做什么,(2)您实际做了什么,以及(3)为什么这不好,并用真实的具体例子来说明,最好是生产环境中的例子。请写下对您来说最重要的问题的报告,发布在您自己的博客、Medium 或作为GitHub Gist(使用 .md
扩展名表示 Markdown),或作为公开可读的 Google 文档,然后在此处链接它们。(访谈视频或幻灯片也受欢迎,尽管它们不太方便我们消化。)
如果您无权编辑 wiki 以将文章添加到此列表,请提交一个 issue。
请保持页面整体按部分(例如,“错误处理”在“日志记录”之前)字母顺序排序。在一个部分内,请按时间顺序排列文章。包含每篇文章要点的单句摘要会很有帮助。
根据需要添加新章节。
目录
- 应用和游戏开发
- 并发
- 类型转换
- Context
- 声明
- 依赖
- 文档
- 诊断和调试
- 教育和教学
- 错误处理
- 错误值
- 文件系统
- 泛型
- GoMobile
- 不变性
- 进程间通信
- 大规模软件开发
- 字面量
- 日志记录
- 杂项/多项
- 模块
- 性能
- 移植
- 切片
- 语法
- 时间
- 工具链
- 类型系统
- 类型化的 nil
- Vendoring(供应商化)
应用和游戏开发
- Paul Ruest,“Go 库对应用和游戏的支持”,2017 年 11 月
- Tad Vizbaras,“在 Go 中构建光学字符识别 (OCR)”,2017 年 12 月
类型转换
- Richard Warburton,“当底层数据结构相同时,是否应允许 Go 类型转换?”,2017 年 12 月
并发
- Sergey Kamardin,“一百万个 WebSocket 和 Go”,2017 年 8 月,关于阻塞读/写 goroutine 的内存开销。
- Nathaniel J. Smith,“关于结构化并发的笔记,或:Go 语句被认为是有害的”,2018 年 4 月。
Context
- Sam Vilain,“使用 Go 的 context 库让您的日志更有意义”,2016 年 12 月,关于从 context 中提取结构化日志值。
- Jon Calhoun,“context 值陷阱及其在 Go 中的避免或缓解方法”,2017 年 2 月。
- Michal Štrba,“context 应该在 Go 2 中消失”,2017 年 8 月
- Axel Wagner,“为什么 context.Value 很重要以及如何改进它”,2017 年 8 月。
- Dave Cheney,“Context 不是用于取消”,2017 年 8 月。
- Ross Light,“在 Go Cap’n Proto 中取消 I/O”,2018 年 1 月。
- Iman Tumorang,“避免 Golang API 中的内存泄漏”,2018 年 1 月。
声明
- Christophe Meessen,“Go 的简短声明 := 的问题”,2017 年 7 月,关于变量遮蔽陷阱和
:=
的明显不一致性。 - Brian Will,“Go 的 := 语法在使用多个目标变量时容易出错”,2017 年 8 月。
依赖
- Patrick Bohan,“Docker => Moby: Go 依赖”,2017 年 6 月 28 日。一个新 Go 团队在依赖管理方面的挣扎以及一种应对方法。
- Judson Lester,“[未命名的 gist] (https://gist.github.com/nyarly/edb6b7a5e3a762da6a5e2da8f59acf07)”,2017 年 8 月。
- David Collier-Brown,“通过回收 Multics 的答案来避免 NP 完全问题”,2018 年 9 月。
- Adrian Hesketh “安全漏洞跟踪”,2018 年 1 月。向安全审计员证明代码不包含已知漏洞。
诊断和调试
-
Kevin Burke,“我如何运行基准测试并打印结果”,如果不需要那么多 Unix 粘合代码来运行和打印这些结果就好了。2017 年 7 月。
-
John Clarke,跟踪间歇性故障(非竞争)通过运行非常缓慢的 {命中测试失败,增加日志记录} 循环,通过连续运行“do { go test -race } while ( $LASTEXITCODE -eq 0 )}”过夜。持续许多个晚上。像https://rr-project.org/这样的执行跟踪功能将具有变革性。2018 年 11 月。
-
guanw
,cmd/trace
和 PySnooper。比较cmd/trace
和一个(更简洁的)Python 跟踪 API。2019 年 5 月。
文档
- Kevin Burke,“需要在三个不同的地方为二进制文件添加文档”,2017 年 5 月。
教育和教学
- Carl Kingsford 和 Phillip Compeau,“Go 2.0 用于教学”。在入门级编程课程中使用 Go 的经验。
错误处理
(本节是关于编写 if err != nil
。)
- Andrew Gerrand,“错误处理和 Go”,2011 年 7 月,展示了 Go 的错误处理模式。
- Martin Sústrik,“我为什么应该用 C 编写 ZeroMQ,而不是 C++(第一部分)”,2012 年 5 月,讨论了 C++ 异常处理的生产问题,因为错误处理代码远离导致错误的错误代码。
- Thomi Richards,“错误的麻烦”,2014 年 3 月,认为代码准确记录其返回的错误/可能抛出的异常至关重要。
- Roger Peppe,“热爱您的错误”,2015 年 3 月,讨论了错误处理的惯用法。
- Bleve,“延迟清理、检查错误和潜在问题”,2015 年 9 月,展示了 Bleve 搜索中与错误处理和 defer 相关的 bug。
- Andrew Morgan,“我为什么不喜欢 Go 中的错误处理,以及如何解决它”,2017 年 1 月,关于强制执行良好的错误处理很困难,错误没有堆栈跟踪,并且错误处理过于冗长。
- André Hänsel,“如果我来做我自己的 Go…”,2017 年 8 月
- Peter Goetz,“思考 Go 2 中的新错误处理方式”,2017 年 9 月,展示了 Go 中错误处理的易错性,并概述了改进体验的要求。
错误值
(本节是关于除了 Error() string
方法之外的其他错误语义。)
- Andrew Morgan,“我为什么不喜欢 Go 中的错误处理,以及如何解决它”,2017 年 1 月,关于强制执行良好的错误处理很困难,错误没有堆栈跟踪,并且错误处理过于冗长。
- Chris Siebenmann,“Go 的 net 包没有不透明的错误,只有未记录的错误”,2018 年 8 月
- Bryan C. Mills,“Go 中的错误包装和冗余”,2019 年 9 月
文件系统
- Chris Lewis,“非本地文件系统应得到支持”,2017 年 7 月。建议将文件系统读取调用替换为更抽象的东西,如
sql
包所做的那样。
泛型
- “Go 泛型讨论摘要(生活文档)”。
- Bouke van der Bijl,“Go 中的惯用泛型”,2014 年 9 月。
- Craig Weber,“在 Go 中不使用泛型生活”,2014 年 12 月。
- Shashank Sharma,“Golang (Go) 中的廉价泛型”,2016 年 5 月。
- Niek Sanders,“Go 泛型排序的开销”,2016 年 9 月,记录了使用 sort.Interface 而不是专用代码进行排序的开销。
- Jon Calhoun,“使用代码生成在 Go 中无需泛型生存”,2017 年 5 月。
- Jon Bodner,“闭包是 Go 的泛型”,2017 年 6 月。
- Andrew Stock,“为什么我想念 Go 中的泛型”,2017 年 6 月
- Kevin Burke,“大量接口转换的代码示例”,需要大量样板代码/转换。
- Ian Lance Taylor,“append 函数”,2017 年 7 月。
- DeedleFake,“接口的问题”,2017 年 7 月。
- Kurtis Nusbaum “我为什么对 Go 如此沮丧”,2017 年 6 月
- Juan Álvarez,“Go 标准库上的泛型”,2017 年 7 月。
- David Chase,“Go 泛型在 Go 编译器中的用例”,2017 年 8 月
- Varun Kumar,“泛型 - 我希望你在这里…”,2017 年 8 月
- Sameer Ajmani,“Go 泛型经验报告:Google metrics API”,2017 年 8 月
- Chewxy,“Tensor Refactor:Go 经验报告”,2017 年 9 月,讨论了缺乏泛型及其对构建高性能多维数组(需要大量指针处理和手动跟踪类型和运行时类型检查)的影响。
- qwerty2501,“由于缺乏泛型导致的运行时错误”,2017 年 10 月
- posener,“我为什么推荐避免使用 go-kit 库”,明确的关注点分离需要大量样板代码。gokit 尝试代码生成来避免这个问题 #70 #308 protoc-gen-gokit,但它看起来是一个复杂的解决方案。
- Xavier Leroy,“一个模块化的模块系统”,关于泛型模块描述的论文。
- Tobias Gustafsson,“实现 PEDS 的经验”,PEDS 是一组静态类型安全、不可变/持久性的集合。2017 年 11 月
- 一位谷歌员工 “govisor/generics.go”。2018 年 4 月 27 日
GoMobile
- Vijay,“[在 gomobile 中不支持嵌套结构体和切片]”
不变性
- Kurtis Nusbaum “我为什么对 Go 如此沮丧”,2017 年 6 月
- Sindre Myren “Go 2.0:通过权衡特性来保持简洁” 2017 年 7 月
- Tobias Gustafsson,“实现 PEDS 的经验”,PEDS 是一组静态类型安全、不可变/持久性的集合。2017 年 11 月
进程间通信
- Pablo R. Larraondo “Go 进程间通信模型”,2017 年 8 月
大规模软件开发
- Russ Cox,“代码库重构(在 Go 的帮助下)”,2016 年 11 月,概述了类型别名(#18130)部分解决的渐进式代码修复问题。
- Travis Jeffery,“我宁愿选择 pkg 而不是 internal”,2019 年 11 月;讨论 Go 项目布局、internal 的问题以及人们为什么使用 pkg。
字面量
- Mike Schinkel,“管理字符串字面量是一件麻烦事,不仅在 GoLang 中,在(所有?)其他语言中也是如此”,2022 年 6 月,提出“字符串字面量”和“模板字面量”类型。
日志记录
- Evan Miller,“日志记录可能很棘手”,2014 年 9 月,展示了日志记录如何增加应用程序的尾部延迟。
- Dave Cheney,“让我们谈谈日志记录”,2015 年 11 月,认为只有两个日志级别。
- TJ Holowaychuk,“Apex log”,2016 年 1 月,描述了一个结构化日志包及其在生产中的用法。
- Paddy Foran,“Go 中的日志记录”,2016 年 2 月,展示了如何将 Go 程序日志发送到 Sentry。
- Martin Angers,“关于 Go 可重用包的日志记录”,2016 年 3 月,提出如何编写不假定特定日志包的代码的建议。
- BugReplay.com,“如何将 Google Cloud 的免费结构化日志服务与 Golang 结合使用”,2016 年 9 月。
- Sam Vilain,“使用 Go 的 context 库让您的日志更有意义”,2016 年 12 月,关于从 context 中提取结构化日志值。
- Logmatic,“我们的 Golang 日志世界指南”,2017 年 3 月。
- Chris Hines, Peter Bourgon,“提案:标准 Logger 接口,“2017 年 2 月,与标准库 logger 相关的问题,尤其是在库的上下文中,以及一个提出的解决方案。
- Sindre Myren,“log.Fatal 毫无 Go 特色” 2017 年 8 月,log.Fatal 与 defer 的不兼容性,以及在 Go 1.x 和 Go 2.x 中处理它的简单模式。
- Joonas Loppi,“修复 Go 日志混乱的一个想法” 2017 年 12 月,只需将 *log.Logger 用作所有地方的接口,并围绕它组合解决方案。
杂项 / 多项
- Iman Tumorang,“在 Golang 上尝试干净架构” 2017 年 7 月
- Laurent Demailly,“我的 Go 语言经验,第一部分” 2017 年 12 月,来自经验丰富的 C/C++/Java/脚本语言开发者的角度对当前 Go 的优缺点进行了详细分析。
- Gokcehan Kara,“使用 Go 语言安装可以更简单” 2018 年 5 月,关于静态剥离二进制文件安装和分发带版本信息的一些复杂性。
- Bob Nystrom,“我希望 Go 是的那种语言” 2010 年 10 月,我希望 Go 有元组、联合体、构造函数、没有 Nil、异常、泛型、一些语法糖,以及能从鼻子里喷出 Cheez Whiz 的小马。
模块
- Paul Jolly - “在现有模块中创建子模块” - 涵盖多模块存储库、循环模块依赖以及在各种“状态”之间移动所需的步骤。
- Chi 作者 - GitHub 评论 - 关于 Chi 作者为何推迟实现 Go Modules 支持(此后已添加)。TL;DR — 由于导入兼容性规则。
- Sam Whited -"支持 Go Modules" - 从升级 20 多个模块中学到的东西。TL;DR — 将大型模块升级到 v1 以上非常痛苦,需要工具支持,模块的失败模式非常复杂,并且很容易搞砸为现有项目添加模块支持。
- Stripe GitHub 线程(向下链接的评论) - 撤销对 Go Modules 的支持。TL;DR — Stripe 正在撤销 Go Modules 支持,因为对于 v1 以上的模块,没有明确的从 dep 升级路径。
- 在
GOPATH
中引用 bash 脚本 - Badger 和 Dgraph 上的 Go Modules。TL;DR - Dgraph 正在放弃对 v2 的支持,因为它强制非 Go Modules 用户更改他们的代码。
- 关于 Golang 依赖管理模式(GOPATH 和 Go Modules)的调查:现状、问题和挑战。- 本报告的目的是帮助开发人员更好地理解从 GOPATH 过渡到 Go Modules 的问题。
性能
- Kevin Burke,“真实生活中的 Go 基准测试”,试图向普通开发人员解释如何使用 pprof 等工具,也许这可以更简单。2016 年 7 月。
- Nathan Kerr,“并发更慢?”,展示了如何使用 Go 的测试、基准测试和性能分析工具来提高函数并发实现的性能。2017 年 4 月。
移植
- Shannon Pekary,“为什么选择 GOPP”,试图创建一个“class”关键字,它只是将一个 struct 也变成一个 interface,从而使从面向对象语言移植代码更加容易。
切片
- Richard Warburton,“Go 2.0 是否应支持切片比较?”,主张将切片视为结构体进行相等性比较,忽略底层数组。
- “去重切片过于麻烦”,您的源代码中的一个 10 行函数,相比例如 Ruby 的
uniq
函数。 - “Go 可变函数的反直觉行为”,2018 年 1 月,在将切片扩展到参数列表时遇到的障碍。
语法
- André Hänsel,“如果我来做我自己的 Go…”,2017 年 8 月
- Bojan Zivanovic,“可选函数参数”,2020 年 5 月
- Raanan Hadar,“一位数据科学家的 Go 观点”,2020 年 9 月
时间
- John Graham-Cumming,“闰秒如何以及为何影响了 Cloudflare DNS”,2017 年 1 月,关于闰秒的计时(#12914)。
工具链
- Jonathan Ingram,“gofmt 不够武断”,2017 年 8 月,关于开发人员之间关于代码风格的持续争论,因为
gofmt
不够武断。 - Jean-Laurent de Morlhon,“为什么 Maurice 千万不要用 GO 编码”,从 Java 开发者的角度谈论 Go(“go dep”不够……),幻灯片为英文。
类型系统
- Sam Whited,“使用常量和未导出类型假装枚举类型”,2017 年 7 月,关于尝试使用类型系统确保提供给 API 的值的编译时正确性。
- Andreas Matuschek,“运算符方法”,2017 年 7 月,只是为了提醒人们存在没有相应运算符的类型的(#19770)。
- Leigh McCulloch,“Go:经验报告:指针”,2017 年 7 月,关于指针同时用于传递所有权和指示值缺失。
- Jack Lindamood,“接口包装方法擦除”,2017 年 7 月,关于类型包装器导致的信息丢失。
- Sam Whited,“interface{} 的情况”,2017 年 8 月,使用 interface 的两个示例以及为什么一个不好(但必要)而另一个好。
- James Frasché,“Sum types 经验报告”,2017 年 8 月,由于无法限制为一组封闭的类型而导致的问题。
- Robin Eklind,“特定用例。响应 James Frasché 的“Sum types 经验报告””,2017 年 8 月,由于无法限制为一组封闭的类型而导致的问题。
- Rick Branson,“隐式指针 = 显式错误”,2017 年 9 月,在参数/变量使用接口类型作为隐式引用时遇到的问题。
- Chewxy,“Tensor Refactor:Go 经验报告”,2017 年 9 月,关于 Go 类型系统讨论的问题。
- Walter Schulze,“泛型函数不能作为值传递”,2017 年 9 月。
- Walter, Schulze,“关于 Sum Types:多个返回参数被高估了”,2017 年 9 月。
- Nicolas, Boulay “Sum type 不总是最佳选择(类型化的无标签最终解释)”,2017 年 10 月。
- Eduard Urbach,“将 interface{} 类型转换为 chan interface{}”,2017 年 10 月。
- David Vennik,“解开 Golang OOP 原语”,2018 年 4 月 20 日 - OOP 原语缺乏结构化的问题 - 虚拟函数和冗余的样板类型绑定。
- Jelte Fennema,“通过借鉴 Rust 来修复 Go 中的“十亿美元错误””,2018 年 6 月 14 日 - Nil 指针解引用会导致生产环境中的 panic - 如果类型系统能捕捉到其中一些就好了。
类型化的 nil
- David Cheney,“Go 2 中的类型 nil”,2017 年 8 月。
Vendoring(供应商化)
- Jeremy Loy,“Go Modules 和 Vendoring”,2018 年 9 月。
- Ian Davis,“用于自包含构建的 Vendoring”,2019 年 1 月。
此内容是 Go Wiki 的一部分。