本篇内容是根据2019年4月份#84 Hardware hacking with TinyGo and Gopherbot音频录制内容的整理与翻译

Mat Ryer 与特邀嘉宾 Ron Evans 共同主持了第一期一对一采访式节目。 Mat 请 Ron 教我们有关 IoT 中的 Go、GopherconTinyGoGopherbot的硬件黑客技术。

过程中为符合中文惯用表达有适当删改, 版权归原作者所有.




Mat Ryer: 大家好,我是Mat Ryer,猜猜今天是什么时间?对了,今天是Go Time!我们正在为机器人起义做准备,*剧透*:这将是非常可爱的。今天我们要讨论TinyGoGopherbot,我身边有Gopherbot的创造者;我听说有人称他为“开源界的圣诞老人”。他就是Deadprogram,也就是Ron Evans。嗨,Ron,你好吗?

Ron Evans: 嗨,大家好。其实今天是TinyGo Time。

Mat Ryer: 是的,TinyGo Time。

Ron Evans: 没错。

Mat Ryer: 你更喜欢别人叫你Ron,还是Dead?

Ron Evans: 嗯,我还没死,所以...

Mat Ryer: 那我们就叫你Ron吧。

Ron Evans: 对,Ron就好。不过我更喜欢人家叫我Deadprogram,像Prince一样---你不会叫他Pri,你只会叫他Prince。

Mat Ryer: 对,Deadprogram。它也可以像一个崩溃的符号,或者别的什么... 总之,欢迎来到节目。

Ron Evans: 只有在我和唱片公司产生分歧时,我才会这么做。

Mat Ryer: [笑] 说实话,我觉得这很可能会发生,Ron。

Ron Evans: 也不是不可能。

Mat Ryer: 很好。其实这是我们第一次做这样的节目。这会是一个非常亲密的节目,靠近麦克风,充满温暖,今天只有我和Ron,聊聊这些话题。

Ron Evans: 还有机器人,当然了。只有我和你,还有一群机器人。

Mat Ryer: 对。我们会多了解一下这些调皮的小机器人,可能从TinyGo开始,因为我认为这就是一切的起点,Go在这里起了作用,对吧?

Ron Evans: 是的。我以前上过GoTime,讨论过我在Go领域参与的一些其他项目---机器人、无人机、计算机视觉,最著名的是Gobot项目... 去年我还谈到了GoCV,这是使用Go和OpenCV进行计算机视觉的项目... 但我一直梦想的,或者说从一开始就想要的,是能够在最小的芯片上运行Go,以及这些微控制器上。这些是非常小的芯片,存在于所有东西中,比如键盘、鼠标、刹车系统... 这些小芯片连接到物理世界,促使事情在正确的时间发生,或者不发生,希望一切顺利... 但我们从未能在这些小芯片上运行Go,因为它们实在太小了。Go是一门很棒的语言,非常强大,能做很多惊人的事情,但它并不以小巧著称。Go的关键字数量虽然很少,但生成的二进制文件却很大,我们就这么说吧。

Mat Ryer: 是的。所以Go对这些微控制器来说太大了。

Ron Evans: 是的,而且大了好几个数量级。一个简单的Hello world程序,在Linux操作系统上编译时,大约有1.1MB大小。公平地说,它包括了整个Go运行时;它几乎包含了你可能会需要的一切... 一个只输出Hello world的程序,和执行一些相当复杂处理的程序,大小差别并不会太大,因为你一旦达到那个初始基准,差别就不太明显了。但当我们谈到微控制器时,我们可能在讨论的处理器只有64k的RAM,甚至更少。

我一直想要这个,但一直没有实现,人们也总是说,“Deadprogram,你疯了,这永远不可能实现。”不过有几个人尝试过,并做了一些很酷的事情。曾经有一个项目叫Emgo,它基本上把Go转译成C代码,然后你可以用GCC编译器为不同的基于ARM的嵌入式设备编译它。这是朝着正确方向迈出的一步,但它不是纯正的Go代码。尽管如此,这是一个非常酷的项目,它的主要开发者完成了很多了不起的工作... 但它依然未能实现我的目标。

我和其他一些人讨论过,试图说服那些我认为能够真正解决这个问题的人:“我们如何才能把Go编译成这么小的东西呢?”直到去年,大约是9月份,我才知道了这个TinyGo项目,它最初是由我的主要合作者Ayke van Laëthem发起的。他参与了多个嵌入式领域的项目,特别是MicroPython,这是一个可以在微控制器上运行的Python版本。

他的态度是:“如果Python可以在微控制器上运行,如果JavaScript可以在微控制器上运行,那为什么Go不可以?”但他的方法非常独特,也非常强大。

其实,Go是用Go编写的。Go编译器是用Go编写的。

Mat Ryer: 它以前不是用Go写的,对吧?

Ron Evans: 对,以前不是。最早是用C写的...

Mat Ryer: 嗯,那他们当时为什么不用Go呢?

Ron Evans: ...所以你必须用C编译器比如GCC来编译Go,然后一旦你编译好了Go编译器,你就可以用它来编译Go程序。所以直到---我记不清是哪个版本了... 可能是1.5左右。

Mat Ryer: 我也这么记得。

Ron Evans: 我不记得具体的版本了,但编译Go编译器本身是一件非常复杂的事情。但后来有一段时间,Go编译器完全用Go编写。这对Go核心团队非常有用,也对任何想为Go编译器做贡献的人有用,因为如果你能读懂Go语言,你就能读懂编译器代码... 这也是其他一些非常酷的开源语言面临的问题,比如Ruby或Node.js,人们说“哦,我想为这个项目做贡献”,可他们会发现:“对不起,它不是用JavaScript写的,它是用C++写的,而我不会C++,所以... 抱歉,我不能真正做贡献。”所以Go是用Go写的,这无疑降低了门槛,同时也创造了新的可能性。

因为Go可以用Go解析自己的语言,你可以使用Go自己的库和工具,然后将其转化为所谓的单一静态赋值(SSA)形式,这就是---当你将Go语言的文本交给Go编译器时,编译器会将其解析,拆解并转化为SSA形式,然后Go编译器的工具链再将其转化为机器代码。

Mat Ryer: 理解。

Ron Evans: 所以Ayke的想法是:“嗯,如果我能拿到这个SSA形式,我就可以用LLVM工具链将其转化为二进制代码。” LLVM是一组已经存在相当长时间的编译器库和工具。我不确定它具体有多久... 至少我用了12年了,但它可能存在的时间更长... 它已经非常有名了,因为有些语言使用了LLVM,而这些语言吸引了很多人的兴趣。其中一个是Swift。Swift是基于LLVM编译器工具链的语言。另一个是Rust。

