Golang Go语言学习要趁早赶紧上车
Golang Go语言学习要趁早赶紧上车
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,等到范型推出的时候,可以比较轻松地过渡过去。
下面是一些学习资料的推荐:
- <The Go Programming Language> 是 Brian Kernighan 和一位 Go 开发组成员 Alan 合写的一本书。虽然这本书出来好几年了,但是 Go 从 1.0 以后就没怎么变化,所以还是很适用。推荐阅读英文版,中文版在大部分时候翻译得不错,但是在一些难以理解的部分,翻译并不能让事情更容易理解,甚至还会出现错误。
- Web 框架推荐 Echo 。写过 Node.js 的同学会发现,Echo(或 gin ) 就是 Express 或 Koa 的翻版,都是 middleware 和 c.Next 的执行方式,属于极简框架,很容易上手。
- Go 的并发很简单,只有 Goroutine 和 channel 一种方式。官方出的那本书里讲解得非常清晰,必读。不过一开始如果理解起来有困难的话,甚至可以跳过,因为很多时候不太用得着。比如用 Echo 框架来写业务,大部分时候不涉及并发,并发是在 Echo 框架的层面实现的(一个请求一个 goroutine ),所以业务代码就不需要并发了。
- 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 。就像上面说的,当范型被大量运用以后,难度应该要提高一个量级。这是我的一点点经验,分享给大家,希望有帮助。
更多关于Golang Go语言学习要趁早赶紧上车的实战教程也可以访问 https://www.itying.com/category-94-b0.html
感觉 err 和病毒一样,弄的我几乎每个 function 都要带 err
我觉得这样挺好 明确每一个函数的返回是否报错 虽然很麻烦
等等党永远不亏。
不用泛型就可以了。。。所以难度没变。。。
我从不推荐使用各种框架。。。
我推荐尽可能使用原生库去完成项目,尽量少使用第三方库。。。
所以也不推荐写 web 用 echo 框架之类。。。
减少中间商赚差价。。。
- 当前的泛型设计对使用方来说几乎无感。
2. 会学的早就上车了,不愿学的多说无益。
3. 敢用 go 的公司太少。估计只有等字节跳动开始向社会输出人才,这玩意才能在国内普及开。
相反,我很喜欢 err != nil 的处理方式,我相信很多已经在写 Go 的人也是同样的感受( Twitter 上很多 Go 社区的人为此辩护)。审美问题,不是大事儿。
范型无缝衔接是对于已经使用过静态类型语言比如 Java 或 Go 1 的人来说的。对于只有动态类型语言经验的人来说,interface 的一层抽象,再加上范型的一层抽象,还是会造成一定程度的困惑的。
两层抽象学不会的话,建议转行 (狗头
不过我认同你的观点,泛型出来之后整个语言的复杂性会明显提升。
带 err 总比 java try catch 高端。。。符合 c 语言特性。try catch 才是最费时的。。。
当然你也可以改成 java try catch 模式,以代码是正常运作的都是‘好人模式’,所以不存在错误,错误只是小概率所以你可以使用 defer + recover 去捕捉 panic 然后恢复。
recover 相当于 catch 了。。。
继续学我的 C/C++
高端什么?写业务的时候,你用 err 代码比 try catch 多了不知道多少,关键的是写 golang 的忽略 err 比 try catch print 不知道多了多少
顶层的 web 业务写多了 ,就知道需要向底层进攻斗不过底层程序员了,谁掌握底层核心谁拥有话语权,底层全是 c 语言啊,,,那些什么 sys 驱动文件都是 c 写的啊,,,你想做自定义高点的 vpn 都得接近底层啊。。。而不仅仅只是调用人家 api 。。。
反正代码行业从 c 起步才是正确的而不是从 java 起步。。。以后到了与 360 那个级别竞争就知道了。。。或者被绝对底层监控录屏而无可奈何,技术没人家那么底层所以无可奈何。。。
那些评激 go 语言 err 处理的都不是 c 起步的人。。。都是 c#、java 起步的人。。。
说的好像 golang 现在不是用来写 web 一样,如果 golang 老老实实做他的中间层,底层,他用 err 还是 try catch 我才不管,但是现在很多都是用 golang 来写 web,你用 err 还是 try catch 就和我有关系了
err 强迫你思考每个函数的 fail path,exception 强迫你思考整个函数的 fail case 。go 出来之前大家都觉得前者没有工程性,但后来 go 确实也证实了这条路是完全没问题的
err != nil 的处理方式真的只是审美问题,三位创始人的审美。当前有很多支持的声音,也同样有很多反对的声音。Go 开发组包括社区也一直在寻找解决方案,不过看起来比范型还要难以处理,因为 err != nil 是最简单的形式了,不能再简化了,而它偏偏又能解决所有的错误处理需求。Robert Griesmer 之前 proposal 了一个 try 关键字,被社区否定撤回了,还有很多其它的 proposal 都是一样的命运。这不是一个缺陷,而且自有它的优点和大量拥趸,所以我说这是一个审美问题。请不要在这里争论这个问题了。
怎么可能没问题,如果没问题,知乎为什么不走 err ?
完全同意你的观点。感觉写 golang 想到了错误处理之后,程序很少崩了。脚本原来用 Python 写,动不动跑着就挂了,还看不太出来什么原因。我个人还是觉得静态语言在复杂使用情景下面更稳一点。
有书吗?想学。
天天喷 if err 也是服了,写出来好看代码的语言有几个?
2020 年了,王垠这种垃圾文章就别拿出来丢人现眼了。这种文章放到发表的那一年,也是错漏百出,稍有水平的人都看得出错误有多少。
你既然知道知乎用 panic / recover,那你还说什么?你没有能力让你们公司代码改用 panic / recover 来处理错误,那是你能力低下,不想用就别用,赶紧换公司换语言,别说得好像别人强迫你用似的。一边忍受一边用,你是受虐狂吗?
用 go 1 年半了,err 处理挺让我安心的。
之前写 python 总会担心程序跑起来之后各种奇奇怪怪的少概率点抛出异常,用第三方库抛异常,代码上线之后修 bug 是各种加 try 包代码,当然也跟个人能力有关,无法考虑所有可能异常点。
go 把 err 处理,强制性让人考虑错误处理,程序稳健性提高不少,剩下的还经常遇到的异常就是接口指针的 nil 判断没做或者没正确初始化。没正确初始化的随着 go 熟练也在减少,剩下的就是返回 err 跟指针,可能 err 忽略拿着指针直接用了。
当然楼上有人提到 union type,应该说的是 rust 的那种吧,只了解语法没大量用熟悉它就不评价了。
又一个 gcp 的人天天劝你学 go
好多时候出现 err 我都只是想抛到上层,但是却不得不判断一次……感觉要是加一个 rust 里面通过 ? 传递 err 的特性就好了
你跟一帮 Java 小子说 Golang 加了泛型会变难?
那爱衣无
这种为什么稳健行提高?难道 golang 的 err 不也是一般往上抛吗?
这点真心希望官方提供一个语法糖,以前就有人提过增加 check 关键词,比如
check err
有错往上抛,无错就忽略,这语法糖就很甜。
那倒是说说错漏在哪里,就我看来除了类型后置无分隔符我觉得无所谓其他还是很赞同的。
其他可能还有争议,err!=nil 我觉得没什么好说的,能把 rust 的 enum 和 Result 抄过来也好不少。
举个常见的场景,我想把一个(可能出错)的函数返回值作为参数传给另一个函数,如果出错就把错误传递上去:
go 你得这样:
val,err:=f1()
if err!=nil{
return nil,err
}
f2(val)
而 rust 直接:
f2(f1()?);
就可以了。
以及王垠提到的,没有任何机制能保证 err 和 val 一定一个是 nil 一个不是,全靠程序员约定俗成。明明 union type 能够完美表示,却非要用 tuple 。
早点学会 go 早点上车,现在市场上还是很缺 go 开发的,我感觉是个机会,趁现在人还不多的时候学,省得到时候培训机构铺天盖地的培训出来一批人和你内卷。
我有写 go 跟 Java…感觉我写的 go 代码非常丑,可能我功力不够
目前我用 interface 写的函数,只能大量使用反射和 switch 去处理,范型应该是众望所归,对写过 C/C++和 java 的人也不会有任何难度。
主要写 go 两年了,看到一大堆 if err!=nil 还是很不爽,特别是闲的时候费尽心思写出一段优雅的代码,一大堆 err 瞬间把你打回代码搬砖工的原型。
个人还有一点期望,增加一个空指针的语法糖,未手动判断 nil 的情况下不要 panic 。在接近脚本语言的语法情景下,我常常会忘掉判断 nil,以前写 C++那会估计也没写 go 的空指针多
据我观察,本站大部分讨论 go 语言特征的最终会变成 if err !=nil 之争。
难道你们练习时长两年半的 go 程序员看到一个“泛型”就已经大脑缺氧、理解困难了吗?难道中学数学没学过全称量词?
如果你知道 Google 里大家是怎么写 C++就不会对这个设计感到奇怪,毕竟一开始他们还是想用 go 代替 C++ 的。但问题是 C++可以用宏把 err 的检查和赋值( assign_or_return )写在一行,go 就没办法
文章垃圾不垃圾不是很懂,你这样张口就说别人垃圾,真的是可以。
说句不好听的,我觉得你比不上王垠,在座的各位也没几个能比得上,所以别总是乱喷了。
有一说一,转 go 之后,用 if err != nil 后 写的代码确实很少出错,很稳定
最近在学 go
目前还在 node 苦海中寻找出路,如果有要学习第二门后台语言当然选择 go,我可受不了 Java 那过度的设计模式和语法规则
喜欢 if err,不喜欢 try
麻烦问下中文到底推荐哪本书?谢谢了。网上的书,全是差评啊。
go 语言,变量是不是越短越好
不懂泛型哪里难
Rust 才应该是真正的云原生语言,没开玩笑。
正反论据都很多,就不列举了。
也早有意义吧
go 是用来干啥的
我是觉得 interface 已经够用了
go 没有那么多语法糖和写法,所以看项目审代码容易的多…
以前看 python 项目,各种炫技语法糖…常常不明白作者的用意,life 一点也不 short
Java 创始人最近谈十几年前设计初衷: https://www.zdnet.com/google-amp/article/programming-languages-java-founder-james-gosling-reveals-more-on-java-and-android/ ,当初所有设备都在重复造轮子,以及处理内存安全问题,所以新语言简单(c style)安全,和性能做了 trade-off 。go 看上去略有点 KPI 项目性质,堆了太多复杂的东西,很多高级特性其他语言也可以轻易实现, 之前王 yin 大神的吐槽: http://www.yinwang.org/blog-cn/2014/04/18/golang
google 原来想用 go 代替 c++,结果 c++的人没有转,写 c 的人转了。java 的人有一小部分赶时髦的在边缘业务尝试。还是那句话,“如果 rust 被证明很有钱景,那么地球一夜之间将会多出 100 万 rust 程序员”
我看你小学语文都没学好,建议你找个小学生
我看你小学语文都没学好,建议你找个小学生,缩写一下我说的话,把句子成分搞清楚!
手写跨域后发现还是得用框架
一看就是和王垠一样,根本就是半桶水。谁告诉你 err 和 val 肯定一个是零值一个不是的?
例如最常见的 io.Reader 接口,返回值是 int, error,这两个可能同时非零,例如返回 42, io.EOF ,这种场景你怎么用 union type?
之前有一个提案可以这样写 f2(check f1()),不过没通过。这种写法并不完美,你可以去 github 看看讨论。
即使是抛也是显式抛,直到合适的调用层处理它,也是处理了错误,当然怎么处理就跟业务和个人习惯个人能力有关了。
python 把错误跟异常混在一起,只能到处 try,或者最外层 try,一不注意本来可以忽略的错误没处理就上抛影响业务了。
我恰好想法, 以前写 linux C 的,看到 if err 反而很亲切
水军,老咔叽玩意
11 年过去了你们还在讨论 if err != nil …
绝大多数使用场景这两个值就是应该有一个空,而 go 没有机制保证这一点。成功就是成功出错就是出错,不能说执行了一半错了一半。这个 io.EOF 场景恰好就是体现 go 错误处理糟糕的一个地方,你不但要检查 err!=nil,还得检查 err!=io.EOF ,读完了和读不了显然得不同处理。
rust 里 Read::read(&mut self,buf:&mut [u8])->Result<usize> 遇到 EOF 直接返回当前已经读取的长度,下次再调用立即返回 0,其他种类的错误既可以通过带有 exhausted check 的 enum match 确保所有情况都显式处理,也可以直接?语法糖轻松向上抛,并且得益于类型系统还带有 Java 中 checked exception 等价的效果。
我好像阅读障碍, 对于这么长的文章读不下去.
挺喜欢够浪(golang)
我们嵌入式网关里已经转 go 做业务了, 爽的一逼
各位熟练 go 的
recover 只能用于 panic 对不对 总共有几种情况会产生 panic ?
比如调用 ioutil.WriteFile(“a.txt”,[]byte(“sdfsd”),0644) 如果对当前目录没权限 会返回 err, printf 出来是 Permission denied
所以只要写 go 就无法避免检查返回值 漏检查了导致问题 会很难排查出来
如果有一门支持 GC 的 Rust 语言就好了
难道 rust 可以保证你检查了返回值是 0 ? rust 只是多了?这个语法糖而已,难道就不是检查错误且要检查返回值是 0 ?
另外,我看你也不怎么熟悉 rust,io::ErrorKind 明明是标记为 non_exhaustive,文档里也明确写了 This list is intended to grow over time and it is not recommended to exhaustively match against it.
你说的是错的。
Read::read 文档里还有一个约定:An error of the ErrorKind::Interrupted kind is non-fatal and the read operation should be retried if there is nothing else to do.
按照你的标准,这算不算糟糕?你要检查有没有错,如果有错,是不是 Interrupted,要不要重试,还要检查有没有读完,你真的可以随时用 ? 这个语法糖吗?
文档里的这个约定,是用语言机制保证的,还是仅仅由文档来约定的?不看文档,你知道要特别处理 Interrupted 吗?
1:golang 粉丝太强势,楼上可以参看
2:大道至简,缺少大量语法糖,是优势也是劣势
3:gorotine 是最大的优点
4:go 的确是很重要,我觉得学一下总没坏处啊,学习这玩意儿别太偏激,跟随下潮流,Go,Rust,Java 谁更牛我不知道,反正都学一下呗,自己感兴趣哪个用哪个,小孩子才分对错,又不是以后不能切换。
5:golang 失去了现代语言很多特性,这点来看见仁见智
异常影响太大,整个第三方库,而且 error 和异常混合使用容易造成混乱
所以 rust 就可以在一个循环里连续读,返回值为 0 为中止条件。
exhaustive 是编译器保证的,能确保当前情况确实是 exhausted,以后再加了编译会报错提醒你修改。
而 go 的错误类型就残废的多,没有办法保证你处理了每一种错误。
你当然可以不额外处理,有错就返回。go 你不看文档不也是直接 err!=nil 返回么。
额外处理的语法也比 go 要优雅:
loop {
match p.read(&mut buf){
Ok(0)=>break,
Ok(i)=>{//do something},
Err(ErrorKind::Interrupted)=>{//handle interrupt},
Err(e)=>{//handle other error}
}
}
赞,才知道 import by 这个功能
#64 其实 golang 念 go language
我觉得还是 java 的 jdk 代码写的优雅
都说了 io::ErrorKind 标记了 #[non_exhaustive],编译器并不会检查。rust 也不能保证你处理了每一种情况。
go 这样写:
for {
n, err := r.Read(buf)
if n > 0 {
//handle data
}
if is(err, io.EOF) {
break
}
if err != nil {
// handle error
}
}
不是比你那样更简洁?
It may return the (non-nil) error from the same call, 这个情况在底层是 posix IO 的情况下是不可能发生的,所以说 union type 完全可以表达正常的语义,不需要 int 和 err 同时出现.posix IO 是使用最广的 IO,因此 go 的 Reader 接口设计的有问题, 凭空出现了本应不存在的情况
另外 Rust 里标注#[non_exhaustive]的 enum 在 match 时没有_
来匹配将来可能新增的字段是会编译错误的,因此不需要看到文档里写这句话也应该知道.用到了,编译不过,rustc 报错提示你 match 分支必须有_,自然就知道了.
如果你要读完那不应该用 read,应该用 read_to_end, 文档里写的很清楚,read_to_end 会忽略 ErrorKind::Interrupted.我不知道别人怎么写,但是我用写的命令行程序里 read_to_end 是直接用?抛到 main 然后直接输出错误退出程序的.磁盘 io 错误也没法处理,但是各种网络库里就要仔细处理了.
在 read 里暴露 ErrorKind::Interrupted 和 ErrorKind::WouldBlock 是因为异步运行时需要靠这个来进行异步 IO 操作.Rust 暴露很多细节是必要的,因为作为系统语言 Rust 允许程序员和最底层进行交互.go 搞有栈协程,因此这种 no blocking IO 的东西看起来很没有用.但是 go 程序员可不能在不改造编译器的情况下修改 go 的运行时.
posix 有没有,关 go 的 io.Reader 什么事? go 支持一堆 non-posix 的平台。而且实现了 io.Reader 的类型,又不限于系统 io 。它是个 byte stream 接口,和 posix io 毫无关系。这个设计允许少一次 Read 调用,难道和 posix 不同,就叫有问题?
没错啊,你的 match 里有 _ ,然后后面新增了其他 kind,编译器不会报错,你就不知道新增了一个 kind,你就不知道需要特别处理这个新增的 kind 。前面有人不是说 rust 会提示你处理所有情况吗?我就明确说了,不会。你只能用兜底的分支去处理,你不看文档,你就不知道多了。
read_to_end? 你内存只有 32G,要你处理一个 128G 的文件,你也用 read_to_end?
看看 tokio 从 go 的运行时学来多少东西吧,rust 只不过把运行时的实现扔出去了而已,你用了 async,你就撇不开 async executor,这就是和 go 类似的运行时,也离不开 M:N 式的调度器。
就想知道,你英语为何这么厉害
就 go 这设计,早就翻车了。 泛型语法的设计直接劝退。
而且 go 本身就完全不适合写业务逻辑代码,就只适合写一些中间件或者 Cloud Native 应用。
一直不明白拿 go 写 web 的人是啥想法(特指写业务代码的)
你这种一不小心 error 就丢掉了,难怪你换 golang 业务不崩了
项目需要刚开始学… 看你们吵得好凶的样子 [开始看书入门
接触过其它几门语言,感觉 golang 的语法有点太过原始,本来可以很好区分的流程被强制混在一起,心智负担很大。我觉得这不是为了性能妥协的问题
维护简单,代码维护本质就是给人看。Go 足够简单就是优势,甚至跟楼主说的一样,不需要很高深知识就可以开始尝试阅读大型项目源码。其他语言里面不敢想
写过 C 的表示很正常
C 语言在我的印象里面就不是用来写业务的语言,是用来写底层的语言
我用 go 就看这两点,比 Python 性能好并且静态类型,
比 Java 启动快内存占用少,并且有高阶函数 Goroutine 等,不用看那一堆过度封装
c 语言不也是 if err 这种吗 go 和 c 一模一样 为什么喷 go? 喷子们没学过 c 吗 是培训班出来的吗
我一直觉得语言学得越多思维越开阔. 各种各样的语法, 思路, 理念都见识过, 就不会觉得某种语言的用法奇葩了.
error code 大法好,try…catch 和 error 都是异端!
继续用我的 C++ 了 😂
作为一个 java 转 go 不到一年的人,表示还是 try catch 好用,毕竟明确划分了错误类型。说 if err != nil 能减少崩溃的人。。。可能是自己问题吧,任何崩溃也不能赖语言上啊。
N 年前听播客,说 Java 不行了,不碰 Java
N-1 年前说 PHP 是世界上最差的语言,不碰 PHP
现在 Java 企业中该用还得用、PHP 写的好应用也不少…
errlang
确实最后都成了争论 err != nil 好不好, 哈哈哈
加个泛型不会增加多少难度,rust 如是说。
别的不说 go 的语法写起来超快,写起小工具比写 bash 还快,现在刚开始学 rust 感觉复杂多了。
真的搞笑,就 go 这种语言,不就几天就上手了吗,后面工作要用再深度研究呀,现在难道招聘会那么看重语言,都是看综合素质的呀
写了几个小时 go 感觉自己更像搬砖的了。copy 改改改 copy 改改改
泛型出来后采纳的人只多不会少的, go 不适合业务逻辑的结论也太武断了
在IT领域,Golang(又称Go语言)的确是一个值得趁早学习的编程语言。其简洁、高效、并发处理能力强大的特点,使得Go语言在云计算、大数据、微服务等领域得到了广泛应用。
首先,Go语言的语法简洁明了,学习曲线相对平缓,对于初学者来说十分友好。同时,Go语言的标准库丰富,提供了许多实用的工具和函数,能够帮助开发者快速构建高效、稳定的程序。
其次,Go语言在并发编程方面表现出色。其内置的goroutine和channel机制,使得开发者能够轻松实现并发任务,提高程序的执行效率。在云计算和大数据处理等领域,并发编程能力尤为重要,因此Go语言在这些领域具有天然的优势。
此外,Go语言的生态系统日益完善。越来越多的开源项目和商业应用开始采用Go语言进行开发,这为学习者提供了丰富的实践机会和资源。通过参与开源项目或者实际项目开发,学习者可以不断提升自己的编程能力和实战经验。
因此,对于想要进入IT领域或者提升编程技能的人来说,趁早学习Go语言无疑是一个明智的选择。当然,学习任何一门编程语言都需要付出努力和时间,但只要坚持练习和实践,就一定能够掌握Go语言并运用到实际工作中去。
总之,Go语言具有广阔的发展前景和强大的应用能力,趁早学习并上车将为你未来的职业发展打下坚实的基础。