本篇内容是根据2017年4月份Go4 and Contributing to Go[1]音频录制内容的整理与翻译,
Brad Fitzpatrick[2] 加入节目谈论成为开源 Go 的代言人、让社区参与 bug 分类、Go 的潜在未来以及其他有趣的 Go 项目和新闻。
过程中为符合中文惯用表达有适当删改, 版权归原作者所有.
Erik St. Martin: 好的,大家好,欢迎回到 GoTime 的另一期节目。今天的节目是第 44 期,今天的赞助商是 Toptal 和 DataDog。
今天的节目嘉宾有我自己,Erik St. Martin[3],还有 Carlisia Pinto[4] ---
打个招呼吧,Carlisia。
Carlisia Thompson: 大家好。
Erik St. Martin: 还有 Brian Ketelsen[5]...
Brian Ketelsen: 大家好!
Erik St. Martin: 我们今天的特别嘉宾大概不用多做介绍了,他是 Go 团队的一员---
Brad Fitzpatrick。
Brad Fitzpatrick: 大家好!
Erik St. Martin: 嗨 Brad,最近怎么样?
Brad Fitzpatrick: 还不错。
Erik St. Martin: 对那些可能不太了解你的人,你能简单介绍一下你是谁以及你在做什么吗?
Brad Fitzpatrick: 我在 Go 项目上工作大概有 5-6 年了,我主要负责开源项目的部分,包括标准库,我也管理构建系统……这些年我几乎碰过每个部分。
Erik St. Martin: 大家应该感谢你为 HTTP 做了很多贡献吧...
Brad Fitzpatrick: 是的,我负责了很多标准库的部分---
我开发了 HTTP 客户端和服务器,支持 HTTP/1 和 HTTP/2...
Brian Ketelsen: 还有 DB SQL...
Brad Fitzpatrick: 对,数据库的部分,还有子进程执行的部分,JSON 的部分我也做了一些......可以说是到处清理。现在 Go 1 已经定型,不能改动太多了,但在 Go 1 之前,变化还是很多的。
Brian Ketelsen: 那时候真是“好时候”啊……
Brad Fitzpatrick: 是啊。
Erik St. Martin: 你提到了一件有趣的事……似乎 Go 团队有些成员专注于解决 Google 内部使用 Go 的问题,另一些则更多地面向外部社区。是这样吗?
Brad Fitzpatrick: 是的,确实如此。早期只有三四个人,后来大概有八九个人,大家都做所有的事情,包括内部和外部的工作。但随着 Go 在 Google 内外的流行度增加,我们开始更多地专注于不同的领域。现在确实有一些人几乎不接触开源社区,他们主要处理 Google 内部的库或性能问题。
有时你会看到他们突然出现在开源世界中,修复一些 bug 或者进行性能优化,这可能是他们第一次出现在公共领域,因为他们之前可能已经在内部调试了好几周。
我们正在努力改变这种情况,让那些只在 Google 内部贡献的人更多地参与开源社区。因为内部和外部的工具和流程不同,所以他们可能会感到不适应。我们打算每三到六个月安排一次,让他们花一两周的时间参与我们称为“启动时间”的活动,当我们为新的 Go 版本开放代码库时,让他们也参与进来。
Brian Ketelsen: 我注意到你几乎成了 Go 开源项目的公共面孔。无论出现什么问题,都是你在处理;仪表盘宕机、构建系统出问题,大家都在找你。这几年来,看到这种情况是如何演变的很有趣。这是你自愿做的吗?还是某种程度上被推选的?
Brad Fitzpatrick: 这事情是渐渐发生的……然后有一天,Russ 或者 Ian 或者某个团队的人正式决定让我来做,我也就接受了,反正我已经基本上在做了。这其实也是 Go 项目中很多事情的运作方式:你做某件事做得久了,就自然而然成了负责人。
Erik St. Martin: 但这也会带来“核心人物”问题,对吧?
Brad Fitzpatrick: 对,这是个现存的问题。其实我很快要迎来我的第一个孩子了,我会休产假。这也是另一种“核心人物”问题吧,但我一直在培养一些人来接手构建系统和仪表盘的管理工作。
Brian Ketelsen: 这是我们听到的最好的消息。
Brad Fitzpatrick: 是啊,这会很有趣……不过我可能会错过 GopherCon[6],但我觉得这是个不错的理由。
Brian Ketelsen: 没问题,这次我们会原谅你。
Brad Fitzpatrick: 好的。我只是希望能有直播,这样我可以在家里观看。
Brian Ketelsen: 去年就有直播。
Brad Fitzpatrick: 哦,真的吗?
Erik St. Martin: 是的,主会场的所有主题演讲都有直播,分会场的没直播……不过我们还在安排细节,可能今年也会部分直播,所以这次你可以错过。婚礼可以改期,但是孩子的出生不能改。
Brian Ketelsen: 孩子的出生其实是可以计划的。
Carlisia Thompson: Brad,其实你本可以把时间安排得更好。
Brad Fitzpatrick: 我知道……不过我确实把时间安排在了 Go 1.9 发布的时候,所以……[笑] 不知道这是好事还是坏事,不过至少在 1.9 版本冻结期间,我不用太担心。
Erik St. Martin: 那么 1.9 版本的代号会跟你孩子的名字一样吗?
Carlisia Thompson: 是啊,简直是双重“出生”了。
Brad Fitzpatrick: 我们之前的版本没有用代号,所以现在开始用的话会有点奇怪。
Brian Ketelsen: 你们总得从某个地方开始一个传统嘛。别的项目都用代号,比如 Zesty Zephyrs、Xenial Xerces 之类的。我觉得 Go 也该有一些酷炫的名字,这是我们缺少的。
Brad Fitzpatrick: 可以提交个提案,我们有提案流程。
Brian Ketelsen: 好,我去提案……我大概知道会发生什么。
Erik St. Martin: 删除![笑]
Carlisia Thompson: 说到 Brad 处理各种事务,我们来谈谈大家如何为 Go 贡献代码吧……最近 Steve Francia[7] 写了一篇博文,我觉得我们可以在节目里讨论一下。对了,Brad,你能通过我的 pull request 吗?我昨晚刚提交的……拜托啦![笑]
Brad Fitzpatrick: 嗯,实际上我们还没有正式接受 pull requests---
这是我接下来要做的一件事。
Carlisia Thompson: 我提交的那是什么?我做了一个修改……叫 CL,它是什么意思?
Brad Fitzpatrick: CL 是 ChangeList 的缩写。这其实是 Perforce[8] 的术语,那时候 Google 还在用 Perforce。
Erik St. Martin: 我记得 Perforce。
Brad Fitzpatrick: Go 项目已经经历了四个版本控制系统,我想 Perforce 是第一个。我们先用 Perforce,然后是 Subversion,再是 Mercurial,现在是 Git。但在这些转换过程中,我们的工具不断更新,以保持和最初的工具相似,所以我们仍然使用那些老旧的术语。这确实很奇怪。
Carlisia Thompson: 好吧,但别转移话题……你能通过我的请求吗?[笑]
Brian Ketelsen: 是的,CL。
Brad Fitzpatrick: 你最好提醒我一下,有时候我会漏掉一些事情,这是我需要改进的。我需要改进我的仪表盘,这样大家都可以帮忙查看旧的请求。现在,遗憾的是,我通常只看到邮箱里最上面的那些。如果你再提醒一下,它就会回到顶部。
Erik St. Martin: 我喜欢 Carlisia 选在直播时让你表态……你在节目里可没法拒绝。
Brian Ketelsen: 太厉害了。
Carlisia Thompson: 我提交的 CL 是为了在网站上加上 GoTime。
Brad Fitzpatrick: 哦,我今天早上确实看到过这个。
Brian Ketelsen: 那是 CL 编号 41146...
Carlisia Thompson: 好的,按下按钮吧。
Erik St. Martin: 她说:“我们等着。” [笑]
Brad Fitzpatrick: 我现在用的是另一台电脑……
Brian Ketelsen: 你真是太棒了,Carlisia。
Carlisia Thompson: 不管怎样,我们还是听听 Brad 怎么说这个过程吧?你之前提到了提交提案的事情……是不是有些情况不需要提交提案?比如,我提交了那个 CL(ChangeList),但当时我是问了 Steve Francia,“嘿,我们能加上这个吗?”他回答说,“可以,提交修改吧。”于是我就提交了。
我没有开一个 issue……如果我没有问 Steve,我是不是应该先开个 issue?还是说对于这种很小的改动,直接提交 CL 就可以了?
Brad Fitzpatrick: 如果改动很小,直接提交就行了。我们甚至让提案的流程尽量简化,因为我们知道,即便我们写了一个非常正式的提案流程,人们也可能会忽略或者不去看。所以我们让提案流程从提交一个 bug 开始,然后开始讨论。如果我们觉得你的提案比较复杂,确实需要更多的正式性,我们才会给你发送提案模板,让你写一个正式的提案。
大多数时候,我们会立即说“可以”或“不可以”,并不会让大家经历整个“写设计文档”的过程。
Carlisia Thompson: 好的。
Brad Fitzpatrick: 是的,你的改动可能没有什么争议。我猜会有人(也可能是我)稍后点击“接受”。
Carlisia Thompson: 谢谢你。实际上,我看到了一段代码,我想加上它,但我自己其实没有什么使用需求……我只是觉得“哇,如果有这个就更完整了”。那我提交提案的时候,是否一定需要有一个强有力的使用场景?还是说即便没有使用场景,我也可以提交,并且说“嘿,我觉得它应该存在”?
Brad Fitzpatrick: 我们有一个我很早前就加上的 FAQ,叫“为什么 X 不在标准库里?”基本上,它解释了我们在标准库里放了太多东西,这其实是个错误,所以除非非常重要的功能,我们不鼓励再往标准库里添加新东西。通常我们会说,“不,请把它放到 GitHub 上。”
Carlisia Thompson: 你说的“放到 GitHub 上”是指什么?
Brad Fitzpatrick: 你刚才说你想加的东西是为了完整性,但你自己并没有使用场景……
Carlisia Thompson: 是的。
Brad Fitzpatrick: 所以如果你提议将这个东西加到标准库,我们可能会说“不”,特别是当没有实际需求,只是为了好玩的时候。我们通常不会仅仅因为可以而往标准库里添加东西。
Carlisia Thompson: 但你刚才说“放到别的地方”是什么意思?
Brad Fitzpatrick: 是的,比如你可以把它放到某个地方,用户可以通过 go get
来获取。标准库的问题在于我们无法快速修复问题,也不能轻易更改或移除东西,所以如果你把它放到 GitHub 上,你会有更多的灵活性。
Carlisia Thompson: 就像我自己的项目一样……
Brad Fitzpatrick: 是的,或者其他地方……你可以自己注册一个域名,给它取个有趣的名字。我有一个 go4.org[9] 网站,上面放着一些我在多个项目中需要的 Go 实用函数,但我并不想把它们加到标准库里……所以我把一些有趣的东西都放到了 go4.org 上。
Carlisia Thompson: 哦,挺酷的。
Erik St. Martin: 我也应该这么做。我很早前就注册了 gopher.af……[笑] 但到现在还没找到用它的机会。
Brad Fitzpatrick: 自从我注册了 go4.org 这个域名之后,我就收到大量垃圾邮件,有人说“嘿,我有一个类似的域名,你有兴趣买吗?” 但那些域名全都很糟糕,全都是随便拼起来的字母和数字。我想,“嗯,确实,我买的域名也差不多是些乱七八糟的字母组合,但……” 不管怎样,这是我的一个小笑话。
Erik St. Martin: 我也讨厌别人试图卖给你……还有一件事是,如果你搜索了一个域名但没有立刻买下它,过一段时间你再去看,它总是变成了高价的“高级域名”。你会想,“真的吗?!” 所以你得在搜索的那一刻准备好买下,否则他们可能会抬价。
Brian Ketelsen: 这也是我的问题。
Brad Fitzpatrick: 如果你通过注册商的搜索表单来搜索,他们就会知道。你应该通过 Whois 直接查询,这样他们就不会知道你在搜索那个域名。
Erik St. Martin: 通过 Whois 搜索域名……[笑]
Carlisia Thompson: 是啊……用终端来搜索。
Brian Ketelsen: 我每次都带着信用卡去注册商那里。
Erik St. Martin: 你之前提到了 1.9 版本……你在 1.9 版本中具体负责哪些工作?能透露一些吗?
Brad Fitzpatrick: 其实我在尝试看看我能在 1.9 版本中尽量少动代码。我做的很多事情实际上是为了让社区更多地参与进来,帮助处理 bug triage(问题分类)和代码审查……因为随着 Go 在内部和外部的不断发展,我们收到的 bug 报告和提交的代码变得越来越多,只有我们几个在做代码审查,这种模式已经无法扩展了,因为我们花了大量时间在分类和审查上。
所以我正在尝试让社区更容易参与进来,这样他们不会感到害怕,他们知道流程,或者我们有更好的仪表盘告诉他们哪些事情需要注意……
我们创建了一个叫 Gardening[10] 的 wiki 页面,这个页面列出了所有你可以做的“园艺”任务。如果你有五到十分钟的时间想为 Go 项目做点贡献,我们会列出一些 GitHub 查询,看看有哪些问题需要关注,或者最近有哪些代码审查,还有一些只需要花几分钟时间就能完成的任务,但这些任务可以推动项目向前发展。
Carlisia Thompson: 这个列表在哪里?
Brad Fitzpatrick: 在 golang.org/wiki/gardening 上。很多开源项目使用“园艺”这个词来形容一些后台的清理任务……就像园艺一样,拔草的工作永远做不完。上面列了很多任务。
比如我们在某个 bug 上加了“等待信息”的标签,你可以看看这些在 GitHub 上标记为“等待信息”的 bug,看看“这个 bug 应该关闭吗?是否超时了?提交人有没有反馈我们要求的信息?”就是推动这些 bug 向前发展,有必要时提醒一下。
如果有人提交了代码审查,但提交信息格式不对,你可以告诉他们如何格式化提交信息,提醒他们忘记加测试了,或者找到拼写错误……有很多简单的事情你可以做,这些与代码修正本身无关,但可以让代码审查过程更顺利。
Erik St. Martin: 这是个有趣的想法……通常在版本发布周期时,Dave Cheney[11] 会做一个演讲,然后多个 Go 社区的 meetup 会使用这个演讲内容。
Brad Fitzpatrick: 是的,全球发布派对。
Erik St. Martin: 是的,我在想,是否可以做一个类似的共享演示文稿,这样各个 meetups 就可以用它作为内容?很多 meetups 总是寻找内容,每个人都可以做展示,或者把它变成“嘿,我们这个月没有什么话题,大家来开个园艺派对吧”,大家一起做一些问题分类的工作,每隔一个月做一次,这样它就变成了一种协作努力,大家可以互相指导那些从未参与过的人。
Brad Fitzpatrick: 这是个有趣的想法。也许我可以在西雅图的 meetup 上试试。
Carlisia Thompson: 这让我想起了很多语言社区都有的 Bugmash 活动,对吧?
Brian Ketelsen: Bugmash,没错。
Carlisia Thompson: 我们还没有类似的活动。Brad,你觉得组织一个怎么样?
Brad Fitzpatrick: 我不知道那是什么。
Carlisia Thompson: Bugmash 就是---
Brian,你可以纠正我---
安排几天时间,先由维护者列出需要解决的问题。然后我们号召大家在这几天内一起集中精力解决这些问题。
Brad Fitzpatrick: 哦,我明白了……就像一个 bug 燃尽活动,或者修复周,类似的东西。
Carlisia Thompson: 没错。每种语言、每个社区的名称不同。
Brian Ketelsen: 是的,重点是吸引那些之前可能没有参与过的人。所以,与其花五分钟自己修复一个小问题,你可以花二十分钟把它变得非常简单,让那些从未提交过补丁的人也能参与进来。
Carlisia Thompson: 完全正确。
Brad Fitzpatrick: 这实际上是我过去三个月以来一直在待办事项上的一件事。我上一季度应该做的一件事是写一篇博客,介绍如何为 Go 提供贡献以及如何参与这些事情,但我一直在推迟,因为我想要有更多的仪表板让人们使用,这样会让参与变得更容易……但总有一个时刻我需要告诉自己,够了,现在的状况已经足够好了,足够让人们参与进来。
Erik St. Martin: 是的,我认为这种争论也是正确的。我记得 Bugmash 或其他类似的活动---
Ruby 也有一个,但我记得它不叫 Bugmash,叫别的什么……这类活动通常是为那些想贡献代码的人准备的,而很多人在刚开始时并不熟悉代码库以及它的工作方式,他们也没有足够的信心去贡献代码。所以我觉得你不会在这类活动中看到太多参与者,反而在“嘿,你可能不想直接贡献代码,但你可以用这些方式贡献”的活动中,会看到更多人参与。通过这样做,他们会熟悉这个项目和各个组件,进而可能通过这种方式建立起信心。
我在一些聚会中也看到过类似的情况,很多人需要很长时间才能鼓起勇气提交代码更改。他们总是担心会被批评……有时候确实会,但每个人的反应不同。我觉得帮助进行项目维护(gardening)是建立信心的一种方式,因为你会熟悉项目的贡献者,了解谁负责什么,应该问什么问题,票据(tickets)会经历哪些阶段,因为你已经习惯参与这个过程了。
Brad Fitzpatrick: 至少我们现在有一个专门给审查员的 Slack 频道……就是 GopherSlack 上的 reviews 频道[12],人们可以在那里聚集,处理问题并维护项目。
Brian Ketelsen: 我都不知道有这个频道。
Carlisia Thompson: 我也不知道……但我觉得任何社区努力,为了帮助人们聚在一起并提供一点支持,以克服设置环境的障碍,并让他们有动力进行设置,因为他们知道会有一份简单的任务清单,这对于初次参与的人来说非常重要。
举个例子,我从来没有为 Go 贡献过代码,但昨天我花了一点时间进行设置,我只想加一行文字,但我得先完成整个设置过程……不过,这个过程其实很简单。虽然花了一些时间,但并不难。
Brad Fitzpatrick: 我个人讨厌我们的贡献流程,还有那篇冗长的文档,吓跑了很多人……其实步骤并不多,但文字太多了,大家看到它就想跑掉,还会问“为什么你们不用 GitHub?”
答案是我们可能应该用……当我们迁移到 GitHub 时,其实是一个非常快速的、被迫的迁移,因为 code.google.com 要关闭了,所以 GitHub 是显而易见的选择,他们有问题跟踪器,但我们当时并不准备放弃 Gerrit,因为 GitHub 上的代码审查历史上一直不太好。虽然 GitHub 现在变得好多了,但我们真的很喜欢 _Gerrit_。所以我们说,“好吧,我们可以用 GitHub 作为问题跟踪器、wiki 等,但代码审查还是用 Gerrit_,GitHub 只是一个镜像。”不过可能是时候写一些工具来接受 GitHub 上的 pull requests,至少目前可以自动转化为 Gerrit 更改,这样审查仍然在 Gerrit 上进行,_Gerrit 仍然是上游……但如果有人只熟悉 GitHub 流程,他们可以继续在 GitHub 上发 PR,然后我们透明地更新 Gerrit CL。我们可能需要从这个开始,但……
Carlisia Thompson: 是的,就像我刚才说的,虽然设置过程不难,但确实花了一些时间,我有时会觉得很沮丧;我会读完一段文字,然后做一件事,然后去做别的事情……“啊!我不想读完这些内容!”所以我来回折腾,最后用了几个小时完成了所有步骤。但这只是你需要做一次的事情,如果你只是为了做一件小事而要经历整个过程,那真的很让人泄气。
现在我完成了这些步骤,我已经拉取了代码,把 Go 项目里的博客和网站都设好了……如果我想做一个文档更改,现在超级简单。我只需要同步一下,像平常一样开始一个分支,然后……虽然我不太懂术语,但用 Git 术语来说,我只需要推送。
现在我有了这些设置,真的很简单。我只需要找出,“好吧,我能根据现有需求做出哪些贡献?”这又回到了我之前说的,举办一些 Bugmash 活动,这会非常棒。
Brad Fitzpatrick: 是啊,既然你已经花了几个小时设置好了,现在你需要修复一堆 bug 来平摊那些时间成本。
Carlisia Thompson: 没错。 [笑] 我已经赚回了我的时间。
Erik St. Martin: 另一个人们可能不太熟悉的事情是,如果你在找任务的话,GitHub 上有一个 Help Wanted 标签。
Carlisia Thompson: 是的,我现在就在找。
Brad Fitzpatrick: 人们总是要求我们多用这个标签;他们想要更多的任务……但我其实不太喜欢这个标签,因为我们似乎从来没有很好地使用它。因为没有一个明确的定义说明它的含义是什么。大家想要一个像 Easy 或 Beginner Friendly 这样的标签,但问题是,对于一个人来说简单的事情,对于另一个人来说可能完全不同。
如果某件事真的对所有人都很简单,它早就被修复了。我们从来不知道问题有多复杂,而 Help Wanted 这个标签也有点傻,因为我们希望每个 bug 都能被帮助修复。我最近越来越多地使用 _Help Wanted_,但我基本上把它加在所有问题上……这也没什么问题,但我觉得大家应该随意地跳进去并开始解决任何问题。
Erik St. Martin: 是的,我曾为一个项目贡献过代码,我记不清是哪一个了---
可能是 Ruby,或者其他什么……他们的标签是 _Bite-Sized_,或者类似的东西,意思是你可以在一次会议里完成---
至少大多数人可以---
而不是那些更大规模的实现,比如 _Generics_。你可能会用 Help Wanted 标签,因为你希望得到别人的意见,但这显然不是新人可以在一小时内完成的贡献……
Brian Ketelsen: 我们需要一个 _GenericsMash_。
Carlisia Thompson: 我想说一下关于 Beginner 标签的事情……当我刚开始学习 Go 时,我有一次经历,我去一个开源项目,他们有一个标签是给初学者的(或者叫 Easy 或类似的标签),我看着这些问题,心想“天哪!这也太难了。如果这是初学者级别的……哇,那中级是什么?简直是火箭科学。”所以这真的把我吓跑了,但我已经编程有一段时间了,所以我学了一段时间后还是给了自己一个机会,现在我能理解这些东西了。
但就像 Brad 说的,如果你给某个东西贴上初学者标签,对于你来说可能很简单的事情,对于新手来说可能非常复杂。你可能真的会吓到别人。你必须小心那些标签,但我喜欢根据任务大小或时间片段来做标签……这很不错。
Brad Fitzpatrick: 嗯,很多时候你在实际做之前并不知道它有多复杂。
Carlisia Thompson: 这也是一个问题。
Erik St. Martin: 我觉得我们已经超时了,该进行我们的第一个赞助商广告了……咱们先休息一下。今天的第一个赞助商是 Toptal。
Erik St. Martin: 好的,我们回来了,继续和 Brad Fitzpatrick 聊天。我们在广告前谈论了 Go 和贡献的问题,但我想继续问的是,你总是有一些很酷的业余项目在进行……你现在在做什么有趣的事情?
Brad Fitzpatrick: 嗯,我最近搬到了西雅图,所以我一直在做一些杂七杂八的家庭自动化项目。我们装了不少 Z-wave 灯光开关,我还买了一些便宜的安全摄像头,现在我正在自己做运动检测系统……
其实,我在上次 GopherCon 上做了一个关于我的运动检测安全系统的闪电演讲。每当我有一点空闲时间,我就会尝试改进这个系统。
Erik St. Martin: 你是用 Go 做的吗,还是你用的是 OpenCV[13]?
Brad Fitzpatrick: 不,几乎都是用 Go。我在家里有一个小型的 Go 服务器,它连接到摄像头,获取压缩的 MPEG 视频流,然后我把它流传输到一个云实例上,那里有更多的计算能力。然后我让一个小的 FFMPEG 子进程来解码视频,并且它还使用 FFMPEG 内置的边缘(EDGE)检测功能。然后我直接通过 FFMPEG 的标准输出输出原始像素,我从 FFMPEG 中读取具有边缘检测的原始像素,并计算随着时间变化的边缘移动位置,一旦它跨越了某些阈值并进入视频的某些区域,我就开始记录。
即使没有任何运动,我也会一直记录最近 5 到 6 秒的内容,存放在一个循环缓冲区中,但一旦有运动,我就会把它流传输到云存储中。
我在后台还有一些小进程会从中生成 GIF,挑选出最有趣的帧,生成两秒钟的小 GIF。然后我可以通过 Telegram 或其他途径发送这些 GIF。这挺有趣的。
Erik St. Martin: 你把所有的原始视频流传输到云端……你的 ISP 一定很“爱”你。
Brad Fitzpatrick: 我有千兆宽带,没问题……
Erik St. Martin: 太棒了。说到超出人们能力范围的项目---
我不确定我能不能构建一个像你这样能处理所有边缘检测的系统……这真是太棒了。你还需要为那些 GIF 添加随机的标题……
Brad Fitzpatrick: 是的,我也在想通过 Google Vision API,识别出物体……有一次我的运动检测系统捕捉到了一些猫,它们在我的前廊上玩耍。那是一只黑猫和一只灰猫,它们互相追逐……
Brian Ketelsen: 那会很酷!这样你就可以收到一条短信说“你家后院有猫。”
Brad Fitzpatrick: 猫咪警报。
Brian Ketelsen: 我喜欢这个主意。
Erik St. Martin: 还有你一直拍的那些天际线照片……你在做什么项目吗,还是只是定时拍摄并存储它们?
Brad Fitzpatrick: 当我刚搬进来的时候,我想对这里做点什么。西雅图有很多起重机,我想制作一段这些新摩天大楼拔地而起的延时摄影……所以我把一台相机装在屋顶上,每分钟拍一张照片并上传到云存储。现在我已经有大约 780,000 张 8 兆像素的 JPEG 照片了,所以我想用它们做点什么。我一直在想一些有趣的点子,比如做个小的网页应用,让你能拖动鼠标,太阳会跟着鼠标移动,或者追踪飞机或船只,或者按色调排序,这样你可以看到不同颜色的天空……但我还没花时间搞这些。我已经有了数据,这部分是最麻烦的,现在有了数据,我需要做点有趣的事情。
Erik St. Martin: 你在云提供商工作真是太好了,因为我觉得没有人会愿意承担你可能产生的账单……[笑]
Brad Fitzpatrick: 其实并不多。我想大概只有 150 GB 左右。
Brian Ketelsen: 这还行。
Brad Fitzpatrick: 是啊,这不算多。
Brian Ketelsen: 这只是我 iTunes 库的一半。 [笑声]
Brad Fitzpatrick: 你还在收集音乐吗?
Brian Ketelsen: 我收集了很长一段时间,但现在我甚至不再用 iTunes 了。
Brad Fitzpatrick: 我刚卖掉了我的车,找到了我以前的 iPod……那种带旋转硬盘的大 iPod,它还一直在我的手套箱里,连接着车,因为车里有一根 iPod 连接线……这基本上是我大学时期的音乐收藏,存在这块 80GB 的硬盘里,虽然从那以后就没更新过,但它还在工作。
Brian Ketelsen: 这太酷了……我昨天在抽屉里找到了一张索尼 MiniDisc,但我完全不知道上面有什么音乐。我确定它一定很精彩,但我完全没法知道上面是什么。
Erik St. Martin: 我确定你可以在 Craigslist 上找到配套的驱动器……应该有人有一个…… (译者注: 类似国内的58同城)
Brian Ketelsen: 是啊,如果我在意的话……
Erik St. Martin: 我可能也有一两个便携硬盘里存着音乐,但我一直保存着它,因为我想,“万一我真的需要这些 MP3 呢?”
Brian Ketelsen: 你的 Napster[14] 收藏?
Erik St. Martin: 现在太方便了……你可以从任何设备上流媒体播放;我的车里有蓝牙连接,Spotify 直接播放---
问题解决了。我不需要 MP3 了。
Brad Fitzpatrick: 我找到了一箱我最早写的 Apple 2 程序,存放在这些五又四分之一英寸的软盘上,但我没法读它们。后来有人在网上说:“哦,我有读取这些的硬件。我可以帮你制作镜像并把原始数据发给你。”然后我想我可以把它放到模拟器里,或者干点别的。所以我把软盘寄给他了,但从那以后我再也没有听到他的消息。我每隔六个月发一次邮件问他:“嘿,你还留着这些盘吗?能寄回来吗?”但没有任何回复……
Erik St. Martin: 哎呀。
Brian Ketelsen: 哎呀……
Brad Fitzpatrick: 不过没关系,它们可能已经坏了。
Erik St. Martin: 或者,你最近有没有身份被盗? [笑声] 也许他发现了什么好东西,然后想:“哦……”
Brad Fitzpatrick: 不,那些程序---
它们一点也不好。
Erik St. Martin: 我还是很怀念那些日子……我总是问那些有五又四分之一英寸软盘的人:“你有《俄勒冈之旅》吗?” 我打赌你现在可以在模拟器里玩到它了……
Brian Ketelsen: 你们真年轻……当我还是个孩子时,我们必须从 Byte 杂志的背面手动输入应用程序,而且一旦关机,程序就没了。
Erik St. Martin: 每次你想用它都得重新输入一遍吗?
Brian Ketelsen: 对的。我刚开始学计算机时,甚至没有磁带机来保存程序。
Erik St. Martin: 那绝对比我的时代要早。
Brian Ketelsen: 我妈会进来说:“你得把那玩意关了。” 我说:“不,不,不……我们不能关机。” 不,不,不……那可是很多的输入啊。
Erik St. Martin: 我记得有 28k 的调制解调器。如果你想要音乐,想要整张 CD,你得开一晚上,还得祈祷没人断开电话线……早上醒来时,“不---
!”
现在想想挺有趣的,现在的年轻一代可能都不明白这其中的讽刺。我们很多人刚开始用互联网的时候,得拨号上网,对吧?互联网是通过电话线提供的,但现在电话却是通过互联网线提供的。
Brad Fitzpatrick: 你们看过电视剧《Halt and Catch Fire》吗?
Brian Ketelsen: 没有。
Erik St. Martin: 只看了几集。
Brad Fitzpatrick: 好的……这部剧讲述了 70 年代末和 80 年代的计算机行业,我记得第二季讲的是一家拨号 ISP,类似于一个 BBS 系统公司,他们正在建立这个公司。整部剧充满了怀旧感……这是很不错的一部电视剧。
Carlisia Thompson: 那是部好剧。我也没看完所有剧集,但我需要补完。谢谢你提醒我。
Erik St. Martin: HBO 有一部关于创业生活的剧叫什么来着?
Brian Ketelsen: 《硅谷》?
Erik St. Martin: 对,就是那部,还有另一部。我想《硅谷》就是那部。那部剧太搞笑了……
Carlisia Thompson: 太搞笑了。
Brian Ketelsen: 我看不下去……感觉太真实了。
Erik St. Martin: 就像,“嗯,有个人拿了钱,然后我想他自杀了。” 结果是,“不,等等……也许他没拿钱。哦,我记不清了。” [笑声]
Carlisia Thompson: 我觉得他们做得很好,他们在咨询方面做得不错,不论他们咨询了谁。
Brian Ketelsen: 可能是 Brad。
Erik St. Martin: 背后是 Brad。
Brian Ketelsen: 对。
Carlisia Thompson: 可能是。我们刚才在聊存储,当然我们得聊聊---
我不知道该怎么念……Camlistore[15]?
Brad Fitzpatrick: 对……那个临时名字,结果并不临时。我一直以为有一天我会给它改名。
Carlisia Thompson: 是啊……我看了你的视频,知道这是个缩写。
Brad Fitzpatrick: 是的,这是让我进入 Go 语言的项目。当时我在 Google 的山景城工作,做 Android 项目,我每天从旧金山到山景城的通勤,顺利的话要 45 分钟,不顺利的话要两个小时。
所以有时候我得在车上消磨四个小时,我要么恨自己的生活,要么就写点代码……但我需要写点什么东西,于是我有了这个想法,我想构建一个终极存储系统,用来备份所有我的东西,归档我所有的社交网络内容。我有些推文在这儿,照片在那儿,博客文章又在别的地方……我想把我所有的东西---
所有备份、文件和内容---
全都集中在一个系统里。我还想用这个系统托管我所有的网站。
我知道自己想要的数据模型,我也知道想要的协议;我做了很多笔记……然后我只需要实际构建这个东西,并且选择一门编程语言。我在 Google 搜索了几种选择:C++、Python 或 Java……我在这些语言上都有很多经验,知道我肯定不想再用它们……
C++ 基本上只有在你有像 Google 那样庞大的标准库和优秀的构建系统时才可用,否则 C++ 的工具链很痛苦。我写了很多 Python 和 Perl,知道它们并不适合写服务器,因为你要么得做很多回调之类的事情,要么性能非常差……当时我写 Java 做 Android,Java 我也写够了,已经厌倦了。
就在这个时候,Go 语言刚好问世,所以我决定用 Go 语言先做个原型。我在通勤的公交车上开始搞这个,真是太棒了,因为我不需要网络,当时的工具已经足够好了……那时候还没有 go
命令,你得用 Makefile,但编译速度非常快,所以还不算太糟糕……我不断发现标准库里缺少一些东西,HTTP 包也有些问题,所以我就开始给 Go 团队提交修改,当时 Go 团队成员基本上是 Russ、Ian 和 Robert。Russ 不断批准我提交的 HTTP 修改,我就不断提交更多的代码,最终我全职转到 Go 团队。
有一天我收到 Rob[16] 的邮件,他问我:“嘿,你想全职做这个吗?” 当时我已经在 Android 团队工作了几年,显然 Android 已经站稳脚跟了……它不再是个疯狂的想法了,所以是时候去做一些新的疯狂想法了。但现在看来,Go 语言可能也要站稳脚跟了……
Carlisia Thompson: 那现在是不是该换个方向了……
Brad Fitzpatrick: 我不知道……我不知道我还能做什么。
Brian Ketelsen: 我记得非常清楚……大概是在2010年中期,有一段时间,Go语言的每一个改动几乎都由Camlistore[17]的变化驱动。可以说,就像钟表一样精确。
Brad Fitzpatrick: 是的,很多HTTP方面的东西源自那里,数据库部分也是,还有很多字符串包的改动……甚至像strings.Contains()
这样非常基础的功能。
Carlisia Thompson: 我看了你的视频介绍了Camlistore,觉得真的很酷。有听众ZelenHunter提了一些关于Camlistore的问题,他问:“你会回到积极开发Camlistore的状态吗?”我看到你确实在本月发布了一个版本,但这是否意味着你重新开始积极投入开发了?
Brad Fitzpatrick: 不,我现在主要是审查另一个开发人员Mathieu的工作。他一直在持续开发。我仍然在观察并参与其中,但不像以前那样写很多代码了。也许等我休产假时,我会在休息时继续开发。我们拭目以待吧。
Carlisia Thompson: 你觉得它未来会成为一个成熟的产品吗?
Brad Fitzpatrick: 其实它现在已经相当可用和稳定了。每次发布新版本,它都会变得更主流、更易用。我记得两三次发布前,我们做了一个启动器……如果你访问Camlistore.org/launch,我们有一个表单,可以帮助你在Google Cloud上创建自己的实例。
Brian Ketelsen: 这很酷。
Carlisia Thompson: 确实很酷。
Brad Fitzpatrick: 当时出来的时候,虽然运行了,但使用的是一个丑陋的IP地址,安全性依赖于自签名的HTTPS证书。后来我去开发了Let's Encrypt[18]支持,并将其添加到Golang中。我和另一个人合作,他实现了Acme协议,然后我做了一个Autocert包,也就是Golang x/crypto/acme/autocert……我们也把这个加入了Camlistore。
现在Camlistore可以获取Let's Encrypt的证书了,但我们还需要自动生成域名,这样当用户创建自己的实例时,他们就可以直接使用。于是我们创建了一个DNS服务器,用户可以自动获得Camlistore.net的子域名。我们开发了一种类似Acme的协议,只要你能证明你拥有密钥对,就可以获得一个子域名。这个域名会有点丑,比如是你密钥的指纹.camlistore.net,而我们会自动设置DNS服务器关联,然后你可以为这个域名请求Let's Encrypt证书。
最终的结果是,你通过这个向导,点击create vm
,大约40到60秒后,你就能得到一个运行中的实例,带有完全信任的证书和域名。
Brian Ketelsen: 你们如何绕过Let's Encrypt的子域名速率限制?因为他们的限制是每周20个子域名。
Brad Fitzpatrick: 我们的用户还不多,所以目前还没有遇到这个问题。
Brian Ketelsen: 好吧,不过要小心……这个问题迟早会来的。
Erik St. Martin: 接受挑战。
Brad Fitzpatrick: 是啊……如果真遇到这个问题,我们会帮助用户自己带域名,或者引导他们通过其他域名创建流程。
Carlisia Thompson: 另一个听众的问题是:“Go核心团队是如何应对倦怠的?”我并没有听说Go团队有倦怠问题,但我觉得这是个不错的问题,能谈谈这个吗?
Brad Fitzpatrick: 是的,确实有些重复的感觉。我知道Andrew[19]去做Upspin项目[20]了,因为他需要一些改变……你知道,当你多年做着同样的事时,确实会有些单调。
我自己也有点这种感觉,因为我想Go 1.9将是我参与的第10或第11个Go版本发布,还不算其中的所有小版本发布……有时候你会感到有些沮丧,因为有些东西你无法修复,而且你总是看到相同的bug报告和提案,不得不一遍遍地重复关闭这些bug,告诉大家“抱歉,我们不能更改这个”,或者“这要等到某种Go 2版本才能解决”……
我会尝试偶尔换一些不同的任务来做,专注于不同的事情……比如为Go 1.6开发的HTTP/2功能就是一个很好的分散注意力的项目,因为我可以实际编写代码,思考新的问题类型。现在,我在做关于社区互动的统计和仪表盘,这在某些方面也很有趣……我还专注于Kubernetes[21],定义我们的构建基础设施和运行Go构建系统的所有微服务……学习Kubernetes的过程中,我确实感到了一些乐趣。不过,确实有时候事情会变得非常重复和无聊,然后我就得找一些新东西来做一段时间。
Erik St. Martin: 你觉得不能做出改变的挫败感,可能会激励大家推动2.0的开发,或者至少开始思考和讨论2.0可能是什么样子吗?
Brad Fitzpatrick: 是的,我觉得我们大家都有这种感觉,觉得我们可能需要做一个Go 2。我不确定,但Go成为一个开源项目已经接近十年了。Rob曾经说过,如果他要做Go 2,十年可能是一个合适的时间点。
就我个人而言,我最大的担忧是有另一个语言会出现,并且拥有像goroutines那样的功能。我觉得goroutines是Go的真正特色。没有其他语言能像Go那样很好地实现轻量级线程。其他语言可能已经借鉴了Go的优秀工具链,但Go的类型系统也非常有趣。如果有一门语言出现,具备非常好的工具链,同时依然简单且拥有goroutines,并且让编写服务器变得非常简单,但又有一个更强大的类型系统……
Brian Ketelsen: 你们看过Crystal语言吗?
Brad Fitzpatrick: 哪个?
Brian Ketelsen: Crystal是一种类似Ruby的语言,是用C或C++写的,速度非常快,编译成原生代码……它几乎复制了Go的goroutines和channels,功能齐全,而且速度真的非常快。标准库还需要一些完善,它还没有到1.0版本。我大概在一两个周末前玩了一下,确实像Ruby一样,但速度快得惊人。它会是一个有趣的存在……
Erik St. Martin: 我总是喜欢尝试新语言。
Brad Fitzpatrick: 谁在开发它?
Brian Ketelsen: 我不记得了……好像是欧洲的一个小团队。
Erik St. Martin: 那是crystal-lang.org[22]。
Brian Ketelsen: 它由Manas.tech赞助。
Brad Fitzpatrick: 有一家公司的支持,这很有希望,不是只有一个人在做。
Erik St. Martin: 尝试其他语言总是有趣的……Brian,我们这些年一起尝试过的其他语言有哪些?Pony, Nim……
Brian Ketelsen: Pony不适合我。Nim挺好玩的……还有哪些?我玩过Elixir……但Elixir对我来说变化不够大。
Erik St. Martin: 是的,你说得对---
goroutines真的非常棒。我记得第一次发现你可以随意使用它们时的感觉……当你推荐给别人时,他们会问:“我可以有多少个?”“你需要多少就有多少。”“等等,没有上限吗?”“没有,继续使用goroutines吧。”
Brian Ketelsen: “你想要多少?”
Brad Fitzpatrick: 我一直在关注Rust和Swift……他们都在考虑添加轻量级任务或goroutines或fibers,或者你想叫它们什么都行,但这两个项目最终都放弃了,认为“这有点难,pthread可能已经够用了……也许我们以后再考虑。”
每个人都在思考这个问题,但没有人付诸实践。我相信最终会有人做到的。
Erik St. Martin: 哦,是的,我觉得肯定会有人做到,这只是个时间问题,是新语言做到,还是现有语言的新版本采用……但我认为很难不去考虑它,尤其是看到Go在短短几年内的快速增长。
我认为其他有前途的新语言至少得思考,为什么人们如此喜欢Go,并开始采用其中的一些特性。
Brian Ketelsen: 回到Crystal……Crystal确实有成功的配方,因为很多人喜欢Ruby的语法,而将goroutines和channels加入其中似乎是个不错的配方。但当你真正使用它时,它并不像Go那样顺畅。
Erik St. Martin: 听起来不够流畅,是吗?
Brian Ketelsen: 是的,我听过很多次……Go的核心优势之一是它的代码是为阅读而写的,而大多数语言不是。Go优化了代码的可读性,这对你的生产力有着巨大的影响……很难描述,要在其他地方复制这一点有多难。
Erik St. Martin: 我认为从另一个角度看,人们可能不愿意尝试Go,因为他们想要一种感觉复杂的语言……那种“哦,我需要学习一些超级酷且复杂的东西”的感觉,而不是他们认为更简单的语言。所以很难打破这个障碍,让他们意识到,“不论你的技能水平如何,你都会喜欢它。我保证。”
Brad Fitzpatrick: 你们知道YouTube正在开发一个用Go编写的Python运行时吗?我想叫Grumpy[23]……
Brian Ketelsen: 哦,知道。
Erik St. Martin: 是的,是的。
Brad Fitzpatrick: 看看他们能走多远会很有趣。也很有趣的是,是否会有其他语言使用Go作为它们的运行时。
Erik St. Martin: 是的,上周我们还讨论了一个项目,看到有人正在用Go实现Ruby运行时。我不确定它已经进展到什么程度,但我们确实看到了。
Brian Ketelsen: 那不是有两个吗?两个不同的用Go实现的Ruby运行时?
Erik St. Martin: 其中一个是用Go实现的类似Ruby的语言,另一个是要符合Ruby规范的运行时。
Carlisia Thompson: 现在我们在聊语言,但我迫不及待地想问一个问题,其他人也在问……Go 语言是否有可能支持 _泛型_?如果答案是肯定的,那这个前景如何?我之所以问这个问题,是因为显然很多人都想知道,人们总是问这个问题,而且据我了解,这个问题从来没有被明确否定过。我觉得这个可能性的大门一直是敞开的。
Brad Fitzpatrick: 是的,我认为基本上每个人都希望引入泛型;团队中几乎没有什么反对泛型的声音。我认为如果我们能够在标准库中引入一些算法,并且能够在标准库或者某个共享库中加入更多的容器和数据结构,那会很棒,即使这些东西不直接在标准库中实现。但目前还没有一个很好的提案……
Ian Lance Taylor 目前已经写了五六个提案了,每次他基本上都会否决自己的提案。他甚至实现了其中几个……所以他可能是最终解决这个问题的人。我不知道他需要写到第七个还是第八个提案……[笑声] 但我觉得他离成功越来越近了。他似乎每次都更喜欢自己新写的提案一点点。
Carlisia Thompson: 你说的是哪位 Ian?
Brad Fitzpatrick: Ian Lance Taylor。他是 golang 项目的 Ent@,在 GitHub 上就是 Ian Lance Taylor。
Brian Ketelsen: 他主要负责 Go 的 GCC 移植。
Erik St. Martin: 对。
Brad Fitzpatrick: 是的,他还写了 gold 链接器。他对信号、链接器以及这些复杂的东西了如指掌,而这些是我不了解的。
Brian Ketelsen: 那些我想忽略的神奇内容。
Brad Fitzpatrick: 对……每当遇到一些非常奇怪的 UNIX 问题,比如“这是一个带有 TTY 会话领导的进程控制组,它接收到信号然后某些东西挂掉了,等等等等……”他就会说,“当然了……在 UNIX 中,这一页规范是这样写的,除了某个特定版本的 UNIX,等等……”他非常了解 UNIX 的工作原理以及底层的东西,而且他也经常思考编程语言的问题……
总的来说,我觉得如果有 Go 2,它应该会有 _泛型_。我不认为我们会发布一个没有 泛型 的 Go 2;那样的话它就不够有吸引力了。如果要进行 Go 2 这样大的变动而不加入泛型,那就不值得。我想 Go 2 可能会在某个时刻出现,只是不确定具体时间。
Erik St. Martin: 是的,我也不认为你会告诉大家“泛型会在 Go 3 中实现”,当他们看到 Go 2 花了多长时间才推出时,他们就会知道这永远不会发生了。
Brad Fitzpatrick: 我还认为如果有 Go 2,我们不能像 Python 3 或 Perl 6 那样彻底“炸毁”整个世界,然后期待一切都会好起来。
Erik St. Martin: 哦,是的……
Brad Fitzpatrick: 我认为……我没有仔细考虑过细节,但我觉得如果在 Go 2 中,你可以导入 Go 1 的包并使用它,但是 Go 1 的包不能导入 Go 2 的包,因为两者的语义会有所不同。我认为我们必须在某种程度上让这两个生态系统共存。
Erik St. Martin: 这很有趣。我觉得我们错过了第二次赞助商广告的时间,所以我们还是先插播一下。今天的第二位赞助商是 DataDog。
Erik St. Martin: 好了,我们回来了,继续和 Brad Fitzpatrick 聊天。我们刚刚谈到了对于 Go 2 的愿景。有没有人想聊聊过去一周看到的一些有趣的项目或新闻?我看到一个很有意思的……
Brian Ketelsen: 我也有一个很棒的……实际上,我有三个好东西。
Erik St. Martin: 你有三个?
Brian Ketelsen: 我有三个好东西,所以你先说吧。
Erik St. Martin: 你是不是把好东西都占了?
Brian Ketelsen: 没有。
Erik St. Martin: 希望我不会把名字读错,我看到了一个叫 periph.io[24] 的项目,是 Marc-Antoine Ruel 做的。它是 Gobot[25] 的一个替代品,不需要任何支持库或者 CGO。我和他聊了一会儿,了解到它可以在 MHz 范围内进行位操作。我们其实已经安排了他两周后上节目,届时会有更多细节……但这个项目对做 GPIO、I2C 和 SPI 的人来说真的很棒……它也刚刚实现了单线协议,所以如果你在玩 BeagleBone 或者 Raspberry Pi,并且做 GPIO 相关的项目,这是一个很值得一试的项目。
Brian Ketelsen: 太棒了……可以用来做烧烤了。 [笑声]
Erik St. Martin: 我知道……很尴尬,因为我决定在做探针和其他东西时只用 ARM 处理器,直接用嵌入式 C,然后我看到了这个项目,我就有点想重新用单板计算机了。
Brian Ketelsen: 改变主意是可以的……绝对没问题。
Erik St. Martin: 是的。
Brian Ketelsen: 我有一个很酷的项目和一个致敬要提一下……我们的一位听众在徒步穿越阿尔卑斯山时听我们的 GoTime 播客,上周他给我们发了一封邮件,介绍了他的代码生成工具,因为他知道我有多喜欢代码生成……
这个代码生成工具在 github.com/dave/jennifer[26] 上。不幸的是,广播不能传达图片……不过,我们会试着找个办法发出 Dave 在阿尔卑斯山顶上拍的照片,照片里他对着我们挥手致意,因为他在听 GoTime。所以,致敬你,Dave……太棒了。我想 GoTime 大概是徒步那些无聊的阿尔卑斯山时最好的伴侣。
Carlisia Thompson: Dave 有姓吗?
Brian Ketelsen: 我不知道 Dave 的姓。我得翻一下邮件看看。
Erik St. Martin: 在爬完一座山后听到 “It is GoTime” 的播报会是什么感觉?
Brian Ketelsen: [笑声] 像天堂的声音。它听起来像天堂。所以这是一个。另一个很棒的公告来自 github.com/myitcv/react[27],这是为 GopherJS[28] 提供的 React 绑定。现在它还支持 Preact,这很棒,因为 Preact 比 React 小得多……所以我很期待有点空闲时间来玩一下 GopherJS 的 React 绑定。
这些绑定特别酷(它们是 Paul Jolly 做的),因为它们为所有繁琐的部分做了代码生成。所以你只需实现几个接口,然后运行 go generate
,它就会生成所有的 Go 代码,这些代码会被编译成 GopherJS 代码,进而与 React 或 Preact 交互。
Erik St. Martin: Brad,你也在做一些 GopherJS 的东西,对吧?
Brad Fitzpatrick: 不太多……Mathieu 正在将我们一些 Camlistore 的东西过渡到 GopherJS,并且开始使用 React,我看了看,觉得有点道理,但我自己用得不多。
Erik St. Martin: 我觉得 React 让我爱上了用 Go 来做 Web 应用。在这之前,像用 Rails 做前端那样会让我觉得“哦,做前端好难……”,但 React 实在是太容易让人搭建一个 UI 了,尤其是基于 Go 的 API。
Carlisia Thompson: 所以 Dave 的姓是 Brophy。
Brian Ketelsen: 哦,谢谢你。Dave Brophy,对的。
Carlisia Thompson: 别感谢我,感谢 Florin Patan[29]。
Brian Ketelsen: 哦,干得好,Florin!这就是为什么我们在 GopherSlack 里有一群听众来帮我们解围。
Erik St. Martin: 是啊,为什么我们是主持人?他们似乎比我们知道得还多。
Brian Ketelsen: 我知道,挺搞笑的,不是吗?
Carlisia Thompson: 他们确实比我们懂得多。我们只是随意发挥,他们做了所有的工作。
Erik St. Martin: Brian,是你问的“Go 2 真的会发生吗?”这个问题吗?
Brian Ketelsen: 不,那不是我。
Carlisia Thompson: 是我。
Brian Ketelsen: 是从 Reddit 上的吗?
Carlisia Thompson: 是的。Reddit 上有一个标题是 Go 2 真的会发生吗?如果是,那什么时候开始开发?[30]。这个帖子非常长。
Erik St. Martin: 有趣的是,我们刚刚谈到了这一点,谈到了它可能需要包含什么,以及大概的时间线……你刚刚说十年左右的时间点可能是对的,但听起来在那之前会有关于它应该是什么样子的讨论,以及提案之类的事情。
Brad Fitzpatrick: 我给你们一个有趣的思考题……如果你们做了 Go 2,并且我们从标准库中移除一些东西,你们会移除什么,或者说你们觉得可以移除多少?
Erik St. Martin: 哦,有意思。我觉得可能有很多东西可以移除……大概 30% 左右,基于我编写的代码以及我使用的组件之少。但这也很难说,因为有多少人使用我不用的那些组件呢……?
Brad Fitzpatrick: 你需要一个糟糕的 SMTP 客户端实现吗?
Brian Ketelsen: 不需要。
Erik St. Martin: 不需要。
Brad Fitzpatrick: 你需要 X509 吗?
Brian Ketelsen: 不需要……我们不需要 Archive,不需要 Compress,也不需要 Container。
Carlisia Thompson: 我其实用过 X509。
Brian Ketelsen: 但它们不需要在标准库里……它们依然可以放在别的地方。
Carlisia Thompson: 对。
Brian Ketelsen: 我认为标准库的门槛应该更高,可能可以去掉 80% 的内容,而不是 30%。
Brad Fitzpatrick: 那么,这里有个更疯狂的问题---
你能去掉 HTTP 吗?
Brian Ketelsen: 是的,绝对可以。
Brad Fitzpatrick: 但这也是人们意见不同的地方。很多人认为内置 HTTP 是很有趣的,但我觉得它有点维护起来麻烦。
Erik St. Martin: 是的,这就是两难的地方,对吧?因为标准库中的 HTTP 确实有优势,比如我记得刚开始使用 Go 时,做 HTTP 的工作非常容易,因为我不用去找一个库,或者写一个库,也不用纠结用哪一个是社区公认的标准库。然而,标准库中包含的内容越多,就越要符合 Go 1 的保证对吧?这意味着它不能轻易更改。所以将它移出标准库可以让它的发展速度更快。
Brad Fitzpatrick: 是啊。标准库中最有趣的事情是,你可以围绕某些类型构建整个生态系统。每个人都使用 time.time
和 time.duration
,或者 context.now
,对吧?而不是说“你使用哪个 context 包?”或者“你使用哪个时间包?”
这也是我们最初将 DatabaseSQL 添加到标准库中的原因之一,因为我们看到 GitHub 上有四五个数据库包,它们的接口完全不同,比如 MySQL、SQLite 以及一些 Postgres... 所以我们将它添加到了 Go 1 中,以便统一整个生态系统,使其感觉一致。但我不知道... 最小的标准库该是什么样的呢?
Carlisia Thompson: 我认为在回答这个问题时,你还需要考虑可用性,甚至有位听众 Chris Benson 提到过关于市场推广的事情,HTTP 在标准库中的存在有助于 Go 的推广。在看到他提到这个之前,我就已经在想这件事了。Go 的一个最大亮点是,“看,这是一门非常出色的服务器端语言!它甚至在标准库中就有 HTTP。用 Go 启动一个服务器非常容易!” 所以,即使维护它可能会有些麻烦,但你必须权衡它在吸引用户和提高可用性方面的作用。
Erik St. Martin: 是的,我觉得你提到了可用性问题,但我认为大家还是会有共识的... 比如说在 Ruby 社区---
有很多常用的包,社区公认那些包是大家都会使用的,虽然它们并不是标准库的一部分。我觉得有些像 time 和 context 这样的核心类型是必要的,因为它们可能会被共享使用。但至于你如何使用它们,比如 HTTP,任何抽象网络栈、系统调用的东西,Matt Layer 在 GoTime FM 频道中也提到了这些。
这些东西是我认为必要的,尤其是为了提高语言的采用率。很多人---
你也提到了,Brad---
并不熟悉 Linux 的底层机制,以及信号处理、系统调用和其他功能。将这些东西抽象出来,的确有助于提高语言的采用率。
Brian Ketelsen: 我们需要记住的是,回到我最早学习 Java 的时候,你需要选择一个 Java 框架,基本上就是选择你的标准库。是 Apache Commons 还是 Java X?如果我们从 Go 的标准库中移除太多内容,我们可能会通过迫使大家选择不同的包,来导致社区的分裂,这可能会很奇怪。
Erik St. Martin: 不过,现在有很多有趣的工具可以帮助我们找到包和工具,例如---
我们经常讨论的那个 Chrome 插件...
Brian Ketelsen: Sourcegraph[31]?
Erik St. Martin: 没错,Sourcegraph。它是一个非常有趣的工具,可以帮助我们找到包,看它们是如何使用的,以及有多少人使用它们。所以,问题真的在于这些东西必须在标准库中吗,还是我们需要更好的方式来找到这些东西?
我觉得困难在于维护,对吧?如果它在标准库中---
这有点像反方观点的论据---
我们可以保证它的维护。我记得早期有几个 MySQL 驱动程序被弃用了,你会想“好吧,现在哪个是最流行的?我们该迁移到哪个?”
Carlisia Thompson: 我觉得找到库可能不是最大的难题。你可能能找到东西,但接下来你需要决定用哪个库,你又该用什么标准来评判呢?我不知道... 回到 HTTP 的例子,我不能数清楚我见过多少次人们问“我应该用哪个框架?”而有经验的开发者会说“只用标准库就行,它很简单。即使你需要多写一些代码来获取参数值,也只用标准库”,然后人们会说“好吧... 即使有很多 HTTP 框架。”
Erik St. Martin: 那 Go 团队对于推广标准库之外的其他库的立场是什么呢?比如说,作为一种思想实验,如果这些标准库不存在,人们可能会期待 Go 团队指引他们使用某些库。Go 团队对此是什么态度?如果有一个更好的 HTTP 库,Go 团队会引导大家使用吗?还是你们尽量避免参与其他人的项目推广?
Brad Fitzpatrick: 其实,我们没有一个明确的政策来支持或反对。大多数情况下,我们不参与,因为我们没有时间在社区中做无偿的代码审查。我们曾经推广---
现在还在推广---
miekg DNS 库[32]。每当有人有一些比较复杂的 DNS 需求时,我们会说“这里有一个非常完善的 DNS 包,它可以满足你所有的需求。” 所以,是的,当有明确的解决方案时,我们会推荐给大家。
Erik St. Martin: 只要有资深开发者引导大家使用这些库,我觉得就没什么问题... 我有时候想过,可能会通宵去浏览一下,列出我觉得没用的库。
能做一个社区调查,看看大家的共识是什么,也挺有趣的。
Brad Fitzpatrick: 我觉得你不需要做调查。你可以查看 GitHub 上的代码库,对吧?你可以看看它们的导入包。我们在 GoDoc.org 上有这些数据,只是我们没好好利用。
Erik St. Martin: 这也是个好主意,没错。
Brian Ketelsen: 我觉得我们应该把所有的包放到一个岛上,让它们决斗,看看哪个能留下来。 [笑声]
Erik St. Martin: 打破一根扫帚...
Brian Ketelsen: 如果你没有实力,你就不能留下。
Erik St. Martin: 也许有趣的是,看看有多少包几乎没人用,或者用得很少。但这很难判断... 当你想用机器学习去分析这些数据时,要怎么训练呢?可能像 HTTP 这样的东西,天生就因为我们写的软件类型而被更多使用。
Brad Fitzpatrick: 我最近发现,很多人都在使用我写的一个包,我感到很震惊---
我写了一个 memcache 客户端,这是我用 Go 写的第一个包之一。当时我只是为了练习写包,实际上我自己几乎从未使用过它,但我写了很多测试,我启动了一个真正的 memcache 服务器作为子进程来测试它。然而,它的性能并不好... 它没有在连接上进行请求的流水线处理,所以如果你有很多活动在运行,你会发现所有这些新的 TCP 连接都指向你的 memcache 服务器,等等。 (译者注: 疑似这个是不是被DDOS攻击了..)
最近有一个 Google 云客户,还有一些其他的 Google 工程师开始调试这个库,并向我提交错误报告,说这个我几乎从未使用过的代码效率低下,我想“糟糕,现在我得维护这个东西了。”
Brian Ketelsen: 删除它。
Brad Fitzpatrick: 但是... 你知道的,我们的包管理工具几乎不存在或者很差劲,所以如果我删除它,我会破坏很多人的代码,这反而会带来更多问题。
Brian Ketelsen: 就像 left-pad 问题一样...
Erik St. Martin: 那么,继续这个思想实验,如果不是标准库的话,你会希望在 Go 2 中去掉语言的哪个部分或语法呢?
Brad Fitzpatrick: 我最近提议去掉复数(complex numbers)。
Erik St. Martin: 有趣。
Brad Fitzpatrick: 它们之所以存在,是因为 Ken(Ken Thompson)非常喜欢它们,但如果你查看现有的所有代码---
无论是 Google 内部还是 GitHub 上---
几乎没人用它们。
人们可能会为了好玩,用它们来实现曼德布罗集合(mandelbrot set)之类的东西,但除此之外,它们几乎没有什么实际用途。
(译者注: 是一种在复平面上组成分形的点的集合,以数学家本华·曼德博的名字命名)
另一方面,很多场景经常会用到大整数(bigints),而它们使用起来非常麻烦,因为你不能直接用 +
和 -
等内置运算符;你必须调用一些方法。所以我们现在处于一个奇怪的局面,复数在 Go 中是头等公民,但几乎没人用它们,而在加密等领域经常用到的大整数却不那么容易使用。 (译者注: 深以为然)
Rob 有另一个提议是让大整数自动化。int 类型不再是 32 位机器上的 32 位,64 位机器上的 64 位,而是... int 代表大整数(bigint),并尽可能高效地实现。如果编译器能证明它永远不会超过 64 位,那么它实际上是一个 64 位的整数,但如果无法证明,它在幕后会变成一个大整数。
Erik St. Martin: 我觉得我第一个想去掉的是 new
。
Brian Ketelsen: new
和 make
的区别?
Erik St. Martin: 大部分人都不用它,所以它通常只会让新手感到困惑,对吧?我们大多数人都会直接声明一个字面值并获取它的指针。你会发现很多刚学习这门语言的人,会觉得好像有多种方式声明变量。你可以用 var name =
来声明,或者用快速声明操作符,或者用 new
... 我觉得有太多种方式了,所以很难让代码保持一致。而我们总是希望代码保持一致性,对吧?所以这是我经常看到新手感到困惑的地方,他们不知道何时该用哪个,搞不清楚。
尽管我觉得看到一个空结构体字面量被声明并获取它的指针时,有点丑陋... 你没有用任何东西初始化它,为什么要使用字面量呢?Brian,你呢?有没有什么是你想第一个去掉的?
Brian Ketelsen: make
... [笑声]
Erik St. Martin: 那么,你的提议是如何声明切片和数组呢?
Brian Ketelsen: 我们已经有很多方式来声明内存了... 我觉得 make
并没有增加什么,只是增加了混乱。这是来自一个教 Go 的人的观点。为什么我们必须用 make
来创建切片和映射,而声明其他东西时用 var
就可以?
Erik St. Martin: 不过,有趣的是你也可以声明容量,对吧?在某些情况下这很重要。
Brian Ketelsen: 我不是在争论它是否有用,我只是觉得应该以某种方式改变它。我没有解决方案。
Brad Fitzpatrick: 如果 Go 2 有 _泛型_(Generics),你可以想象切片和映射是标准库中的一种类型,你可以用 bytes.new
,或者 slice.new
,或者 maps.new
,类似这样的方式。
Erik St. Martin: 是的,这倒是真的。
Brian Ketelsen: 你看到了吗?
Erik St. Martin: 是啊,Carlisia,你呢?你会删掉什么?
Carlisia Thompson: 我想不出什么,但是我真的很喜欢Erik的想法,把new
删掉。我会投票支持这个。
Erik St. Martin: 是的,这涉及到重新思考声明的方式。当你深入了解的时候,你会发现有很多不同的方式... 很多人在使用这个语言的过程中形成了自己的一套标准做法,但...
Carlisia Thompson: 我想到一个,那叫裸返回吗?
Brian Ketelsen: 哦,对。
Carlisia Thompson: 我们应该把它去掉。
Brian Ketelsen: 这个建议不错。
Erik St. Martin: 我刚开始学Go编程的时候老是用这个,现在几乎不用了。
Brad Fitzpatrick: 是的,有点遗憾的是裸返回和命名的返回参数绑在了一起... 但对,裸返回大概可以被去掉。或者说你有一个函数,它返回一个time.Time
和一个error
,但你只想返回error
,不关心其他参数的值;现在你必须写“return time.Time{}, error
”。有各种提案允许你使用下划线_
来表示任何类型的零值,或者你可以想象只返回错误error
,忽略其他参数。
Erik St. Martin: 哦,这很有趣。
Brian Ketelsen: 是啊,我喜欢这个。
Erik St. Martin: 这让我想到声明的方式... 我不太喜欢空的结构体字面量,比如time.Time{}
... 它没有任何上下文,因为你并没有用任何值初始化。所以如果能有一种更简洁的方式来使用零值,那就太酷了。我不知道那会是什么样子,因为我不是语言设计师,但这会很有用。
Brad Fitzpatrick: 在Go中还有一些奇怪的地方,比如在字符串上循环时,它给你的是UTF-8代码点,而不是字符串的字节,这是语言中唯一假设字符串是UTF-8的地方。所以这有点怪,还有很多这样的奇怪地方。
Erik St. Martin: 是的,这很有意思。我想这可能会成为一个问题,因为有些库假设输出是字符串而不是字节切片,所以你就会卡在这里。
Brad Fitzpatrick: 我觉得另外一个大问题是字节切片和字符串如此相似,却又如此不同,以至于我们不得不有两个包---``bytes
包和strings
包,而且在它们之间切换代价很高... 这真的很糟糕。
Erik St. Martin: 这种情况经常发生,因为大多数包假设你是想处理字符串,所以你的包接收字符串,然后用它作为字节切片进行一系列处理,最后返回一个字符串。但问题是,当我们把这些库组合起来时,我们就会在字符串和字节切片之间不断转换。
Brad Fitzpatrick: 其实,我很久以前有一个提案,想要改变语言和整个标准库,假设有一种类型表示可读的内存视图。字符串保证世界上任何人都不能改变它,包括你自己,而字节切片则表示你可以修改它,其他人也可能在修改它。不过,没有一种类型可以同时接受字节切片和字符串。所以我曾提出过一个内存视图类型的提案,这样你就可以写一个函数,既可以接受字节切片,也可以接受字符串,并对其进行某些操作,但你不能写入它,可能它是别人的。
Erik St. Martin: 这很有意思。所以,它可以接受字符串或字节切片,你只能读取,不能修改。
Brad Fitzpatrick: 对,我当时有个mem
包,里面有一个mem.rw
类型和一个mem.ro
类型,分别表示可写和只读的内存类型。
Erik St. Martin: 我还挺想看看这个提案的。
Brad Fitzpatrick: 我刚刚在Slack频道里贴了一个链接,是关于它的文档。
Erik St. Martin: 好,大家准备做“自由软件星期五”吗?
Erik St. Martin: 我把沉默当作“是”的回答了。[笑声]
Carlisia Thompson: 是的,来吧。
Brian Ketelsen: 抱歉,我因为家里有电锯声静音了。
Erik St. Martin: 哦,你在搞装修?
Brian Ketelsen: 是的。
Erik St. Martin: 每周我们都会给开源项目或维护者一个致敬,表达我们的敬意。那么这周,Carlisia,你要先来吗?
Carlisia Thompson: 这周我想向Changelog[33]网站致敬。它是一个艺术品,特别是我要感谢Jerod,因为他是这个项目的主要负责人,我尤其喜欢其中的搜索功能,真的让我很开心。如果你是听众,并且对任何与Go相关的话题感兴趣,你可以访问Changelog网站或GoTime网站,进行搜索,可能会找到一个或多个讨论该话题的节目。真的很棒。你可能会在节目注释中找到相关引用,或者发现一些讨论该主题的节目。
Brian Ketelsen: 不错!
Erik St. Martin: 你呢,Brian?
Brian Ketelsen: 我之前提到过,但我还是想再提一次,因为它真的让我很开心。Buffalo[34]用于Web开发。用Go写网站,没有比Buffalo更快的了。今天有人在Buffalo的Slack频道里问我,是否有人在生产环境中使用它,我想天哪,我从年初开始就在GopherCon网站上使用了Buffalo,还有GopherAcademy[35]网站,GopherTrain网站... 我可能有五六个Buffalo的网站在生产环境中运行,它们都运行得非常好。
Erik St. Martin: 看起来GopherCon和GopherAcademy的网站是任何用Go写的酷项目的试验场。我们很早就把Caddy[36]投入使用了,它本不该在生产环境中使用的...但我们还是用它搭建了GopherCon网站...
Brian Ketelsen: 为什么不呢?我有眼光,我告诉你。
Erik St. Martin: 我们还用过Hugo[37]来做CMS的部分...
Erik St. Martin: Brad,你有没有谁想致敬的?
Brad Fitzpatrick: 没有,我正忙着审查Carlisia的代码。[笑声]
Brian Ketelsen: 发布吧!发布吧?
Carlisia Thompson: 通过了!太棒了,谢谢!
Brad Fitzpatrick: 没问题。
Erik St. Martin: 这周我没有特别想提的项目,因为我最近没做什么新东西。我就向那些为Arduino传感器和相关库做贡献的人致敬吧,因为在最后一刻,Brian和我能够快速地拼凑出一个流式传输烧烤数据的项目,供我们烤猪时使用。
Brian Ketelsen: 太棒了,真是史诗般的体验。最棒的复活节。
Erik St. Martin: 我喜欢一些转换,不过我觉得芯片之间需要一个CRC校验,因为我不觉得四十亿度是个合理的温度。[笑声]
Brian Ketelsen: 这就是如何让皮肤焦糖化的方式。
Erik St. Martin: 对,简直就是终极慢煮。
Carlisia Thompson: 我们这次讲得这么快,难道不讨论Docker改名的事吗?(译者注: 改名为moby)
Brian Ketelsen: 不,我们不讨论Docker改名的事,我不想让我本来就高的血压再升高了。
Carlisia Thompson: 算了吧...
Erik St. Martin: [笑声]
Carlisia Thompson: 好吧。
Erik St. Martin: 那么最后,感谢今天节目的所有嘉宾,特别感谢Brad的参与。非常感谢我们今天的赞助商Toptal[38]和Datadog[39]。请一定要和其他Go开发者、同事、朋友分享这个节目。你可以通过访问GoTime.fm[40]订阅我们。我们也在Twitter[41]上。如果你有话题建议、对嘉宾的问题,或者想要上节目,请到github.com/GoTimeFM/ping[42]联系我们。好了,再见大家,我们下周见!
Brian Ketelsen: 谢谢你,Brad!
Brad Fitzpatrick: 对,谢谢!
Carlisia Thompson: 再见!
Go4 and Contributing to Go: https://changelog.com/gotime/44
[2]Brad Fitzpatrick: https://github.com/bradfitz
[3]Erik St. Martin: https://github.com/erikstmartin
[4]Carlisia Pinto: https://github.com/carlisia
[5]Brian Ketelsen: https://github.com/bketelsen
[6]GopherCon: https://www.gophercon.com/
[7]Steve Francia: https://twitter.com/spf13
[8]Perforce: https://en.wikipedia.org/wiki/Perforce
[9]go4.org: https://go4.org/
[10]Gardening: https://github.com/golang/go/wiki/gardening
[11]Dave Cheney: https://twitter.com/davecheney
[12]reviews 频道: https://gophers.slack.com/messages/C029WG6AM
[13]OpenCV: https://opencv.org/
[14]Napster: https://www.napster.com/availability
[15]Camlistore: https://en.wikipedia.org/wiki/Perkeep
[16]Rob: https://twitter.com/rob_pike
[17]Camlistore: https://perkeep.org/
[18]Let's Encrypt: https://letsencrypt.org/
[19]Andrew: https://twitter.com/enneff
[20]Upspin项目: https://github.com/upspin/upspin
[21]Kubernetes: https://kubernetes.io/
[22]crystal-lang.org: https://crystal-lang.org/
[23]Grumpy: https://github.com/google/grumpy
[24]periph.io: https://periph.io/
[25]Gobot: https://gobot.io/
[26]github.com/dave/jennifer: https://github.com/dave/jennifer
[27]笑声] 像天堂的声音。它听起来像天堂。所以这是一个。另一个很棒的公告来自 [github.com/myitcv/react: https://github.com/myitcv/react
[28]GopherJS: https://github.com/gopherjs/gopherjs
[29]Florin Patan: https://twitter.com/dlsniper
[30]Go 2 真的会发生吗?如果是,那什么时候开始开发?: https://www.reddit.com/r/golang/comments/65rqi6/is_go_2_actually_happening_if_so_when_will/
[31]Sourcegraph: https://about.sourcegraph.com/
[32]miekg DNS 库: https://github.com/miekg/dns
[33]Changelog: https://github.com/thechangelog/changelog.com
[34]Buffalo: http://gobuffalo.io/docs/getting-started
[35]GopherAcademy: https://www.gopheracademy.com/
[36]Caddy: https://caddyserver.com/
[37]Hugo: https://gohugo.io/
[38]Toptal: https://www.toptal.com/
[39]Datadog: https://www.datadoghq.com/
[40]GoTime.fm: http://gotime.fm
[41]Twitter: https://twitter.com/GoTimeFM
[42]github.com/GoTimeFM/ping: https://github.com/GoTimeFM/ping