Ayke利用Go编译器工具链生成的SSA形式,然后TinyGo---这个编译器项目---接过这个SSA形式,转化为LLVM的中间表示(IR),这样就可以为LLVM支持的目标架构进行编译。其中一些目标就是微控制器,比如Arduino,它使用的是AVR微控制器。所有基于ARM的微控制器,比如Adafruit的Circuit Playground Express,这是一个非常酷的微控制器... 所有新的Arduino都基于这些类型的ARM微控制器,比如Arduino Zero和MKR1000。所以几乎所有有趣的、小型的、廉价的芯片都基于这样的微控制器架构,如果我们能将代码编译到这些设备上...

今年2月,我在布鲁塞尔的FOSDEM大会上首次展示了TinyGo,场面非常激动人心。Ayke从他所在的荷兰赶来了,还有其他地方的贡献者... 在我的演讲之后,我们还举行了第一次“志同道合者”会议,FOSDEM的组织者很慷慨地把我的演讲安排在主会场,所以我实际上是第一个在FOSDEM主会场里讲述Go的人。这真是太神奇了。我心想:“你们应该先挑选一个真正的Go专家,但...嘿,TinyGo!让我们开始吧!”不过,能够分享这些成果真的很激动人心,我们发布了软件的第一个版本。

我展示了很多演示,但最吸引人注意的是,我编译了一个500字节大小的TinyGo程序,它运行在一个8位的微控制器上,叫做ATtiny85,它只有8k的RAM。

Mat Ryer: 哇哦。

Ron Evans: 所以我可以为一个只有8k RAM的8位微控制器编译一个Go程序。

Mat Ryer: 那真是非常小。

Ron Evans: 是的,非常小。我选择它基本上是因为这个微控制器的名字里有“tiny”这个词,我承认。

Mat Ryer: 哈哈。所以Go源码被转化为SSA,然后TinyGo工具链接手,从那里生成这些小程序... 那么代价是什么呢?你失去了什么?11k的Hello world中缺少了1.1MB版本中的什么东西?

Ron Evans: 这就是关键---我们无法做到将100%的信息压缩到0%信息,我相信这是不可能的...

Mat Ryer: 对,没错。

Ron Evans: 它并没有包含Go中的所有东西。一个很大的区别是,当你在没有操作系统的裸金属上运行时,运行时是不同的... 所以我们必须以不同的方式实现运行时调用。

另一个挑战是Go的标准库。我们可以编译很多标准库,但有些部分我们不能,因为它们与运行时本身紧密耦合。

Mat Ryer: 是的。

Ron Evans: 所以在这些情况下,我们需要实现一个更偏向操作系统无关的标准库版本。因此,这涉及一些权衡。我们目前还无法编译所有的 Go 代码……但这也并不是我们主要的目标。

Go 核心团队的工作非常出色。我们并不是在尝试取代 Go,也不是说“Go 不好,TinyGo 很好。”完全不是这个意思。恰恰相反,我们的观点是:“哇,Go 是一个如此棒的语言,我们希望在更多的地方运行 Go 代码。我们能否提出一个新的 Go 运行时和标准库实现,同时仍然保持使用同样的 Go 编程语言呢?而且,这样的话,是否可以继续使用 Go 的标准库呢?”也许是全部,或者大部分,至少相当一部分。

但是,由于它需要运行的环境,存在一些权衡。然而,一个巨大的好处是,我们不需要携带所有额外的东西。毕竟,没有人会一次性使用整个标准库。如果你真的这么做了,那你的代码真的是非常庞大啊,朋友们!

Mat Ryer: 你肯定不想在 Tiny 这种边缘硬件上运行这样的大代码吧……有些东西是显而易见的,比如操作系统、打开文件等---在没有多少文件系统的情况下,它们可能会有所不同。我不知道这个例子是否合适。

Ron Evans: 这个例子其实很好。在微控制器上,你根本没有文件系统,对吧?但你可以……我们目前还没有实现它,但它在我们的路线图上。有很多小设备通常会有闪存或者 SD 卡接口。这些设备通常使用 SPI 接口,这是一个低级硬件接口,微控制器可以通过它与设备通信。这样,设备上就可以有一个文件系统。非常常见的是,这些设备默认使用 FAT 文件系统……所以当你获得一个 Adafruit Circuit Playground Express 时,它自带一个 1 MB 的闪存,你可以用它来存储你可能想要从微控制器代码中读取的各种数据文件。最终---我们目前在 TinyGo 中还不支持这一点,但它在我们的路线图上;例如,你可以有 wav 文件,然后使用内置的数模转换器 (DAC) 播放它们……所以你可以作为一些有趣交互的一部分播放 wav 文件。或者,你可以远程记录数据……对于那些并非一直连接云端的设备,或者本来就不打算连接云端的设备,你也许仍然希望能够保存数据。

Mat Ryer: 对。

Ron Evans: 也许你想训练你的设备来识别你的声音,但你不想把任何数据放到云端;你需要某种本地存储。因此,这些是你需要实现的低级接口。有些人使用所谓的实时操作系统来实现这些功能,这并不是一个完整的操作系统,但它可能具有某些功能……比如一些内存分配功能、文件读写功能、网络功能等等……但我们尽量在能用 Go 标准库的地方使用它。

Mat Ryer: 那么在这个例子中,TinyGo 需要有自己的 OS 包吗?这个包的功能完全不同,但可能复制了标准库 OS 包的接口?你会这样处理吗?

Ron Evans: 这实际上就是我们正在做的事情,在多个场景下。例如,我们一直在为 MacOS 添加支持,以一种操作系统无关的方式实现它。但一个更好的例子是裸机环境,在这种情况下我们需要能够说“哦,根本没有操作系统原语”,所以我们要么自己实现它们,要么以某种方式不实现它们。

我们在 TinyGo 的 wiki 页面 上讨论了我们遇到的主要挑战,其中之一就是 Go 本身当前实现的紧密耦合---即运行时和标准库之间的紧密耦合。实际上,有一些非常棒的演讲是关于这个话题的……我参加了其中一个讨论 Go 2.0 设计的演讲。Ian Lance Taylor 做了这个演讲,讨论 Go 2.0 过渡。他做了几次这个演讲,我第一次是在 GopherPalooza,我记得是在旧金山举行的。那是去年举办的一个非常酷的会议。他讨论了运行时和标准库之间的紧密耦合,以及一些解耦的提议……这样,如果你正确实现了运行时,理论上整个标准库仍然可以继续工作。

对于 TinyGo 来说,这是一个技术上的巨大挑战,但我们能够通过重新实现一些逻辑上的原语来绕过这个问题,特别是在你运行在内存非常有限的设备上时。

还有一些其他重要的差异,比如微控制器到底是如何工作的?在微控制器上,你有寄存器,这些寄存器通常用于非常低级的硬件通信。它可以通过 GPIO 接口打开和关闭 LED,或者它可以与直接连接到微控制器的其他芯片通信,比如我们的小闪存示例中的 SPI 接口,或者许多传感器使用的 I2C 接口,比如数字指南针(更正式的名字是磁力计)、加速度计(运动检测器)、温度计……有很多传感器使用 I2C 接口。

TinyGo 最重要的工作之一是创建驱动程序,这些驱动程序提供标准接口---同样是用 Go 定义的---这样你可以编写一些代码,如果它使用的是 Circuit Playground Express 板上的同样的 LIS3DH 数字加速度计,那么同样的代码可以移植……今天 Hacker News 和一些网站上有一个项目是关于一个自制智能手表的---我不知道你们今天是否看到了这个项目---它使用了相同的数字加速度计。所以我们可能---我还没有拿到那个硬件,也没有仔细看,但如果它使用的是 TinyGo 支持的处理器之一,我们理论上可以在这个手表上运行 TinyGo,然后连接到它已经有的同一个传感器,几乎不用更改代码,甚至可能完全不需要更改。

Mat Ryer: 哇,这太棒了。

Ron Evans: 是的,这种硬件抽象层非常重要,因为你不总是能确切知道你想要使用哪种目标硬件,所以我们可以解耦那些知道如何执行标准功能的驱动程序,比如读取温度、检测加速度计的运动,无论它运行在哪个芯片上,无论是来自微芯片的,还是 Nordic Semiconductor、NXP 或者 Intel 的……通过这样做---这符合 Go 的精神,Go 试图做到操作系统和架构无关;我们只是将其扩展到 Go OS 无操作系统……这应该是我们的理想用例。

Mat Ryer: 是的。你刚才提到了接口……这是否意味着你可以在这个地方编写单元测试?如果你正在处理 Go 中的一个接口,这是一个不需要物理硬件的测试机会吗?你可以只针对这个接口编写测试代码。

Ron Evans: 是的,这绝对是这样的……首先,关于测试。测试在任何现代软件开发中都是绝对必要的。

Mat Ryer: 毫无疑问。

Ron Evans: 然而,如今已经是 21 世纪了,大多数嵌入式软件仍然主要使用的是非正式的手动/功能测试。笑话是这样的:“嘿,我刚刚看了一下这个程序,它有 10,000 行代码,没有测试。”“什么?!这不可接受!”“哦,这是一个嵌入式程序。”“哦,没事了。发布吧。”

Mat Ryer: [笑]

Ron Evans: “别担心,它只是在一个喷气式飞机上,或者也许是在一个用于脑外科手术的激光器上……没什么太重要的东西。” “我们实际上也不知道。我们只是把这些芯片卖给某人,他们又把它们卖给一些公司,最后他们用来做某些东西。”

Mat Ryer: 确实是这样……这不是他们的问题,对吧?

Ron Evans: “问题总会得到解决的。”所以这种方式显然不是开发软件的正确方法。因此,首先,正如你所说,我们可以使用接口来测试一些不一定需要连接物理硬件的东西。我们现在使用 QEMU 做了一些这样的工作,这是一个硬件的模拟器。还有一些其他很酷的项目……Antmicro 有一个项目,我现在记不起名字了,但它的具体功能就是提供一些微控制器的模拟。所以有很多我们可以做的事情,来对不同的嵌入式系统进行全面深入的测试,使用现代语言和现代编译器---如果我们谈论的是软件可靠性,这在涉及边缘设备时就变得更加重要,因为安全显然是一个大问题……但还有一些次要影响;如果它收集信息不正确,这可能会导致我们忽视某些问题……比如,洒水系统可能不是关键任务,但如果它浪费了大量的水,长期来看这是非常糟糕的。

Mat Ryer: 是的。

Ron Evans: 短期来看也很糟糕,因为你会收到一张巨额的水费账单。所以通过测试,我们可以避免这些问题。另一个是时间测试。如果我们想测试我们的洒水系统,确保它正常工作,如果我们只有物理功能测试,那么每次迭代我们都要让它运行一整周,以确保它在正确的时间开启和关闭。

如果我们能够编写一些单元测试,来测试它是否在正确的时间触发事件,我们可以加快进度---这是正常的迭代式软件开发,正确的模拟机制和接口设计可以帮助构建更好的架构。如果我们将这些结合起来,这真的是我们编写接触物理世界的软件的唯一希望。

Mat Ryer: 是的。

Ron Evans: 最后一毫米。

Mat Ryer: 是的,接触物理世界是一个很好的点,我现在可以谈谈我们今天要进行的精彩赠品活动。我们要求大家要么对播客进行评价(最好是正面的),要么分享它,告诉你的朋友这个播客,特别是这一集……所以当这一集上线后,如果你在社交媒体上分享它,或者只是推荐给一个朋友。如果你想参加抽奖,请截个屏幕截图证明你确实分享了,并发送到 GoTime@Changelog.com。相关信息会在节目笔记中,但你肯定不想错过这个机会,因为我觉得奖品非常棒。Ron,现在或许是一个好时机来谈谈那个奖品,我们可以深入了解一下那个项目。

Ron Evans: 是的,我们将赠送一个 Gopherbot。什么是 Gopherbot?Gopherbot 是一个可以用 TinyGo 编程的机器 gopher 毛绒玩具。

Ron Evans: 很多人有这些非常棒的 gopher 毛绒玩具,它们是你在 Gophercon 和其他酷活动中获得的……我和我弟弟 Damon 一起合作,他也是一个硬件黑客,他设计了一个 3D 头盔,我在里面安装了很多 LED 和传感器……人们非常喜欢它。所以我们想,“哇,这是一个为我们的开源努力筹集资金的好方法,同时还能创造一个非常酷的、可编程的、可收藏的机器人毛绒玩具。”所以 Gopherbot 是我们的表达方式。它使用来自 Golang Market 的非常棒的 gopher 毛绒玩具,结合了一个 3D 打印的定制头盔。

有两种不同的毛绒颜色,还有十种不同的头盔颜色。我还没有决定有多少种不同的 LED 颜色……我还没告诉大家他们可以选择 LED 颜色。这会是活动结束后的一个惊喜。它内置了一个 Adafruit Circuit Playground Express 微控制器,这是 Adafruit 公司出品的一个非常酷的圆形微控制器。这家公司总部位于纽约,在硬件和软件方面都做了非常创新的事情。

在头盔里有一个 RGB LED 阵列,包含 15 个不同的 LED,每一个都可以单独控制它的 RGB 颜色。我们还有一个可以弹簧式闪烁的 LED,它真的可以弹簧式闪烁。你可以“嗡嗡”地弹动它,它仍然可以工作。

Mat Ryer: 这是我最喜欢的部分。如果你去 Gopherbot.com,有一个 gif,我猜是你做的,Ron,它展示了这个项目,展示了小 Gopherbot。然后其中一个场景就是剪辑到 Ron 在弹他的头顶上的弹簧。这太精彩了,所以你一定要去 Gopherbot.com 看一看。

Ron Evans: 那是最具工程挑战的部分---一个可以安装在弹簧上的 LED,还能够在弹簧弹动时继续闪烁。

Mat Ryer: [笑] 是啊。我是说,作为软件开发的任务要求来说,这个肯定是其中之一。你看,我真的很高兴这件事能发生,因为我看过一些关于 TinyGo 的演讲,每当软件触及现实世界时,我就非常兴奋……因为我基本上整个职业生涯都是做网页开发的。所以当我听说 TinyGo 时,我就在想:“我该怎么玩这个呢?我希望有一个套件,我可以把它组装起来,开始实际编写代码,做点事情……”然后,当然,Gopherbot 就出现了,这正是它的用处,不是吗?

Ron Evans: 没错。这个套件包括 LED 头盔、弹簧、电路板和一个可以连接的背包……电路板内部有很多传感器。有一个光强度传感器,有一个加速度计,可以检测 X、Y、Z 轴的运动,或者检测它被移动的情况……还有一个内置的 MEMS 麦克风,使用 I2S 接口进行声音录制。还有一个数模转换器,它有一个小小的扬声器……它还配有九个 NeoPixel LED,你可以单独控制它们的颜色……

我们在 Furriebot 的 Instagram 上发布了很多视频,我们展示了不同的场景---看起来好像是经过滤镜处理的,但实际上没有一张照片是经过滤镜处理的。它们都是用我的安卓手机拍摄的,只是角度不同。有些照片是和一些著名的机器人或玩具、我的收藏品一起拍的……我真的很喜欢玩具。

Mat Ryer: 那个 Instagram 账号是什么来着?

Ron Evans: Furriebot

Mat Ryer: 我很惊讶这个账号名字居然还没被用掉。所以你可以编写 TinyGo 代码,然后将其刷到 Gopherbot 上吗?是这样的吗?

Ron Evans: 完全正确。你在电脑上编写代码,编译它,然后将代码传输到微控制器上,也就是那个小小的 Circuit Playground Express 板上。从那时起,你可以断开与电脑的连接,因为所有的 Go 代码都在那个小电路板上运行。

例如,如果你想做一个类似于电子宠物的小玩具,带着它到处走,或者你想去参加一个聚会,并希望它的面罩能跟随音乐的节奏闪烁,或者在电池上运行---你可以做到这些。Gopherbot 本身没有内置无线通信功能,但你可以很容易地添加它。

我在 FOSDEM 演讲中展示的一个演示是将一个 ESP8266 Wi-Fi 芯片连接到微控制器上,这样它就有了 Wi-Fi 功能。但这是我们没有内置的东西。我认为人们不一定想要联网的玩具,但他们确实想要可编程的玩具。

Mat Ryer: 是的。

Ron Evans: 这些是两种不同的东西。一种是“哦,Hello Barbie 在监听你,并将你最深处的想法传回我们的公司总部……”你知道的,这不一定是好事。另一种是你可以自己编程让 Barbie 做不同的事情。Barbie 的创造者可能会说:“哦,如果 Barbie 说了我们不想听的话怎么办?”嗯,这就是重点,不是吗?

Mat Ryer: 是啊,这就是关键。

Ron Evans: 可编程玩具会被用于创造者没有预料到的事情中,而这正是重点;这就是让它们有趣的原因。

Mat Ryer: 对。

Ron Evans: 我们看到过一些令人难过的消息,比如 Anki。Anki 是一个非常酷的机器人创业公司,曾获得非常丰厚的资金。他们几年前在苹果 WWDC 上凭借蓝牙遥控赛车大放异彩……但他们突然宣布公司解散了,这太可惜了。令人遗憾的消息。但我认为他们产品的问题之一是他们制造了不可编程的玩具。那些玩具只能做他们 API 内置的功能,无法超越这些限制,所以所有的软件开发工作都依赖于他们自己的团队。而且,如果你想超越这些功能,你要么完全无法做到,要么就像我们对 Tello 无人机所做的那样,需要付出大量的逆向工程成本。如果不是我们六个人对 Tello 稍微有点疯狂地痴迷于让它飞起来,我们不会投入如此多的时间编写 Lua 脚本和其他内容,那它根本不会存在。

玩具制造商真的有必要这样限制你吗?而实际上,只需要稍微多一些努力---在我看来,所有的玩具都应该是可编程的。所有的玩具都应该是可破解的。特别是如果它本身具有可编程能力,那这些能力就应该被开放出来。至少那样我们可以自信地看着它说:“哦,实际上它并没有监视我们并将信息传回 Gopherbot 总部。” [笑] 它是可编程的;你可以自己添加这种功能,但这不是我们打算做的事情。

Mat Ryer: [笑] 没错。但你说得对,实际上我认为这适用于所有东西。让东西变得可破解,这样人们可以拿来玩弄---这才是乐趣所在,不是吗?这就是其中的所有乐趣。对于玩具来说,我小时候也是这样,玩了一段时间之后,可能是几个月,我肯定会找螺丝刀,因为我想知道里面发生了什么。所以我们无论如何都会这么做;他们还不如让我们这么做。

Ron Evans: 是啊,没错。我打赌,你的玩具有多少能撑过一个小时没被拆开?我们得问问你的父母才能确定。[笑] 我敢打赌,几乎没有几个能在头几天里幸免于被拆开,因为它们本来就不应该这样,对吧?如果它们真的说:“是的,这个玩具可以被拆开并重新装好,还能继续工作”,那不是很棒吗?

