要学 Go 的赶紧上车

2020-10-03 12:59:17 +08:00
 kidlj

Go 预计在 2021 年开始支持范型,那个时候代码对新手的复杂度将提升一个量级。当前 Go 语言只有一种明显的抽象,就是 interface (接口),范型是另一种,而且比接口要更难以理解和编写、阅读。

2017 年我决定转 Go 的时候,调查了社区的成熟度,比如 kafka,redis,mongo,mysql,pg 等等中间件的库是否完善,那时候这些该有的都已经有了。现在又过了三年,Go 的社区更加成熟了,特别是 Docker 和 Kubernets 主导的云原生生态的崛起,Go 语言占了半壁江山还多。

前一阵坐我背后的一个写 Python 的同事在学习 Go,问我一个简单的问题。一个函数的返回值是 error 类型,被他当作是返回变量,因此代码看不懂。这可能是只写过动态类型语言( python, javascript, php 等)都要面对的一个思维转变。这个时候学习 Go,除了静态类型的思维转变以及 interface 这一层抽象,你会发现 Go 大部分时候像一个动态类型的语言,而且特性非常少(比 Python 少得多),Go 开源代码和标准库也非常 accessible 。

不过当范型推出来以后,虽然从 draft design 来看范型的设计已经非常简单,但对于没接触过静态类型语言的同学来说这是一个不小的挑战,甚至函数的签名都难以分辨。因此这是一个肉眼可见的复杂度提升。而且可以预计的是,当范型可用的时候,社区里大量的开源项目和库将迁移到范型的实现(因为代码更紧凑和通用),我觉得那个时候代码不会像当前一样 accessible 。

所以这个时候上车,用大约半年到一年时间熟悉 Go 的静态类型和 interface,等到范型推出的时候,可以比较轻松地过渡过去。

下面是一些学习资料的推荐:

  1. <The Go Programming Language> 是 Brian Kernighan 和一位 Go 开发组成员 Alan 合写的一本书。虽然这本书出来好几年了,但是 Go 从 1.0 以后就没怎么变化,所以还是很适用。推荐阅读英文版,中文版在大部分时候翻译得不错,但是在一些难以理解的部分,翻译并不能让事情更容易理解,甚至还会出现错误。
  2. Web 框架推荐 Echo 。写过 Node.js 的同学会发现,Echo(或 gin ) 就是 Express 或 Koa 的翻版,都是 middleware 和 c.Next 的执行方式,属于极简框架,很容易上手。
  3. Go 的并发很简单,只有 Goroutine 和 channel 一种方式。官方出的那本书里讲解得非常清晰,必读。不过一开始如果理解起来有困难的话,甚至可以跳过,因为很多时候不太用得着。比如用 Echo 框架来写业务,大部分时候不涉及并发,并发是在 Echo 框架的层面实现的(一个请求一个 goroutine ),所以业务代码就不需要并发了。
  4. Go modules 很好用。新推出不久的 pkg.go.dev 可以查询某个库被哪些开源项目 import,可以方便地学习这个库的使用方式。比如想看哪些开源项目使用了 Echo 框架,点开 Echo 的 import by tab 就看到了。这里是示例: https://pkg.go.dev/github.com/labstack/echo/v4?tab=importedby

我写 Go 有两年时间,肯定不算是一个 Go 的高手,但也不害怕去阅读一些大型项目的代码,比如 Kubernetes 。这就是 Go 的魔力,very accessible 。就像上面说的,当范型被大量运用以后,难度应该要提高一个量级。这是我的一点点经验,分享给大家,希望有帮助。

