V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
kidlj
V2EX  ›  Go 编程语言

要学 Go 的赶紧上车

  •  
  •   kidlj ·
    kidlj · 2020-10-03 12:59:17 +08:00 · 23787 次点击
    这是一个创建于 1273 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 。就像上面说的,当范型被大量运用以后,难度应该要提高一个量级。这是我的一点点经验,分享给大家,希望有帮助。

    180 条回复    2020-11-26 10:39:41 +08:00
    1  2  
    chenqh
        1
    chenqh  
       2020-10-03 13:02:29 +08:00 via Android   ❤️ 6
    我就问你怎么忍受 if err 的
    chenqh
        2
    chenqh  
       2020-10-03 13:03:24 +08:00 via Android   ❤️ 1
    感觉 err 和病毒一样,弄的我几乎每个 function 都要带 err
    labulaka521
        3
    labulaka521  
       2020-10-03 13:06:19 +08:00 via iPhone   ❤️ 3
    @chenqh 我觉得这样挺好 明确每一个函数的返回是否报错 虽然很麻烦
    dcalsky
        4
    dcalsky  
       2020-10-03 13:06:33 +08:00   ❤️ 8
    等等党永远不亏。
    kangsheng9527
        5
    kangsheng9527  
       2020-10-03 13:08:23 +08:00   ❤️ 1
    不用泛型就可以了。。。所以难度没变。。。

    我从不推荐使用各种框架。。。

    我推荐尽可能使用原生库去完成项目,尽量少使用第三方库。。。

    所以也不推荐写 web 用 echo 框架之类。。。

    减少中间商赚差价。。。
    lewinlan
        6
    lewinlan  
       2020-10-03 13:08:34 +08:00 via Android
    1. 当前的泛型设计对使用方来说几乎无感。
    2. 会学的早就上车了,不愿学的多说无益。
    3. 敢用 go 的公司太少。估计只有等字节跳动开始向社会输出人才,这玩意才能在国内普及开。
    kidlj
        7
    kidlj  
    OP
       2020-10-03 13:08:52 +08:00
    @chenqh 相反,我很喜欢 err != nil 的处理方式,我相信很多已经在写 Go 的人也是同样的感受( Twitter 上很多 Go 社区的人为此辩护)。审美问题,不是大事儿。
    kidlj
        8
    kidlj  
    OP
       2020-10-03 13:12:18 +08:00
    @lewinlan 范型无缝衔接是对于已经使用过静态类型语言比如 Java 或 Go 1 的人来说的。对于只有动态类型语言经验的人来说,interface 的一层抽象,再加上范型的一层抽象,还是会造成一定程度的困惑的。
    lewinlan
        9
    lewinlan  
       2020-10-03 13:15:38 +08:00 via Android
    @kidlj 两层抽象学不会的话,建议转行 (狗头
    不过我认同你的观点,泛型出来之后整个语言的复杂性会明显提升。
    kangsheng9527
        10
    kangsheng9527  
       2020-10-03 13:16:09 +08:00
    @chenqh 带 err 总比 java try catch 高端。。。符合 c 语言特性。try catch 才是最费时的。。。

    当然你也可以改成 java try catch 模式,以代码是正常运作的都是‘好人模式’,所以不存在错误,错误只是小概率所以你可以使用 defer + recover 去捕捉 panic 然后恢复。
    recover 相当于 catch 了。。。
    whincwu142
        11
    whincwu142  
       2020-10-03 13:18:23 +08:00 via Android
    继续学我的 C/C++
    chenqh
        12
    chenqh  
       2020-10-03 13:20:20 +08:00 via Android   ❤️ 2
    @kangsheng9527 高端什么?写业务的时候,你用 err 代码比 try catch 多了不知道多少,关键的是写 golang 的忽略 err 比 try catch print 不知道多了多少
    kangsheng9527
        13
    kangsheng9527  
       2020-10-03 13:29:18 +08:00   ❤️ 2
    @chenqh 顶层的 web 业务写多了 ,就知道需要向底层进攻斗不过底层程序员了,谁掌握底层核心谁拥有话语权,底层全是 c 语言啊,,,那些什么 sys 驱动文件都是 c 写的啊,,,你想做自定义高点的 vpn 都得接近底层啊。。。而不仅仅只是调用人家 api 。。。

    反正代码行业从 c 起步才是正确的而不是从 java 起步。。。以后到了与 360 那个级别竞争就知道了。。。或者被绝对底层监控录屏而无可奈何,技术没人家那么底层所以无可奈何。。。

    那些评激 go 语言 err 处理的都不是 c 起步的人。。。都是 c#、java 起步的人。。。
    chenqh
        14
    chenqh  
       2020-10-03 13:35:11 +08:00 via Android
    @kangsheng9527 说的好像 golang 现在不是用来写 web 一样,如果 golang 老老实实做他的中间层,底层,他用 err 还是 try catch 我才不管,但是现在很多都是用 golang 来写 web,你用 err 还是 try catch 就和我有关系了
    coyove
        15
    coyove  
       2020-10-03 13:41:24 +08:00   ❤️ 4
    err 强迫你思考每个函数的 fail path,exception 强迫你思考整个函数的 fail case 。go 出来之前大家都觉得前者没有工程性,但后来 go 确实也证实了这条路是完全没问题的
    kidlj
        16
    kidlj  
    OP
       2020-10-03 13:42:07 +08:00
    @chenqh @kangsheng9527 err != nil 的处理方式真的只是审美问题,三位创始人的审美。当前有很多支持的声音,也同样有很多反对的声音。Go 开发组包括社区也一直在寻找解决方案,不过看起来比范型还要难以处理,因为 err != nil 是最简单的形式了,不能再简化了,而它偏偏又能解决所有的错误处理需求。Robert Griesmer 之前 proposal 了一个 try 关键字,被社区否定撤回了,还有很多其它的 proposal 都是一样的命运。这不是一个缺陷,而且自有它的优点和大量拥趸,所以我说这是一个审美问题。请不要在这里争论这个问题了。
    chenqh
        17
    chenqh  
       2020-10-03 13:53:07 +08:00 via Android
    @coyove 怎么可能没问题,如果没问题,知乎为什么不走 err ?
    zhangysh1995
        18
    zhangysh1995  
       2020-10-03 14:04:33 +08:00
    @coyove 完全同意你的观点。感觉写 golang 想到了错误处理之后,程序很少崩了。脚本原来用 Python 写,动不动跑着就挂了,还看不太出来什么原因。我个人还是觉得静态语言在复杂使用情景下面更稳一点。
    qzy168
        19
    qzy168  
       2020-10-03 14:07:44 +08:00
    有书吗?想学。
    huiyifyj
        20
    huiyifyj  
       2020-10-03 14:08:59 +08:00
    天天喷 if err 也是服了,写出来好看代码的语言有几个?
    Jirajine
        21
    Jirajine  
       2020-10-03 14:14:37 +08:00 via Android
    err!=nil 绝对是 go 最大的糟粕之一,一个 union type 就能解决的问题非要搞个 tuple 出来。
    Jirajine
        22
    Jirajine  
       2020-10-03 14:16:15 +08:00 via Android   ❤️ 1
    reus
        23
    reus  
       2020-10-03 14:29:59 +08:00   ❤️ 2
    @Jirajine 2020 年了,王垠这种垃圾文章就别拿出来丢人现眼了。这种文章放到发表的那一年,也是错漏百出,稍有水平的人都看得出错误有多少。
    reus
        24
    reus  
       2020-10-03 14:33:17 +08:00
    @chenqh 你既然知道知乎用 panic / recover,那你还说什么?你没有能力让你们公司代码改用 panic / recover 来处理错误,那是你能力低下,不想用就别用,赶紧换公司换语言,别说得好像别人强迫你用似的。一边忍受一边用,你是受虐狂吗?
    jingniao
        25
    jingniao  
       2020-10-03 14:36:57 +08:00 via Android
    用 go 1 年半了,err 处理挺让我安心的。
    之前写 python 总会担心程序跑起来之后各种奇奇怪怪的少概率点抛出异常,用第三方库抛异常,代码上线之后修 bug 是各种加 try 包代码,当然也跟个人能力有关,无法考虑所有可能异常点。
    go 把 err 处理,强制性让人考虑错误处理,程序稳健性提高不少,剩下的还经常遇到的异常就是接口指针的 nil 判断没做或者没正确初始化。没正确初始化的随着 go 熟练也在减少,剩下的就是返回 err 跟指针,可能 err 忽略拿着指针直接用了。
    当然楼上有人提到 union type,应该说的是 rust 的那种吧,只了解语法没大量用熟悉它就不评价了。
    shutongxinq
        26
    shutongxinq  
       2020-10-03 14:39:15 +08:00 via iPhone
    又一个 gcp 的人天天劝你学 go
    24bit
        27
    24bit  
       2020-10-03 14:44:18 +08:00
    好多时候出现 err 我都只是想抛到上层,但是却不得不判断一次……感觉要是加一个 rust 里面通过 ? 传递 err 的特性就好了
    cigarzh
        28
    cigarzh  
       2020-10-03 14:44:34 +08:00
    你跟一帮 Java 小子说 Golang 加了泛型会变难?

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

    check err

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

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

    以及王垠提到的,没有任何机制能保证 err 和 val 一定一个是 nil 一个不是,全靠程序员约定俗成。明明 union type 能够完美表示,却非要用 tuple 。
    yoke123
        33
    yoke123  
       2020-10-03 15:08:49 +08:00 via Android
    早点学会 go 早点上车,现在市场上还是很缺 go 开发的,我感觉是个机会,趁现在人还不多的时候学,省得到时候培训机构铺天盖地的培训出来一批人和你内卷。
    EminemW
        34
    EminemW  
       2020-10-03 15:09:34 +08:00
    我有写 go 跟 Java..感觉我写的 go 代码非常丑,可能我功力不够
    BoarBoar
        35
    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
        36
    falcon05  
       2020-10-03 15:27:31 +08:00 via iPhone
    据我观察,本站大部分讨论 go 语言特征的最终会变成 if err !=nil 之争。
    pisc
        37
    pisc  
       2020-10-03 15:30:11 +08:00 via Android   ❤️ 1
    难道你们练习时长两年半的 go 程序员看到一个“泛型”就已经大脑缺氧、理解困难了吗?难道中学数学没学过全称量词?
    laike9m
        38
    laike9m  
       2020-10-03 15:32:12 +08:00 via Android   ❤️ 1
    @kidlj 如果你知道 Google 里大家是怎么写 C++就不会对这个设计感到奇怪,毕竟一开始他们还是想用 go 代替 C++ 的。但问题是 C++可以用宏把 err 的检查和赋值( assign_or_return )写在一行,go 就没办法
    dahhd
        39
    dahhd  
       2020-10-03 15:39:44 +08:00 via iPhone   ❤️ 15
    @reus 文章垃圾不垃圾不是很懂,你这样张口就说别人垃圾,真的是可以。
    说句不好听的,我觉得你比不上王垠,在座的各位也没几个能比得上,所以别总是乱喷了。
    SignLeung
        40
    SignLeung  
       2020-10-03 15:45:02 +08:00   ❤️ 1
    有一说一,转 go 之后,用 if err != nil 后 写的代码确实很少出错,很稳定
    zxCoder
        41
    zxCoder  
       2020-10-03 15:51:40 +08:00
    最近在学 go
    Zchary
        42
    Zchary  
       2020-10-03 16:00:03 +08:00 via iPhone
    目前还在 node 苦海中寻找出路,如果有要学习第二门后台语言当然选择 go,我可受不了 Java 那过度的设计模式和语法规则
    herozzm
        43
    herozzm  
       2020-10-03 16:06:27 +08:00 via Android
    喜欢 if err,不喜欢 try
    mikulch
        44
    mikulch  
       2020-10-03 16:09:15 +08:00 via iPhone
    麻烦问下中文到底推荐哪本书?谢谢了。网上的书,全是差评啊。
    mikulch
        45
    mikulch  
       2020-10-03 16:10:45 +08:00 via iPhone
    @Zchary go 语言,变量是不是越短越好
    fakeshadow
        46
    fakeshadow  
       2020-10-03 16:31:16 +08:00   ❤️ 1
    不懂泛型哪里难
    Nugine0
        47
    Nugine0  
       2020-10-03 16:32:08 +08:00 via Android   ❤️ 1
    Rust 才应该是真正的云原生语言,没开玩笑。
    正反论据都很多,就不列举了。
    wzw
        48
    wzw  
       2020-10-03 16:33:36 +08:00 via iPhone
    @mikulch 也早有意义吧
    impig33
        49
    impig33  
       2020-10-03 16:35:44 +08:00
    go 是用来干啥的
    mikulch
        50
    mikulch  
       2020-10-03 16:38:38 +08:00 via iPhone
    @impig33 写 web 写业务,增删改查
    chengxiao
        51
    chengxiao  
       2020-10-03 16:53:24 +08:00
    我是觉得 interface 已经够用了
    go 没有那么多语法糖和写法,所以看项目审代码容易的多....
    以前看 python 项目,各种炫技语法糖..常常不明白作者的用意,life 一点也不 short
    hanjie
        52
    hanjie  
       2020-10-03 17:07:53 +08:00
    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 程序员”
    reus
        53
    reus  
       2020-10-03 17:15:16 +08:00 via Android
    @dahhd 我看你小学语文都没学好,建议你找个小学生
    reus
        54
    reus  
       2020-10-03 17:18:42 +08:00
    @dahhd 我看你小学语文都没学好,建议你找个小学生,缩写一下我说的话,把句子成分搞清楚!
    vision1900
        55
    vision1900  
       2020-10-03 17:26:46 +08:00
    @kangsheng9527 手写跨域后发现还是得用框架
    reus
        56
    reus  
       2020-10-03 17:40:51 +08:00
    @Jirajine 一看就是和王垠一样,根本就是半桶水。谁告诉你 err 和 val 肯定一个是零值一个不是的?
    例如最常见的 io.Reader 接口,返回值是 int, error,这两个可能同时非零,例如返回 42, io.EOF ,这种场景你怎么用 union type?
    之前有一个提案可以这样写 f2(check f1()),不过没通过。这种写法并不完美,你可以去 github 看看讨论。
    jingniao
        57
    jingniao  
       2020-10-03 17:51:33 +08:00 via Android
    @chenqh 即使是抛也是显式抛,直到合适的调用层处理它,也是处理了错误,当然怎么处理就跟业务和个人习惯个人能力有关了。
    python 把错误跟异常混在一起,只能到处 try,或者最外层 try,一不注意本来可以忽略的错误没处理就上抛影响业务了。
    mangogeek
        58
    mangogeek  
       2020-10-03 18:14:34 +08:00
    @chenqh 我恰好想法, 以前写 linux C 的,看到 if err 反而很亲切
    huangsh
        59
    huangsh  
       2020-10-03 18:33:54 +08:00
    水军,老咔叽玩意
    Mohanson
        60
    Mohanson  
       2020-10-03 18:38:16 +08:00 via Android
    11 年过去了你们还在讨论 if err != nil …
    Jirajine
        61
    Jirajine  
       2020-10-03 18:44:53 +08:00
    @reus 绝大多数使用场景这两个值就是应该有一个空,而 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 等价的效果。
    12101111
        62
    12101111  
       2020-10-03 18:45:58 +08:00
    @reus 不知道谁是半桶水,你可以看看`man 3 read`, EOF 是怎么确定的,
    No data transfer shall occur past the current end-of-file. If the
    starting position is at or after the end-of-file, 0 shall be returned.
    If the file refers to a device special file, the result of subsequent
    read() requests is implementation-defined.
    所以 42,EOF 是怎么返回的?
    go 的标准库设计的很没有品味, 很多东西都模模糊糊处理,在一些 corner case 就会出现很奇怪的行为.
    go 缺少一种 rfc 机制,导致她的设计终究是跟着 Google 的需要而不是社区的需要走的,这也限制了她像 C 一样可以流行 50 年并且可以预料的再流行至少 20 年.
    RickyC
        63
    RickyC  
       2020-10-03 18:49:26 +08:00
    我好像阅读障碍, 对于这么长的文章读不下去.
    mangogeek
        64
    mangogeek  
       2020-10-03 18:53:25 +08:00
    挺喜欢够浪(golang)
    我们嵌入式网关里已经转 go 做业务了, 爽的一逼
    AJQA
        65
    AJQA  
       2020-10-03 18:54:48 +08:00
    各位熟练 go 的
    recover 只能用于 panic 对不对 总共有几种情况会产生 panic ?
    比如调用 ioutil.WriteFile("a.txt",[]byte("sdfsd"),0644) 如果对当前目录没权限 会返回 err, printf 出来是 Permission denied
    所以只要写 go 就无法避免检查返回值 漏检查了导致问题 会很难排查出来
    reus
        66
    reus  
       2020-10-03 19:06:06 +08:00   ❤️ 2
    @12101111 我讨论的是 go 标准库定义的 io.Reader 接口,你拿 posix read 的文档来说个屁啊,根本就是两回事,看到都叫 EOF 就以为是一回事吗?不懂能不能别插嘴?
    io.Reader 文档: https://pkg.go.dev/io#Reader
    When Read encounters an error or end-of-file condition after successfully reading n > 0 bytes, it returns the number of bytes read. It may return the (non-nil) error from the same call or return the error (and n == 0) from a subsequent call.
    定义得清清楚楚。
    真的,不懂就闭嘴。王垠都还学习过一下,称得上半桶水,你是根本不懂,生搬硬套。
    fpure
        67
    fpure  
       2020-10-03 19:12:26 +08:00
    如果有一门支持 GC 的 Rust 语言就好了
    reus
        68
    reus  
       2020-10-03 19:17:53 +08:00   ❤️ 1
    @Jirajine 难道 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.
    你说的是错的。
    reus
        69
    reus  
       2020-10-03 19:34:01 +08:00
    @Jirajine 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 吗?
    coetzee
        70
    coetzee  
       2020-10-03 19:38:25 +08:00
    1:golang 粉丝太强势,楼上可以参看
    2:大道至简,缺少大量语法糖,是优势也是劣势
    3:gorotine 是最大的优点
    4:go 的确是很重要,我觉得学一下总没坏处啊,学习这玩意儿别太偏激,跟随下潮流,Go,Rust,Java 谁更牛我不知道,反正都学一下呗,自己感兴趣哪个用哪个,小孩子才分对错,又不是以后不能切换。
    5:golang 失去了现代语言很多特性,这点来看见仁见智
    MarioLuo
        71
    MarioLuo  
       2020-10-03 19:58:07 +08:00 via Android
    @cmdOptionKana 异常影响太大,整个第三方库,而且 error 和异常混合使用容易造成混乱
    Jirajine
        72
    Jirajine  
       2020-10-03 20:15:10 +08:00
    @reus 所以 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}
    }
    }
    clocktree
        73
    clocktree  
       2020-10-03 20:17:47 +08:00
    赞,才知道 import by 这个功能
    EminemW
        74
    EminemW  
       2020-10-03 20:38:04 +08:00
    @mangogeek #64 其实 golang 念 go language
    chihiro2014
        75
    chihiro2014  
       2020-10-03 20:48:45 +08:00 via iPhone
    我觉得还是 java 的 jdk 代码写的优雅
    reus
        76
    reus  
       2020-10-03 20:48:53 +08:00
    @Jirajine 都说了 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
    }
    }

    不是比你那样更简洁?
    12101111
        77
    12101111  
       2020-10-03 21:01:19 +08:00   ❤️ 1
    @reus 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 的运行时.
    reus
        78
    reus  
       2020-10-03 21:26:10 +08:00   ❤️ 1
    @12101111 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 式的调度器。
    nnws2681521
        79
    nnws2681521  
       2020-10-03 21:31:05 +08:00
    就想知道,你英语为何这么厉害
    WispZhan
        80
    WispZhan  
       2020-10-03 21:36:05 +08:00   ❤️ 1
    就 go 这设计,早就翻车了。 泛型语法的设计直接劝退。

    而且 go 本身就完全不适合写业务逻辑代码,就只适合写一些中间件或者 Cloud Native 应用。
    一直不明白拿 go 写 web 的人是啥想法(特指写业务代码的)
    chenqh
        81
    chenqh  
       2020-10-03 21:41:33 +08:00
    @jingniao 你这种一不小心 error 就丢掉了,难怪你换 golang 业务不崩了
    mosom
        82
    mosom  
       2020-10-03 21:49:53 +08:00
    项目需要刚开始学...... 看你们吵得好凶的样子 [开始看书入门
    ErrorMan
        83
    ErrorMan  
       2020-10-03 21:50:16 +08:00
    接触过其它几门语言,感觉 golang 的语法有点太过原始,本来可以很好区分的流程被强制混在一起,心智负担很大。我觉得这不是为了性能妥协的问题
    blless
        84
    blless  
       2020-10-03 21:51:19 +08:00 via Android
    @WispZhan 维护简单,代码维护本质就是给人看。Go 足够简单就是优势,甚至跟楼主说的一样,不需要很高深知识就可以开始尝试阅读大型项目源码。其他语言里面不敢想
    littlewing
        85
    littlewing  
       2020-10-03 22:12:04 +08:00
    @chenqh 写过 C 的表示很正常
    chenqh
        86
    chenqh  
       2020-10-03 23:12:46 +08:00
    @littlewing C 语言在我的印象里面就不是用来写业务的语言,是用来写底层的语言
    TypeError
        87
    TypeError  
       2020-10-04 00:09:36 +08:00 via Android
    我用 go 就看这两点,比 Python 性能好并且静态类型,
    比 Java 启动快内存占用少,并且有高阶函数 Goroutine 等,不用看那一堆过度封装
    buffzty
        88
    buffzty  
       2020-10-04 00:24:16 +08:00   ❤️ 1
    c 语言不也是 if err 这种吗 go 和 c 一模一样 为什么喷 go? 喷子们没学过 c 吗 是培训班出来的吗
    ruyu
        89
    ruyu  
       2020-10-04 00:38:48 +08:00
    我一直觉得语言学得越多思维越开阔. 各种各样的语法, 思路, 理念都见识过, 就不会觉得某种语言的用法奇葩了.
    JerryCha
        90
    JerryCha  
       2020-10-04 01:17:33 +08:00
    error code 大法好,try...catch 和 error 都是异端!
    tianshilei1992
        91
    tianshilei1992  
       2020-10-04 01:42:24 +08:00
    继续用我的 C++ 了 😂
    cassyfar
        92
    cassyfar  
       2020-10-04 02:20:35 +08:00
    作为一个 java 转 go 不到一年的人,表示还是 try catch 好用,毕竟明确划分了错误类型。说 if err != nil 能减少崩溃的人。。。可能是自己问题吧,任何崩溃也不能赖语言上啊。
    mageemeng
        93
    mageemeng  
       2020-10-04 03:01:19 +08:00
    N 年前听播客,说 Java 不行了,不碰 Java
    N-1 年前说 PHP 是世界上最差的语言,不碰 PHP
    现在 Java 企业中该用还得用、PHP 写的好应用也不少......
    deepreader
        94
    deepreader  
       2020-10-04 05:28:23 +08:00
    errlang
    dcoder
        95
    dcoder  
       2020-10-04 07:36:10 +08:00
    确实最后都成了争论 err != nil 好不好, 哈哈哈
    hst001
        96
    hst001  
       2020-10-04 07:49:43 +08:00 via Android
    加个泛型不会增加多少难度,rust 如是说。
    ypcs03
        97
    ypcs03  
       2020-10-04 09:50:04 +08:00
    别的不说 go 的语法写起来超快,写起小工具比写 bash 还快,现在刚开始学 rust 感觉复杂多了。
    woshifyz
        98
    woshifyz  
       2020-10-04 09:55:32 +08:00
    真的搞笑,就 go 这种语言,不就几天就上手了吗,后面工作要用再深度研究呀,现在难道招聘会那么看重语言,都是看综合素质的呀
    ai277014717
        99
    ai277014717  
       2020-10-04 10:22:14 +08:00
    写了几个小时 go 感觉自己更像搬砖的了。copy 改改改 copy 改改改
    dbskcnc
        100
    dbskcnc  
       2020-10-04 10:53:29 +08:00 via Android
    @WispZhan 泛型出来后采纳的人只多不会少的, go 不适合业务逻辑的结论也太武断了
    1  2  
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5614 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 44ms · UTC 06:34 · PVG 14:34 · LAX 23:34 · JFK 02:34
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.