Mat Ryer: 是的。另一方面,反例就是乐高。乐高如果不去搭建和改装,它就是垃圾。否则它只是一袋砖块。所以是的。

Ron Evans: 没错。踩上去还危险。

Mat Ryer: 没错。实际上,在我们国家,唯一比它更糟糕的东西就是英国的电源插头。

Ron Evans: 哦,是的。

Mat Ryer: 它们本质上非常危险。它们天生就是尖刺朝上的,所以……[笑] 我们很多人都有踩到插头的惨痛记忆。顺便说一下,Ron,这很有趣……Justin Clift 在 Slack 上---顺便说一下,听众们,如果你们在听直播,你们可以加入 Gopher Slack 或 \#gotimefm 频道……Justin Clift 在那边,他刚刚在讨论 WebAssembly,有人试了一下,用 TinyGo 编译的 2.5 MB Go WebAssembly 二进制文件只有 575 字节,这挺不错的。

Ron Evans: 是的,我们说过我们并不是想接管 Go 的所有用例,这是真的,但可能有一些我们可以做得更好一点(双关)。我现在可以同时说 Tiny 和 Go 的双关语,理想情况下在同一句话里。

Mat Ryer: 哇,这太棒了。

Ron Evans: 这是三重关语。很少有人尝试,偶尔有人成功,但我看看能不能做到。

Mat Ryer: 偶尔成功的只是双关。

Ron Evans: 是的,没错。WebAssembly 非常有趣。对于那些完全不熟悉它的听众来说---虽然我会感到惊讶---WebAssembly 是一种新的尝试,旨在创建一个新的网页运行时环境,让代码在网页浏览器中能够访问更多本地功能,从而提高处理速度,使其更高效。它并不是为了取代 JavaScript,而是为了多种原因增强它,性能无疑是其中非常重要的一点,尤其是在很多情况下。

有许多语言能够编译成 WebAssembly,实际上它是一种设计用于在沙箱中执行的指令集。LLVM 是编译工具链---你可能还记得,TinyGo 就是使用它来生成代码的……LLVM 可以生成 WebAssembly 作为它的后端。

我们有几个人专注于 WebAssembly 的部分。我对它的了解出乎意料地少,我还在学习。Justin Clift 正在研究这个,Johan Brandhorst 最近在 DotGo 上做了一个很棒的演讲,其中提到了 TinyGo,现在他也是我们 TinyGo 团队的一员,在帮助确保 TinyGo 在 Web 上的安全性。

回到开始---Go 很棒,Go 很强大,但 Go 太大了,下载一个 1 兆的东西到你的移动设备上,这基本上是行不通的,尤其是当我们谈论远程地区时,带宽非常昂贵且有限,甚至可能根本无法实现。

那么,如果我们能够将 Go 代码编译成可以在 WebAssembly 中执行的代码,并且能够利用更小的可执行文件,同时保留我们喜欢的 Go 的语法和功能---哇,对于如此小的东西来说,这真是一个巨大的进步。所以这是 TinyGo 的一个重要发展领域。微控制器是一个,WebAssembly 是另一个,还有两个我想简要提及的。

Justin 在 Slack 频道里说:“用 gzip 压缩后可以降到 408 字节。” 是啊……有时候你会想,“我们还能多省几个字节吗?” 你得节省几个字节,因为你可以……但这也是重要的。我们现在对技术的使用已经非常宽松了。我们对技术的过度使用是惊人的。

作为一个年轻程序员,我曾经看到过最令人惊叹的事情之一是在 Commodore 64 上的 GEOS。它实际上是一个完整的窗口操作系统,运行在 64k 的 RAM 中。简直不可思议。我有一次见到了其中一位创造者,我完全是个粉丝。我说:“你们是怎么做到的,简直太不可思议了。” 然后我想到我们现在浪费了多少资源,想着“哦,没关系,计算是廉价的。” 但计算并不廉价。只是成本被外部化了。发电的成本,冷却的成本---这些成本很多都被转移到了环境,而不是由任何人真正支付。

随着时间的推移,计算效率将变得更加重要,一方面是因为资源的利用,另一方面是因为我们对计算的需求也在增加。我们希望机器学习算法能够在边缘计算设备上执行,在那里它们可以真正发挥作用。尽管 Machine Box 做的东西很酷,但它对无人机的碰撞避免算法没有帮助,因为我们必须在无人机上直接执行该算法,否则如果那天 Verizon 网络不佳,它就无法发挥作用,对吧?

Mat Ryer: 是的,没错。

Ron Evans: 这些东西都有它们的用例。这不是一个非此即彼的选择。这是一种错误的二分法。TinyGo 的使命是说:“有些地方 Go 还没有去过。我们希望 Go 能够去到那里。” 因为任何足够成熟的语言都有不止一种实现。看看 Python 有多少种实现。看看 C 有多少种编译器。C++ 有多少种实现。JavaScript 有多少种实现。而 Go 只有一种,直到 TinyGo 出现。我见过一些其他尝试,但没有一个真正说要“使用 Go 本身来编写一种新的 Go,它仍然是 Go,但能够做一些重要的事情。”

最后一个大话题是未来。未来……[唱歌] “未来啊啊啊啊啊……” [笑声] 我们现在正处于我所见过的计算最激动人心的时代。不是开玩笑。为什么?因为我们正处于定制硅片的寒武纪大爆发的第一步。

我们多年来一直在讨论:“如果你能创建专用芯片,将某些类型的处理变得更高效、更便宜,那不是很棒吗?” 但没有实际的方法来做到这一点。你需要找到那些掌握深奥知识的芯片设计师,还要支付巨额的许可费用给那些提供帮助的公司---不仅仅是因为他们让你这么做,还因为专利问题,但你也确实做不到没有他们的帮助。比如,“我要造一颗新芯片。” 十年后,“是的,我们要造一颗新芯片。” “那你进展如何?” “嗯,这真的很难做到。”

RISC-V 是一种技术,有些人听说过,有些人只是听到这个流行词……它实际上是一个开源的硅片设计集,这样你就可以像我们能够构建自定义操作系统那样构建自己的定制芯片;比如从 Linux 的某些部分创建自己的 Linux 发行版---我们将能够用定制硅片做同样的事情。所以 TinyGo 将能够运行在 RISC-V 上,因为它使用的是 LLVM 后端……我正在等待我的 Sci-Fi 原型板到货。我本来打算在告诉任何人之前就运行一个演示,但我太兴奋了,因为很多人都在用 RISC-V 做一些很酷的事情,而我还在等我的货……我已经等不及了,我必须说出来。