24246 次点击
所在节点    Go 编程语言
180 条回复
Jirajine
2020-10-03 14:14:37 +08:00
err!=nil 绝对是 go 最大的糟粕之一,一个 union type 就能解决的问题非要搞个 tuple 出来。
Jirajine
2020-10-03 14:16:15 +08:00
reus
2020-10-03 14:29:59 +08:00
@Jirajine 2020 年了,王垠这种垃圾文章就别拿出来丢人现眼了。这种文章放到发表的那一年,也是错漏百出,稍有水平的人都看得出错误有多少。
reus
2020-10-03 14:33:17 +08:00
@chenqh 你既然知道知乎用 panic / recover,那你还说什么?你没有能力让你们公司代码改用 panic / recover 来处理错误,那是你能力低下,不想用就别用,赶紧换公司换语言,别说得好像别人强迫你用似的。一边忍受一边用,你是受虐狂吗?
jingniao
2020-10-03 14:36:57 +08:00
用 go 1 年半了,err 处理挺让我安心的。
之前写 python 总会担心程序跑起来之后各种奇奇怪怪的少概率点抛出异常,用第三方库抛异常,代码上线之后修 bug 是各种加 try 包代码,当然也跟个人能力有关,无法考虑所有可能异常点。
go 把 err 处理,强制性让人考虑错误处理,程序稳健性提高不少,剩下的还经常遇到的异常就是接口指针的 nil 判断没做或者没正确初始化。没正确初始化的随着 go 熟练也在减少,剩下的就是返回 err 跟指针,可能 err 忽略拿着指针直接用了。
当然楼上有人提到 union type,应该说的是 rust 的那种吧,只了解语法没大量用熟悉它就不评价了。
shutongxinq
2020-10-03 14:39:15 +08:00
又一个 gcp 的人天天劝你学 go
24bit
2020-10-03 14:44:18 +08:00
好多时候出现 err 我都只是想抛到上层,但是却不得不判断一次……感觉要是加一个 rust 里面通过 ? 传递 err 的特性就好了
cigarzh
2020-10-03 14:44:34 +08:00
你跟一帮 Java 小子说 Golang 加了泛型会变难?

那爱衣无
chenqh
2020-10-03 14:47:10 +08:00
@jingniao 这种为什么稳健行提高?难道 golang 的 err 不也是一般往上抛吗?
cmdOptionKana
2020-10-03 14:50:41 +08:00
@24bit 这点真心希望官方提供一个语法糖,以前就有人提过增加 check 关键词,比如

check err

有错往上抛,无错就忽略,这语法糖就很甜。
Jirajine
2020-10-03 15:00:36 +08:00
@reus 那倒是说说错漏在哪里,就我看来除了类型后置无分隔符我觉得无所谓其他还是很赞同的。
其他可能还有争议,err!=nil 我觉得没什么好说的,能把 rust 的 enum 和 Result 抄过来也好不少。
Jirajine
2020-10-03 15:06:25 +08:00
@reus 举个常见的场景,我想把一个(可能出错)的函数返回值作为参数传给另一个函数,如果出错就把错误传递上去:
go 你得这样:
val,err:=f1()
if err!=nil{
return nil,err
}
f2(val)

而 rust 直接:
f2(f1()?);
就可以了。

以及王垠提到的,没有任何机制能保证 err 和 val 一定一个是 nil 一个不是,全靠程序员约定俗成。明明 union type 能够完美表示,却非要用 tuple 。
yoke123
2020-10-03 15:08:49 +08:00
早点学会 go 早点上车,现在市场上还是很缺 go 开发的,我感觉是个机会,趁现在人还不多的时候学,省得到时候培训机构铺天盖地的培训出来一批人和你内卷。
EminemW
2020-10-03 15:09:34 +08:00
我有写 go 跟 Java..感觉我写的 go 代码非常丑,可能我功力不够
BoarBoar
2020-10-03 15:23:03 +08:00
目前我用 interface 写的函数,只能大量使用反射和 switch 去处理,范型应该是众望所归,对写过 C/C++和 java 的人也不会有任何难度。
主要写 go 两年了,看到一大堆 if err!=nil 还是很不爽,特别是闲的时候费尽心思写出一段优雅的代码,一大堆 err 瞬间把你打回代码搬砖工的原型。
个人还有一点期望,增加一个空指针的语法糖,未手动判断 nil 的情况下不要 panic 。在接近脚本语言的语法情景下,我常常会忘掉判断 nil,以前写 C++那会估计也没写 go 的空指针多
falcon05
2020-10-03 15:27:31 +08:00
据我观察,本站大部分讨论 go 语言特征的最终会变成 if err !=nil 之争。
pisc
2020-10-03 15:30:11 +08:00
难道你们练习时长两年半的 go 程序员看到一个“泛型”就已经大脑缺氧、理解困难了吗?难道中学数学没学过全称量词?
laike9m
2020-10-03 15:32:12 +08:00
@kidlj 如果你知道 Google 里大家是怎么写 C++就不会对这个设计感到奇怪,毕竟一开始他们还是想用 go 代替 C++ 的。但问题是 C++可以用宏把 err 的检查和赋值( assign_or_return )写在一行,go 就没办法
dahhd
2020-10-03 15:39:44 +08:00
@reus 文章垃圾不垃圾不是很懂,你这样张口就说别人垃圾,真的是可以。
说句不好听的,我觉得你比不上王垠,在座的各位也没几个能比得上,所以别总是乱喷了。
SignLeung
2020-10-03 15:45:02 +08:00
有一说一,转 go 之后,用 if err != nil 后 写的代码确实很少出错,很稳定

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/712344

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX