要学 Go 的赶紧上车 - V2EX
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 24983 次点击
    这是一个创建于 1834 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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
    有书吗?想学。
    fengyj
        20
    fengyj  
       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 的空指针多
    GG668v26Fd55CP5W
        36
    GG668v26Fd55CP5W  
       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 就没办法
    v7offJ3MsdbC1IhU
        39
    v7offJ3MsdbC1IhU  
       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 都是异端!
    shiltian
        91
    shiltian  
       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     Solana     862 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 38ms UTC 20:33 PVG 04:33 LAX 13:33 JFK 16:33
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86