Mat Ryer: [笑声]

Ron Evans: 但如果你考虑一下这意味着什么,尤其是在为解决那些因为所需的传感器太多而太昂贵的问题,或者因为传感器所需的位置太远而太难解决的问题时……你知道我在说什么问题,当然是气候变化。那位著名的 Bret Victor,以在编程界面方面的惊人实验而闻名……如果你还没有关注 Dynamicland 的最新进展……这是一个非常糟糕的名字,但技术却是不可思议的,通过使用物理对象进行现实世界编程……他们做的事情简直令人震惊。

Mat Ryer: 哇。

Ron Evans: 我简直不敢相信我现在忘了那个名字……尴尬。不过他有一篇很棒的博文,叫做《我们作为技术人员能为气候变化做些什么》。显然,这是我们时代最重要的问题之一,因为它会对我们生活的物理世界产生影响。作为技术人员,我们能为此做些什么?他列出了不同的技术,无论是更好的可视化和科学分析技术……这离我有点远,因为我不是科学家(虽然我认识一些),而且我没有经过同行评审的论文……但我是个技术人员,所以其中一个领域是我们需要更好的技术来控制物理世界,监控和控制物理世界,作为我们对这些不断变化的环境条件的广泛应对的一部分。

为了做到这一点,我们首先需要能够重新利用现有的很多技术。现在有很多芯片---我们需要能够回收它们。这就是为什么我花了很多时间研究 TinyGo 的 AVR(Arduino)功能的原因之一。这是一种非常旧的架构,功能非常有限,但有很多芯片和开发板可以被重新利用来做我们需要做的有用的事情。

每一种足够先进的技术起初都是以玩具的形式出现的。这是对 Chris Dixon 的一句话的改编……但是你从玩具概念开始,玩弄这些概念。这样,当你说“我在玩它”时,你就不用真正做任何有用的或工作的东西,对吧?“我在玩 WebAssembly。” 这意味着“我不是真的要负责写一个能工作的 WebAssembly 程序。我只是在尝试。”

Mat Ryer: 是啊。

Ron Evans: 所以没有压力。我可以自由地学习和实验而不需要为任何特定的事情负责。在某个时候,我要么把它放到一边,玩别的东西,要么我跨越了从“你还在玩吗?”到“是的,我现在在用它做 X”的鸿沟,其中 X 是一些有用的任务。这就是一切的开始。所以玩具是我们作为开发者适应这些新事物的第一步---回到 Matt 刚才说的……你是一个网页开发者;你对网页技术有很多了解,并且深入思考过它……现在你可以将这些原则应用于边缘计算,并解决其中的一些问题。我们需要的开发者将来自于这样的工作群体。不会突然冒出一群神秘的机器人专家,他们已经完全成型,准备就绪。我们必须与我们现在拥有的人类合作。我们就是救援队,别无他法。

Mat Ryer: [笑] 这就是为什么我喜欢 Gopherbot 项目,因为它给了每个人这样的机会。它给你一个可以玩的东西,并且它提供了你所需要的一切。所以我建议大家去 Gopherbot.com 看看。

Ron,你会去 Gophercon 吗?

Ron Evans: 是的,实际上今年的 Gophercon 将是有史以来最大最好的一次。它将在圣迭戈举行,这个地方……

Mat Ryer: 很热。

Ron Evans: ……在南加州,我家人住在那儿,所以你可能会见到我的父母……但更重要的是,在社区日---Gophercon 是一个为期四天的会议。第一天是教程和工作坊。会有一些非常棒的工作坊。Mark Bates 会做一个很酷的关于测试的……Mat,你有做什么吗?

Mat Ryer: 没有,我会演讲。

Ron Evans: 我知道 Johnny 会做一个,Bill Kennedy 也会做一个……真的有很多很棒的培训。然后会议的第二、第三天是所有的演讲,满满的学习机会和互动……但会议的最后一天绝对是最棒的。如果你没有计划留下来参加最后一天,那你就错过了。这是社区日,每年我们都会举办硬件黑客活动;我们称之为“Gobots 和其他飞行物”,而且年年越来越大。实际上,它占用了越来越多的空间。他们给了我们一个双倍大的区域。我们有一个无人机专区,你可以用 Go 驱动的无人机飞行……

去年我们做了 GopherCar,这是基于 Donkey Car 的,这是一个使用树莓派的自驾车项目,Go 驱动,使用摄像头,结合了 Gobot 和 GoCV……我们有很多套件可以进行传感器黑客操作,都是由不同的赞助商提供的。所以你不需要带任何硬件;我们会带来很多很多硬件。我们有大量的赠品、活动、乐趣……所以这绝对非常棒,如果你不去,那你一定会后悔……因为不仅你会学到一些东西,更重要的是你会玩得很开心。

Mat Ryer: Ron,我突然想到一个问题。当我们谈论 TinyGo 在浏览器中运行,或者在这些微控制器上运行时,垃圾回收是如何处理的?因为这也是让这些二进制文件变得又大又胖的原因之一---这是由于运行时的存在。那么,TinyGo 是如何处理垃圾回收的呢?这是我一直想知道的一个技术问题。

Ron Evans: 目前 TinyGo 对垃圾回收的支持相对有限。在一些架构上,比如基于 ARM Cortex 的微控制器,TinyGo 实现了一种非常简单的标记清除(mark-and-sweep)垃圾回收。在 AVR 微控制器上,比如 Arduino,则完全没有实现垃圾回收。这部分是因为 8 位处理器的限制,我记得好像是数据和指令不在同一个内存空间,或者类似的原因。AVR 架构有一些奇怪的地方,可能我记错了,但目前还没有实现垃圾回收。

不过,事实证明你可以在没有垃圾回收的情况下编写有用的代码。一种方法是使用包含所需内存的结构体,另一种是使用全局变量。我们还实现了一些像环形缓冲区这样的东西,这些在进行各种 IO 操作时非常有用。所以,即使没有垃圾回收,你也可以编写有用的代码。不过,TinyGo 的目标之一是支持垃圾回收,并且能够支持多种垃圾回收算法和后端。

