长一段时间以来,Javascript 是在 Web 开发者中的通用语言。如果你想写出一个稳定、成熟的 Web 应用程序,那么使用 Javascript 几乎是唯一的方法。
WebAssembly(也叫 wasm )即将改变这种情况。使用 WebAssembly,现在可以用任何语言来编写 Web 应用程序。在这篇文章当中,我们将明白怎样编写 Go 程序并使用 wasm 在浏览器中运行它们。
首先,什么是 WebAssembly
WebAssembly 官方网站 webassembly.org 对它的定义是“一个基于堆栈的二进制指令格式的虚拟机”。这是一个很好的定义,但是让我们来将它分解为我们能够简单理解的内容。
从本质上讲,wasm 是一种二进制格式,就像 ELF、Mach 和 PE 一样。唯一的区别是它适用于虚拟编译目标,而不是真正的物理机。为什么是虚拟机?因为与 C/C++ 的二进制不一样,wasm 二进制不针对于特定平台。因此,你可以不用改变任何东西而在 Linux、Windows 和 Mac 上使用同一份二进制文件。但是,我们需要额外的“代理”,它将 wasm 指令中的二进制文件转换为特定平台的指令并运行它们。通常,这个“代理”就是一个 Web 浏览器,但是理论上讲,它可以是任何其它东西。
这为我们提供了一个通用的编译目标,我们可以使用自己选择的任何编程语言来构建 Web 应用程序。只要我们将程序编译为 wasm 格式,我们就不用担心目标平台。就像我们编写一个 Web 应用程序,但现在我们可以使用我们选择的任何语言编写它。
Hello WASM
让我们尝试从编写一个简单的“ hello world ”程序开始。确保你的 Go 版本至少为 1.11。我们可以这样写:
保存为一个 test.go 文件。这看上去就是一个常规的 Go 程序。现在让我们来编译这个文件到 wasm 平台。我们需要像下面这样设置 GOOS 和 GOARCH 来编译它。
$GOOS=js GOARCH=wasm Go build -o test.wasm test.go
我们现在就生成了 wasm 二进制文件。但是与本机系统不同,我们需要在浏览器中运行它。为此,我们需要投入一些额外的东西来实现这一个目标:
我喜欢把它想象成制作飞天小女警所需要的东西。
然后 BOOM,我们就有了一个 WebAssembly 应用程序!
我们已经在 Go 发行版本中提供了 HTML 和 JS 文件,在此我们将它们复制下来。
serve 是一个简单的 Go 二进制文件,它为当前目录中的所有文件提供服务。但是几乎所有的 Web 服务器都会这样做。
一旦我们运行它,并打开我们的浏览器。我们看到一个 Run 按钮,点击它,将执行我们的应用程序。然后我们点击它并检查控制台:
优美!我们刚刚使用 Go 编写了一个程序并在浏览器中运行了它。
到现在为止还挺好。但这是一个简单的“ hello world ”程序。一个现实世界中的 Web 应用程序需要与 DOM 进行交互。我们需要对按钮点击事件进行响应,从文本框中获取数据,并将数据发送回 DOM。现在我们将构建一个最小的图片编辑器,这个示例将用到所有的这些功能。
DOM API
首先,为了让 Go 代码与浏览器进行交互,我们需要一个 DOM API。我们需要 syscall/js 库来帮助我们解决这个问题。它是一个非常基础但却强大的 DOM API,我们在其上构建我们的应用程序。在我们转向制作我们的应用程序之前,让我们快速了解它的一些功能。
回调
为了响应 DOM 事件,我们声明了回调并用这样的事件将它们连接起来:
更新 DOM
要从 Go 内部更新 DOM,我们可以这样做 -
你甚至可以调用 JS 函数和操作本地原生 JS 对象,就像 FileReader 或 Canvas 一样。请随时查看 syscall/js 文档以获取更多详细的信息。
好了,现在开始构建我们的应用程序!
一个像样的 Web 应用
我们将构建一个小的应用程序,它将获取一个图片输入,然后对图片进行一个操作,如亮度、对比度、色调、饱和度,最后将图片输出回浏览器中。每一个效果都将会用滑块,用户可以更改这些效果并实时查看目标图像的变化。
首先,我们需要从浏览器获取输入图片到我们的 Go 代码中,以便我们可以处理它。为了有效的做到这一点,我们需要采取一些 unsafe技巧,具体细节跳过。一旦我们获取到了图片,它就完全在我们的掌控之下了,我们就可以随心所欲的做任何事情。下面是图片加载器回调的简短片段,为简洁起见略有优化:
然后我们从任何效果滑块中获取用户的值,并操纵图片。我们使用很棒的 bild 库。这是操作对比度回调的一小部分片段:
在此之后,我们将图片编码为 jpeg 格式并将其发送回浏览器。这是完整的应用程序操作:
我们加载图片:
改变对比度:
改变色调:
太棒了,我们可以在浏览器中本地操作图片而不需要编写一行 Javascript 代码!可以在 这里 找到源码。https://github.com/agnivade/shimmer
请注意,所有这些都是在浏览器本身中完成的。这里没有 Flash 插件、JavaApplets 或 Silverlight。开箱即用的浏览器本身对 WebAssembly 提供了支持。
最后说两句
我的一些结束语:
希望这篇文章展示了 WebAssembly 一些很酷的方面,以及如何使用 Go 编写一个功能齐全的 Web 应用程序。如果你发现一个 bug,请尝试解决一下,并提出 issue。如果您需要任何帮助,请随时访问 #webassembly 频道。
via: https://blog.gopheracademy.com/advent-2018/go-in-the-browser/
作者:Agniva De Sarker 译者:PotoYang 校对:polaris1119
本文由 GCTT 原创编译,Go语言中文网 荣誉推出
「入群交流:Go中文网 QQ群:731990104 微信群:274768166 备注:头条 微信公众号:Go语言中文网」
o语言中文网,致力于每日分享编码、开源等知识,欢迎关注我,会有意想不到的收获!
以常规方式编写并发程序,需要对共享变量作正确的访问控制,处理起来很困难。而golang提出一种不同的方式,即共享变量通过channel传递,共享变量从不被各个独立运行的线程(goroutine)同时享有,在任一时刻,共享变量仅可被一个goroutine访问。所以,不会产生数据竞争。并发编程,golang鼓励以此种方式进行思考,精简为一句口号——“勿通过共享内存来进行通信,而应通过通信来进行内存共享”。
Unbuffered channels的接收者阻塞直至收到消息,发送者阻塞直至接收者接收到消息,该机制可用于两个goroutine的状态同步。Buffered channels在缓冲区未满时,发送者仅在值拷贝到缓冲区之前是阻塞的,而在缓冲区已满时,发送者会阻塞,直至接收者取走了消息,缓冲区有了空余。
如下代码使用Unbuffered channel作同步控制。给定一个整型数组,在主routine启动另一个goroutine将该数组排序,当其完成时,给done channel发送完成消息,主routine会一直等待直至排序完成,打印结果。
如下代码中,messages chan的缓冲区大小为2,因其为Buffered channel,所以消息发送与接收无须分开到两个并发的goroutine中。
函数封装时,对仅作消息接收或仅作消息发送的chan标识direction可以借用编译器检查增强类型使用安全。如下代码中,ping函数中pings chan仅用来接收消息,所以参数列表中将其标识为接收者。pong函数中,pings chan仅用来发送消息,pongs chan仅用来接收消息,所以参数列表中二者分别标识为发送者与接收者。
使用select可以用来等待多个channel的消息,如下代码,创建两个chan,启动两个goroutine耗费不等时间计算结果,主routine监听消息,使用两次select,第一次接收到了ch2的消息,第二次接收到了ch1的消息,用时2.000521146s。
select with default可以用来处理非阻塞式消息发送、接收及多路选择。如下代码中,第一个select为非阻塞式消息接收,若收到消息,则落入<-messages case,否则落入default。第二个select为非阻塞式消息发送,与非阻塞式消息接收类似,因messages chan为Unbuffered channel且无异步消息接收者,因此落入default case。第三个select为多路非阻塞式消息接收。
当无需再给channel发送消息时,可将其close。如下代码中,创建一个Buffered channel,首先启动一个异步goroutine循环消费消息,然后主routine完成消息发送后关闭chan,消费goroutine检测到chan关闭后,退出循环。
2.5 for range
for range语法不仅可对基础数据结构(slice、map等)作迭代,还可对channel作消息接收迭代。如下代码中,给messages chan发送两条消息后将其关闭,然后迭代messages chan打印消息。
资源访问、网络请求等场景作超时控制是非常必要的,可以使用channel结合select来实现。如下代码,对常规sum函数增加超时限制,sumWithTimeout函数中,select的v :=<-rlt在等待计算结果,若在时限范围内计算完成,则正常返回计算结果,若超过时限则落入<-time.After(timeout) case,抛出timeout error。
本文代码托管地址:https://github.com/olzhy/go-excercises/tree/master/channels
参考资料
[1] https://golang.org/doc/effective_go.html#channels
[2] https://gobyexample.com/channel-synchronization
[3] https://gobyexample.com/channel-buffering
[4] https://gobyexample.com/channel-directions
[5] https://gobyexample.com/select
[6] https://gobyexample.com/non-blocking-channel-operations
[7] https://gobyexample.com/closing-channels
[8] https://gobyexample.com/range-over-channels
[9] https://gobyexample.com/timeouts
原文:https://leileiluoluo.com/posts/golang-channels.html
本文作者:磊磊落落的博客,原创授权发布
018 年接近尾声,InfoQ 策划了“解读 2018”年终技术盘点系列文章,希望能够给读者清晰地梳理出重要技术领域在这一年来的发展和变化。本篇文章是 Go 语言 2018 年终盘点,分为上下两篇。客观、深入分析 2018 年 Go 语言的技术发展现状,同时对明年可能的发展情况进行预测和展望。
今年真可谓是不平静的一年,前有人工智能国家级战略的发布,行业已经在大跨步的挺进,但人才缺口每天都在扩大;后有区块链技术从爆发式增长到大幅回落,无数程序员蜂拥而至,又在现如今变得手足无措。
那么,Go 语言在 2018 年这一年发展得又如何呢?它的下一步又将会怎样?且听笔者细细道来。(如果大家还希望了解更多详情,还可以看下笔者在极客时间的Go 语言专栏)
首先,笔者要说的是,在 TIOBE 于 2018 年 11 月份公布的编程语言排行榜中,Go 语言已然挤到了前 10 的位置。虽然这与去年同期的第 14 位看起来相差不大,但却是一个里程碑式的进步。
图 1:TIOBE Index for Nov 2018
从 Google Trends 提供的流行趋势统计来看,在过去的 12 个月里,Go 语言的流行也是持续升温的。
图 2: Google Trends - Golang 热度随时间变化的趋势
这种升温虽然并不算快,但是很持久。这对编程语言的生态环境和人才的发展是非常有利的。
此外,完全不出乎我们的意料:中国依然是 Go 语言爱好者最多的国家,没有之一。
图 3: Google Trends - Golang 按区域显示的搜索热度
具有讽刺意味的是,作为 Go 语言诞生地的美国,仅排在了第 15 位。我们对先进技术和前沿科技的热衷绝对是不输他国的。下面,让我们再把尺度缩小到城市级别。
图 4 :Google Trends - Golang 按区域显示的搜索热度(城市)
显然,在我国,北京、深圳、上海这三个城市聚集了非常多的 Go 语言程序员和工程师。尤其是北京,简直是 Go 语言爱好者的圣地啊!
至于北京博得头筹的原因,据笔者观察,首先肯定是:在北京的互联网公司很多,起码明显多于其他的一、二线城市。Go 语言如今在互联网公司中非常流行,即使有的公司高层并没有批准大规模地使用 Go 语言,但是工程师们都在做积极的尝试。
其次,北京做云计算的公司很多,不论是面向市场的公有云还是自建自用的私有云。说到云计算,我们就不得不提及开放平台技术、容器技术、集群管理技术,以及现在很火热的微服务(Microservices)和 Serverless 技术,等等。而这些,恰恰都是 Go 语言的专长。在这些方面,有很多成熟的基于 Go 语言的解决方案可供选择。
再次,北京的高科技创业公司非常多。他们往往没有历史包袱、勇于创造和尝试。在做技术选型的时候,他们也更容易选择 Go 语言。因为,Go 语言既拥有编译型编程语言固有的高运行效率,又具有解释型编程语言常有的高开发效率。而且,Go 语言还不像有些编程语言那样时不时地出现内斗、分裂等混乱情况,当然也没有无良的技术持有者吵闹着要对编程语言的商用进行收费。
Go 语言在语言规范的发展、版本的迭代和开发者生态的建设方面都非常的稳定,并有着良好的包容性和兼容性。保持简单、面向契约和利于协作是 Go 语言最突出的设计哲学。无论是做软件原型,还是用于小团队作战,又或是进行大规模的研发,Go 语言都会是很不错的选择。
最后,很多喜爱 Go 语言、致力于推广 Go 语言技术的个人开发者、技术团队、互联网公司以及知识服务厂商也都在北京。这都直接或间接地导致了 Go 语言在这座城市的流行。
好了,到这里,笔者相信你已经对 Go 语言在中国的流行有了一定的了解。下面,我们再来说说 Go 语言在 2018 年具体都有哪些进展。
首先说一下,关于 Go 语言在 2018 年之前的具体进展,笔者推荐你去看这几篇同系列文章,如下:
Go 语言官方团队在 2018 年 2 月正式发布它的 1.10 版本。不同于其他很多被称为版本帝的编程语言,到了这样一个版本号 10,Go 1 在语言规范方面已经几乎没有什么改动了,一些语法上的小小增强也并不值得我们特别关注。而在 2018 年 8 月发布的 Go 1.11 更是没有任何语言规范方面的变动。
Go 语言对于本身的向后兼容性保持得非常好,高版本对低版本中的语言语法、工具和标准库都不会有任何破坏。然而,Go 语言在其支持的操作系统方面还是很大刀阔斧的。这体现在,Go 1.10 不再支持 10.3 以下版本的 FreeBSD 和 8.0 以下版本的 NetBSD。并且,这个版本也是支持 OpenBSD 6.0、OS X 10.9 以及 Windows XP 和 Windows Vista 的最后一个版本。** 在这些操作系统之上编写或运行 Go 语言程序的开发者们要注意。
使用过 Go 语言的开发者们都知道,当把 Go 语言的预编译包解压到某个目录后,我们还需要至少设置两个环境变量——GOROOT 和 GOPATH。前者代表直接包含 Go 语言本身的那个目录路径,而后者则用于指定可放置第三方库和自有代码的工作区(或者说工作目录)的路径。
一个好消息是,自 Go 语言的 1.10 版本起,GOROOT 这个环境变量就没有必要设置了。如果我们不设置它,那么 Go 的标准工具会尝试以自身所在的目录为基础,自动地推断出 GOROOT 应该指向的目录路径。
另外,从这个版本开始,我们可以自行地设定 Go 语言的临时目录路径了,设定的途径是设置环境变量 GOTMPDIR。Go 语言的临时目录主要用于存放 Go 工具在编译或测试程序时产生的各种临时文件。在这之前,这些临时文件都会被存放到固定的地方,此地的具体路径会根据操作系统的不同而不同,一般会位于操作系统的临时目录的某个子目录下。自定义这个目录的好处在于,可以让我们方便地观察编译过程,并查看编译或测试的中间结果。
说到编译,笔者一定要提一下 1.10 版本的另一项改进,这与 go build 命令有关。以前,如果我们要强行地重新构建所有相关的代码包,那么就需要在运行这个命令的时候追加标记“-a”。而现在,我们无需这样做了。go build 命令会根据源码文件内容、构建标记和编译元数据,自动地决定什么时候应该重新构建那些代码包。这项工作再也不需要人工干预了。
与此项改进相关的变化是,go build 命令现在总是会把最近的构建结果缓存起来,以便在将来的构建中重用。我们可以通过运行 go env GOCACHE 命令来查看缓存目录的路径。缓存的数据总是能够正确地反映出当时的源码文件、构建环境和编译器选项等的真实情况。一旦有任何变动,缓存数据就会失效,go build 命令就会再次真正地执行构建。因此,我们并不用担心缓存数据体现的不是实时的结果。实际上,这正是上述改进能够有效的主要原因。go build 命令会定期地删除最近未使用的缓存数据,但如果你想手动删除所有的缓存数据,运行一下 go clean -cache 命令就好了。
顺便说一下,对于测试成功的结果,go 命令也是会缓存的。运行 go clean -testcache 命令将会删除掉所有的测试结果缓存。不过别担心,这样做肯定不会删除任何的构建结果缓存,它们是两码事。
此外,设置环境变量 GODEBUG 的值也可以稍稍地改变 go 命令的缓存行为。比如,设置值为 gocacheverify=1 将会导致 go 命令绕过任何的缓存数据,而真正地执行操作并重新生成所有结果,然后再去检查新的结果与现有的缓存数据是否一致。
再来说 go install 命令。现在,go install 命令在默认情况下只会去安装我们明确指定的那些代码包。这些代码包依赖的那些包并不会被安装。这同样得益于构建结果缓存,它可以使安装的速度得到明显的提升。如果你想要强制地安装依赖包,那么请在运行命令的时候追加“-i”标记。
前面我们说过了,测试成功的结果也会被缓存。如果 go test 命令确定可以使用被缓存的结果,那么它打印出的内容也会出自于缓存。这时,被打印的内容中会包含“(cached)”字样。
另外,go test 命令现在会自动地运行 go vet 命令,以便在真正运行测试之前识别出一些程序编写方面的问题。我们都知道,go vet 命令用于对 Go 语言源码进行静态检查,并报告已发现的可疑问题。这些问题一般都是符合语法规则的,因此编译器无法查出它们。但是,它们很有可能代表了对某些程序实体(或者说 API)的错误使用。虽然 go vet 命令有时候并不能保证它报告的每一个问题都是真正的问题,但它却可以给予我们一份重要的参考,以便让我们在编程的过程中小心行事。
与 Go 语言提供的很多高级功能一样,我们也可以阻止 go test 命令自动运行 go vet 命令,这需要在运行前者的时候追加“-vet=off”这个标记。
最后,关于 go test 命令,还有两个值得注意的新标记——“-failfast”和“-json”。顾名思义,“-failfast”标记可以让 go test 命令一旦发现有测试失败的情况就立即忽略掉剩余的测试并终止运行。不过要注意,如果存在与失败的测试并发进行的测试的话,那么后者还是会继续运行直至完成的。“-json”标记对于程序测试的自动化大有裨益。它会让 go test 命令产生 JSON 格式的测试报告,这使得其他程序很容易读入和处理。
关于程序文档,只有一点需要我们注意。**Go 1.11 是 godoc 命令支持命令行接口的最后一个版本。** 在未来的版本中,我们运行 godoc 命令的时候,它会启动一个 Web 服务器,以便让我们直接进入图形化界面进行文档查询。
现在,runtime/pprof 代码包中的 Lookup 函数已经支持了更加多样的参数值。这就意味着,Go 语言的程序性能分析现在可以生成和解读更多视角下的分析报告了。我们可以把这样的分析报告包含的内容叫做程序性能概要信息(简称概要信息),并把存储这些分析报告的文件叫做概要文件。
Lookup 函数可以生成的概要信息目前共有 6 种。这 6 种概要信息分别由字符串类型的参数值goroutine、heap、allocs、threadcreate、block和mutex代表。下面是它们代表的含义:
这里所说的同步原语,指的是存在于 Go 语言运行时系统内部的一种底层同步工具,或者说一种同步机制。它是直接面向内存地址的,并以异步信号量和原子操作作为实现手段。我们已经熟知的通道、互斥锁、条件变量、“WaitGroup”以及 Go 语言运行时系统本身,都会利用它来实现自己的功能。
另外,在用空间和已分配空间的区别是,前者指的是已经分配但还没有被回收的空间,而后者只关注分配出的空间,不论它们是否已经被回收。
注意,如果我们在运行 go test 命令的时候追加了标记“-memprofile”,那么该命令会通过底层的 API 以allocs为视角生成概要信息和概要文件。这相当于对从测试开始时的所有已分配字节进行记录,包含已经被垃圾回收器收回的那些字节。在 Go 1.11 版本之前,go test 命令在这种情况下采用的是heap视角。
最后,go tool pprof 工具已经可以正确地单独读取和处理所有种类的概要文件了。这得益于,从 Go 1.10 版本开始,block和mutex视角下的概要信息已经完善。在这之前,我们使用 go tool pprof 查阅这两种概要文件的时候,还不得不同时指定相应程序的二进制文件。
需要特别注意,runtime 代码包中的 LockOSThread 函数和 UnlockOSThread 函数的行为已经发生了变化。我们都知道,前一个函数的功能是将当前的 goroutine 与那一时刻正在承载这个 goroutine 运行的操作系统线程进行绑定。在绑定之后,这个 goroutine 就只能由该操作系统线程运行了,反之,该操作系统线程也只能运行这一个 goroutine 了。显而易见,runtime. UnlockOSThread 函数的功能是解除上述绑定关系。当然了,这两个函数都只能作用于它们被调用时所在的那个 goroutine。
以前,runtime. LockOSThread 函数是幂等的。也就是说,无论我们在同一个 goroutine 中调用了它多少次,都只相当于调用了一次。另一方面,只要我们调用一次 runtime. UnlockOSThread 函数,就总是能够解除针对于当前 goroutine 的这种绑定。
但是,从 Go 语言的 1.10 版本开始,在我们想要完全解除绑定的时候,可能就需要调用多次 runtime. UnlockOSThread 函数才能够实现了。至于具体需要调用多少次完全取决于,当初在同一个 goroutine 中调用 runtime. LockOSThread 函数的次数。换句话说,只有进行相同次数的函数调用,才能让当前 goroutine 与某个操作系统线程之间的绑定关系完全解除。我们可以把现在的这种对应关系理解为是基于嵌套的,可以想象一下:当初包装了多少层纸箱,现在就要拆开多少层纸箱。
其实一直以来,有很多第三方 Go 语言库的作者都误以为对于这两个函数的调用就是基于嵌套关系的。不过无论怎样,我们现在都应该仔细检查代码并小心的应对了。
笔者认为,如果你确实需要进行这种绑定,那么就应该基于这两个函数封装一个数据结构。在这个数据结构中,至少应该包含一个用于记录调用 runtime. LockOSThread 函数次数的字段,以方便后续的解绑操作。
在 2018 年,对于 Go 语言的运行时系统来说,我们可以轻易感知到的变化基本上只有这一个。不过,非常多的改进和优化都在悄无声息的进行着,有的已经完成了,而有的还在进展之中。已完成的改进如:在通常情况下,我们传递给 runtime.GOMAXPROCS 函数的参数值已经不再受限了,只要它在 int32 类型可容纳的范围之内就可以。
在 Go 语言的 1.10 和 1.11 这两个版本中,官方团队与社区开发者们一起对标准库做了大量的改进。可喜可贺,社区开发者对 Go 语言的贡献次数现在已经超过官方团队了!
由于这方面的改进繁多,也由于笔者在新近发布的极客时间专栏《Go 语言核心 36 讲》中已经详细讲解了不少,所以这里就不再赘述了。
我们再来说说 Go 1.11 的两个新实验吧,一个是对 WebAssembly 的实验性支持,另一个是推出由 dep 和 vgo 演化而来的依赖管理机制和新概念 module。
按照官方的描述,WebAssembly(缩写为 WASM)是一种二进制指令格式,它针对的是以堆栈为基础的虚拟机。WASM 有很好的可移植性,以便让 C++、Golang、Rust 等高级编程语言来操控它,并有能力部署到 Web 程序上。
用普通话来说,WASM 提供了一种途径,可以让我们用后端编程语言直接去编写 Web 页面中的逻辑。在 Go 1.11 中,我们可以很轻易地把 Go 语言源码文件转换为 WASM 格式的文件,然后在 Web 页面中通过寥寥几行 JavaScript 代码引用这个文件并把其中的逻辑发布到页面上。WASM 的 1.0 版本现在已经支持了绝大多数的主流网络浏览器,比如:Chrome、Firefox、Safari 等。如果想了解具体的玩法,你可以参看这个 wiki 页面。
笔者对 Go 语言官方的这种探索性实验一直都持赞成的态度,不论是前些年的移动端(Android 和 iOS)方向,还是今年的 Web 端(WASM)方向。不过,笔者依然觉得 Go 语言的优势在服务端,现在很明显,而且在可预见的未来也应该是如此。所以,对于这些多端探索,笔者建议大家“保持关注,积极试验,但不要偏移重心”。
相比之下,笔者倒是更加看好 Go 语言新放出的依赖管理机制。Go 语言爱好者们都知道,Go 语言在这方面一直是缺失的。虽然目前存在几个不错的第三方解决方案,但是没有一个是可以脱颖而出的,同时官方也一直没有给出一个统一的标准。
经过了一段时间的试验和演化,Go 语言官方的依赖管理机制终于脱胎于 dep 和 vgo。虽然其间存在一些摩擦和风波,但是结果终归是积极的。
在 Go 语言新的依赖管理机制中,module 是一个非常重要的概念。简单来说,module 象征着由某个 Go 语言代码包以及它依赖的代码包共同组成的一个独立单元。这里的 Go 语言代码包和它依赖的那些代码包都是版本化的。一个 module 的根目录下总是直接存有一个名为 go.mod 的文件。这个文件中会包含当前 module 的路径,以及它依赖的那些 module 的路径和版本号。如此一来,对于每一个版本的 module,它依赖的所有代码都会被固化下来。这对于后续的版本管理和 module 重建来说都是重要的基础。详情可以参看这里的 wiki 页面。
不过,不要忘了,Go 1.11 中包含的这个依赖管理机制是实验性的。其中的任何部分都有可能由于社区的反馈和官方的改进而变化。所以,你在正式使用它之前一定要考虑到后续可能存在的变更成本。虽然如此,笔者仍然会鼓励广大开发者们去积极使用和反馈。想象一下 maven 对于 Java 世界的重要性吧。笔者相信,我们心目中的 Go 项目依赖管理机制已经离此不远了。
[1] Go 1.10 is released: https://blog.golang.org/go1.10
[2] Go 1.11 is released: https://blog.golang.org/go1.11
[3] Diagnostics: https://golang.google.cn/doc/diagnostics.html
[4] WebAssembly: https://github.com/golang/go/wiki/WebAssembly
[5] Modules: https://github.com/golang/go/wiki/Modules
[6] Go 1.12 Release Notes(DRAFT): https://tip.golang.org/doc/go1.12
[7] Nine years of Go: https://blog.golang.org/9years
[8] Toward Go 2: https://blog.golang.org/toward-go2
[9] Go 2 Draft Designs: https://go.googlesource.com/proposal/+/master/design/go2draft.md
作者简介郝林,国内知名的 Go 语言技术布道者,GoHackers 技术社群的发起人和组织者。他也是极客时间专栏《Go 语言核心 36 讲》的作者,以及图灵原创图书《Go 并发编程实战》的作者。他曾在轻松筹任大数据负责人,同时负责大数据部门和主站的后端技术团队。
*请认真填写需求信息,我们会在24小时内与您取得联系。