我们想做的一件事是能够将 TinyGo 插入系统中,以便能够使用实时操作系统的内存分配器和释放器。这样的话,如果你想从 Go 代码中调用一些 C 代码---顺便提一下,编译和链接使用 LLVM 的一个大优势是,我们不需要像主流 Go 实现中的 cgo 那样的所有东西;对我们来说,它们最终只是函数指针,因此我们能够在 Go 和 C 之间进行更快的调用,因为在 TinyGo 中,最终它们都是二进制代码。

Mat Ryer: 这真是太酷了。

Ron Evans: 目前的 TinyGo 版本,我们花了很多时间简化安装过程,去除了一些额外的依赖项。我们没有完全去掉所有依赖项,如果你想为基于 ARM Cortex 的微控制器编译代码,你仍然需要 Clang 编译器。但下一个 TinyGo 版本将消除这一点,所以你将能够只使用 TinyGo 编译器编译 Go 和 C 代码。

这将把我们带入一个非常激动人心的领域---你需要一些现有的 C 代码来运行这些不同的微控制器上的代码。有些是实时操作系统的 SDK,例如 Zephyr (一个小型的实时操作系统,用于资源受限的嵌入式互联设备,主要是微控制器,支持多种架构)、FreeRTOS 和 Riot OS 等等。

另一个例子是有一些闭源的代码,但它们提供开放的 API,比如 Nordic Semiconductor (挪威的一家芯片公司,成立于1983年) 的蓝牙低能耗(Bluetooth Low Energy)实现,比如 BBC micro:bit。这是一个非常酷的小板子,几年前英国的所有孩子都得到了这些板子,现在还有很多……Mat,你可能从邻家的某个小孩那里顺手拿了一个吧……

Mat Ryer: [笑] 不,我是合法途径得到的。

Ron Evans: 是的,先生,我相信你是合法得到的。 [笑声] BBC micro:bit 内置了 Nordic Semiconductor 的 nRF51 芯片,包含了完整的蓝牙低能耗协议栈,如果你能调用这些闭源代码库。

我们的大目标之一是能够将所有这些代码结合在一起,执行非常小且快速的代码,同时仍然使用 Go 的并发模型……因为我们能够在这些微控制器上运行 goroutine,这本身就非常令人惊讶。比如在我们的 Gopherbot 演示套件中,那个末端发光的 LED 实际上是在它自己的 goroutine 中运行的。

Mat Ryer: 哇哦……真令人惊讶。它竟然支持 goroutine。

Ron Evans: 是的。不过有一些差异和限制。TinyGo 中的 goroutine 实现使用的是 Clang 的协程(coroutines),这是另一种并发执行模块,能够完成我们期望 goroutine 做的大部分工作。我们已经实现了 channels,不过有一些限制,其中最大的一个是我们还没有实现 select 语句。一旦 select 语句实现了,channels 将变得更加有用……不过你现在已经可以使用它们了。此外,还有一个正在开发的分支,里面实现了一些 sync/atomic 的功能,这样你就可以在需要的时候进行 goroutine 之间的同步。

Mat Ryer: 太棒了。如果有听众想要参与进来,或者他们对实现 channels 或 select 功能感兴趣,他们应该如何提供帮助?你们现在在寻找什么样的帮助?

Ron Evans: 我们在寻找各个经验水平的 Tiny gophers,尤其是那些没有太多经验的人。如果你从来没有尝试过这些东西,我们特别需要你,因为你是帮助我们改进入门流程的完美人选,让更多人更容易地开始使用 TinyGo,尝试制作各种有趣的设备和小工具,或者工业系统之类的东西。

另一方面是为 TinyGo 本身做出贡献。我们已经花了不少时间改进了从源码安装 TinyGo 的过程。我们有一些 make 任务,可以让你从源码安装最新的 LLVM,这让想深入研究并为 TinyGo 添加新功能的人更容易上手。

其中最有趣的贡献者之一是 Carolyne Van Slyk,她一直在为 TinyGo 添加测试功能。这样我们就可以用 TinyGo 来执行测试代码。这将非常有用,而了解 Go 测试的内部实现也是非常有趣的。

Mat Ryer: 嗯,我想是的。

Ron Evans: 所以没有比通过构建一些使用相同工具的东西来学习它们工作原理的方式更好的方法了。

Mat Ryer: 是的,太棒了。

Ron Evans: 我还想提到一点---对于那些想真正理解底层机制的人,Ayke 昨天在 Aykevl.nl 上发表了一篇非常棒的博文,名为 LLVM from a Go perspective。它通过一些非常简单的 Go 代码示例,展示了这些代码如何首先转换为 Go 的 SSA 形式,然后转换为 LLVM IR 形式。这是一个非常好的方式来了解---不管你是对帮助 TinyGo 做贡献感兴趣,还是只是想了解现代编译器是如何在底层工作的---这篇博文都非常棒。我一直在反复阅读这篇文章,每次都感到“哦,原来是这样”。

Mat Ryer: 这也会是一个很好的演讲题材。

Ron Evans: 每个人都认为我做了所有的艰苦工作,但我认为其他人才是做了所有的艰苦工作。我相信这被称为“良性循环”。当然,开源的力量就在于我们一起合作,不管是直接通过代码贡献,还是间接地通过反馈“我试了一下,但没成功。这是哪里出了问题……”

几年之前,我在伦敦听过一个非常棒的演讲,演讲者是一位涉及 IoT 相关工作的女性。我不记得她的名字了,但她提出了一个非常棒的观点,关于那些刚刚入门的人在进行电路连接时的困惑。一般来说,红线代表正极,黑线代表负极,对吧?

Mat Ryer: 对。

Ron Evans: 但如果你不知道这一点,你就不会意识到颜色是有意义的;这其实是一个约定俗成的规则。没人会向你解释这一点。这是非常关键的信息,所以当你刚开始时,你甚至不知道什么信息是关键的。所以,如果你遇到困难,试图让某些东西正常工作,你并不孤单,我们需要知道这些问题,这样我们可以帮助其他遇到同样问题的人……因为有时候我们可能知道得太多了。我们已经全部安装好了,可能我们根本不知道安装过程中的问题。

Mat Ryer: 是的,这确实是个好观点。所以无论你有没有经验,或者是否觉得自己准备好做出贡献,都不妨看看,因为你可能会感到惊讶。Ron,你给出的建议真的很棒。TinyGo 和 Gopherbot 这样的项目很棒的一点是,贡献者和维护者都对其他人非常友好和包容;这对社区来说非常重要。

我们之前在节目中也提到过一个问题,就是在面试时,我总是给出的建议之一是,如果你没有其他可以在面试中谈论的内容,那就参与一些开源项目。TinyGo 是一个很好的例子,因为它还涉及到现实世界的应用,这总是一个有趣并令人兴奋的话题。所以,这也是我给那些入门级或者刚开始学习编程的人的建议。

Ron Evans: 这绝对是真的……而且你还需要一个优势。这个优势可能是你让某个硬件上的 LED 亮了起来。对这个领域不熟悉的人会对你的新技能感到印象深刻,甚至你自己也会对自己的新技能感到惊讶。

Mat Ryer: 是的,我会为此感到惊讶。

Ron Evans: 是吧?这会让你有信心去学习其他东西,因为事实证明,大部分物联网、机器人技术和无人机技术只是在正确的时间打开或关闭设备,仅此而已。如果你能做到这一点,你就成功了。

Mat Ryer: 你让这一切听起来如此简单,Ron。

Ron Evans: 在激光射向你之前先把它关闭。这是我的座右铭。

Mat Ryer: 顺便说一句,我知道红线是正极,因为所有的詹姆斯邦德电影里都说得很清楚……所以我们应该没问题吧。

Ron Evans: 还记得那部电影《深渊》吗?他们在海底,只有一个发光棒,无法分辨哪根线是哪种颜色,该剪哪根线?

Mat Ryer: 真是噩梦啊……

Ron Evans: 这就是我的人生故事……我的人生故事。 [笑声] 我该剪哪根线?不知道,那就全剪了吧! [笑声]

Mat Ryer: 是的。我总是想,当他们在拆除炸弹时,总是那种“哦哦哦……”的紧张时刻。我心想,软件基本上从来不管用,所以它大概也不会管用……随便弄弄吧,应该没事。它不会爆炸的。这是我的建议,不过我可不在拆弹工作中。

Ron Evans: 是的,最好在连接激光之前先试试 LED。

Mat Ryer: 是啊,没错。

Ron Evans: 这是我曾经得到的一个好建议。

Mat Ryer: 非常好。

Ron Evans: 确保安全……你懂的,确保安全。 [笑声]

Mat Ryer: 你觉得那根弹簧上的 LED 有可能会变成激光吗?还是它会变成眼睛……?

Ron Evans: 我觉得有人很可能会这么做,但我自己可能不会,因为它会直直地向上射,可能会射到某人的眼睛,我就是那个人。

Mat Ryer: 是的。但这样死去也挺酷的,不是吗?

Ron Evans: 别忘了把激光对准地面。

Mat Ryer: Ron,我敢肯定你最终会被你自己创造的东西搞死,这一点毫无疑问。

Ron Evans: 是啊,这世上有两种人---一种是建造机器人的人,另一种是害怕机器人的人。所以你得决定站在哪一边。

Mat Ryer: 是的。

Ron Evans: 但你更愿意机器人瞬间让你灰飞烟灭,还是希望它在识别你是它的创造者时稍微迟疑几毫秒,然后再让你灰飞烟灭?我更倾向于后者。

Mat Ryer: 是的,所以我们确实需要 Machine Box!

Ron Evans: 没错,没错。你总有一天会需要它的。

Mat Ryer: 是啊。对于那些正在建造未来可能会统治世界的机器人的人,你有什么建议吗?毕竟你也在做这件事,对吧?

Ron Evans: 嗯,你知道的,世界很大,容得下机器人帝国。火星目前是我们太阳系中唯一一个完全由机器人居住的星球,所以它是一个和平美好的地方……

最重要的一点是---嗯,有两部分。第一部分是很多人对这些事情知之甚少……所以不要害怕去尝试和探索。你不需要最新最酷的硬件来做这些。事实上,任何你能够找到的旧 Arduino 都可以。如果你有硬件闲置在抽屉里,把它拿出来给别人用,不要等它变成危险废物,这样他们可以学习……但不要害怕去尝试,因为这也是一种有趣酷炫的学习方式。

另一方面是---不要忘记我们为什么要做这些事情。我们可以构建一个充满杀手机器人的世界,也可以构建一个充满有帮助的机器人的世界。这完全取决于我们。现在,称之为“人工智能”其实不太准确,更像是“智能应用程序”。它们在非常特定的领域内具有一些小范围的智能,但并没有任何通用智能……而且也没有迹象表明我们很快就会获得通用智能。

如果你看过 Roger Penrose (英国数学物理学家、哲学家,诺贝尔物理学奖得奖者) 的书,你会知道我们永远不会实现通用智能。但这并不意味着它没有用处。它仍然非常有用,但我们必须非常小心,因为我们作为人类带入这些计算公式中的偏见可能会对现实世界产生直接影响。我们真的需要在构建这些系统之前、而不是之后思考“我们应该构建它吗?”

同样的技术可以用来做好事,也可以用来做坏事,有时是无意的,有时是被不法分子利用的。所以我们在将这些系统部署到现实世界时,必须非常谨慎,因为它们可能会带来我们意想不到的后果。

此外,物理系统一旦安装,往往会比原计划存在更长的时间。任何在工厂或零售店工作过的人都知道,他们安装了一些东西后,它们往往会超期服役。部分原因是他们不愿意更换,另一部分是他们忘记了它还在那里……所以当我们将设备部署到世界的边缘时,我们真的需要考虑这一点。至少在服务器机房里我们还能挨个机架检查设备“这在做什么?那在做什么?”但在物理世界中的设备,我们甚至可能不知道它们具体安装在哪。我们已经见过很多看似无害的设备被利用来做坏事,比如 Mirai 僵尸网络……

所以我们必须在将分布式设备部署出去之前,应用非常严谨的架构和工业化思维,而不是事后才发现“哦,这些设备无法更新了。那太糟了……”这是不可接受的。关于设备开发的伦理问题,必须在开发前就考虑清楚。

Mat Ryer: 是的,这是真的。这确实是个现实问题。好了,节目到此为止了。非常感谢 Deadprogram,也就是 Ron Evans,向我们介绍 TinyGo,并与我们分享他对 Gopherbot.com 的热情。一定要去看看这个项目。别忘了我们的有奖问答。如果你想赢取 Gopherbot 套件,包括所有你需要的零件,这样你就可以编写 TinyGo 代码并创造你自己的 Go 毛绒玩具机器人,那就查看节目笔记中的有奖问答细节吧。你只需要分享这个播客,并发送邮件到 gotime@changelog.com

好了,我们下周见。非常感谢大家!


好文收藏
38 声望6 粉丝

好文收集