[译文] 关于 Golang 的一个令我深深叹服的特性 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
jemygraw

[译文] 关于 Golang 的一个令我深深叹服的特性

  •  
  •   jemygraw
    jemygraw 2014 年 7 月 13 日 5281 次点击
    这是一个创建于 4302 天前的主题,其中的信息可能已经有所发展或是发生改变。
    41 条回复    2014-07-15 01:24:20 +08:00
    hhkbp2
        1
    hhkbp2  
       2014 年 7 月 13 日
    这也是为什么我发现Go的设计者拒绝糟糕的异常和泛型设计。他们就是想做正确的事情,当然他们知道这需要花费时间。

    ------
    没有泛型,我写代码多花了很多时间
    jemygraw
        2
    jemygraw  
    OP
       2014 年 7 月 13 日
    @hhkbp2 转换下思路。
    SoloCompany
        3
    SoloCompany  
       2014 年 7 月 13 日
    真能扯,这也能深深叹服,还顺带黑一下泛型和异常
    guotie
        4
    guotie  
       2014 年 7 月 13 日
    异常没啥用
    泛型还是很好的。
    hhkbp2
        5
    hhkbp2  
       2014 年 7 月 13 日
    @jemygraw 转换成什么
    raincious
        6
    raincious  
       2014 年 7 月 13 日
    嗯?我怎么记得在哪儿看过这篇文章?……

    好吧,可能是原文。

    感谢楼主翻译。
    dndx
        7
    dndx  
       2014 年 7 月 13 日   1
    这哪能叫什么特性,更像是帮助不合格的程序员写出正确的代码的 Hack 。

    我没读过 Go 里 Hash Table 的实现,但是 range 遍历竟然与添加顺序相同本来就很怪异。如果 Golang 通过修改实现使其变成乱序遍历那的确无伤大雅,如果是故意在遍历时添加随机因素,那就是不信任程序员的编程能力,不一定是好事。
    jemygraw
        8
    jemygraw  
    OP
       2014 年 7 月 13 日
    @raincious 嗯,多谢。
    jemygraw
        9
    jemygraw  
    OP
       2014 年 7 月 13 日
    @dndx 你说的对,这篇文章本来没有什么用处,但是就体现了一个问题,那就是做事认真。如果你做事情会导致别人犯错误,那么就是你的不对。所以就是要改。

    文章里面也说了,这个不是什么大不了的问题。

    只是表明一点:态度!
    jemygraw
        10
    jemygraw  
    OP
       2014 年 7 月 13 日
    @hhkbp2 那样看你想实现什么。如果大家都希望每一个新的编程语言都和老的完全一样,那么新的就没有意义了。
    raincious
        11
    raincious  
       2014 年 7 月 13 日
    @jemygraw 但是,最好做成集合帖。如果大量主题一个一个刷屏,恐怕L会警告或者删掉的。
    hhkbp2
        12
    hhkbp2  
       2014 年 7 月 13 日
    @jemygraw
    语言不是为了标新立异而创造的,而是为了解决问题
    有缺点就承认咯,为什么顾左右而言他
    jemygraw
        13
    jemygraw  
    OP
       2014 年 7 月 13 日
    @raincious 嗯,不发了。
    jemygraw
        14
    jemygraw  
    OP
       2014 年 7 月 13 日
    @hhkbp2 语言当然是为了解决问题而存在。但是存在以下的问题。
    1. 语言发展的成熟度问题,比如java8里面才加了lambda表达式
    2. 语言解决问题的思路问题,不同语言解决问题的方式是不同的,这是差异性的问题。你要接受和了解这种差异,举例子就是java有的go不一定有或者一定没有,但是不表示go遇到问题无法解决。
    3. 文章很清楚的讲一个问题,就是map的元素插入顺序和遍历顺序的不一致的问题。这个问题开始的时候也是不一致的,或者说按照道理就是不一致的,只是实现上是一致的,现在google发现很多人依赖这种一致性,就改了。而作者就是表达了对google的这种做事的态度表示赞赏。
    4. 哪里顾左右而言他???
    dorentus
        15
    dorentus  
       2014 年 7 月 13 日
    如果我没记错的话,Map/Associative array/Dictionary 如果想要做到“range 遍历竟然与添加顺序相同”,是要以牺牲性能为代价的,或者是把 key 顺序另外保存;无论采用那种方法,对于没有“range 遍历竟然与添加顺序相同”的用户,都是吃力不讨好的事情;真要说态度的话,这种完全可以分成两个数据结构来做,一个正常的 Map,一个可以做到“range 遍历竟然与添加顺序相同”的 Map。
    jemygraw
        16
    jemygraw  
    OP
       2014 年 7 月 13 日
    @dorentus
    1. 你的想法是对的,就是把key另外排序,我也做过。
    2. 其实如果真遇到那种key,value必须按照插入顺序读取的,我觉得完全可以用set和list来搞定。
    set存储key,list存储值。
    3. java里面有TreeMap,就是key排序的,HashMap就是随机的。
    hhkbp2
        17
    hhkbp2  
       2014 年 7 月 13 日   1
    @jemygraw
    没有泛型写起代码来很累就是缺点咯,文章说拒绝泛型是做正确的事情,不同苟同
    实际真的有这种需求如何解决,难道每个类型都要写一遍?所谓“做正确的事情”如何解决一线程序员的实际痛点?
    在这个问题上,你所说的什么新语言要与老语言不同,语言成熟度,差异性,在我看来就是顾左右而言他,只是说由于各种原因不做泛型,而没有直接面对或解决泛型的需求

    这个range顺序的事情本来就是必须的,语言本份应该做的,这都来个“深深叹服”,好吧,有句广告语说得好,在台风口上什么动物都能吹上天
    jemygraw
        18
    jemygraw  
    OP
       2014 年 7 月 13 日
    @hhkbp2 http://coolxing.iteye.com/blog/1536200

    上面的例子供参考,以后不发了,有污尊眼,敬请谅解。
    hhkbp2
        19
    hhkbp2  
       2014 年 7 月 13 日
    @jemygraw 接口+适配只能解决一部分,而且多了一层,本来编译器可以自动推导的事情,由人去手工写一遍
    jemygraw
        20
    jemygraw  
    OP
       2014 年 7 月 13 日   1
    @hhkbp2 嗯,我觉得你可以不用Go,选择java比较好。
    dorentus
        21
    dorentus  
       2014 年 7 月 13 日
    看了 https://codereview.appspot.com/5285042/patch/9001/10003 这个我就真不明白了……

    本来:
    1) 通用知识里的 Map 没有任何对 key 顺序的假设
    2) Go 实现的 Map 保留了 key 顺序(按文章里的说法)
    3) 有些人写程序的时候依赖了 2)(按文章里的说法)

    于是 Go 选择了更改实现来故意 break 3)。这没有问题。
    但是为啥要这么实现……如果没有其它原因的话,这种简单粗暴的方式(加了个随机偏移量),和文章里面说的 Javascript/PHP 过于迁就用户的做法有什么区别……
    dorentus
        22
    dorentus  
       2014 年 7 月 13 日
    @jemygraw
    说到范型,几乎很难提到 Java 的啊,前有 C++,后有 C#,都比 Java 更早提供范型机制。

    @hhkbp2
    我记得 Go 是把防止程序员犯错放在第一位的,让程序员开心排在后面;所以按这标准的话,拒绝泛型,减少潜在的错误,但是写起代码来很累,还真的是“正确”的事情 :)
    yxz00
        23
    yxz00  
       2014 年 7 月 13 日
    服点好低。。
    jemygraw
        24
    jemygraw  
    OP
       2014 年 7 月 13 日
    @dorentus 嗯,其实这篇文章的要点是,作者赞赏google这种知错就改的做法。防止程序员依赖这种一致性,因为在以后的迭代中,很有可能就不一致了。

    至于Javascript和php迁就用户的缺点,我就不讨论了,我也不知道。
    但是,有一点就是用户的需求往往只能呵呵呵。
    abscon
        25
    abscon  
       2014 年 7 月 13 日 via Android
    很好,我决定使用哈希表时顺便取得一个随机数,因为现在的实现确保了我可以做到这一点。golang不会因此又修改实现吧?
    jemygraw
        26
    jemygraw  
    OP
       2014 年 7 月 13 日 via Android
    @abscon 应该不会。
    wulin
        27
    wulin  
       2014 年 7 月 13 日
    “针与干草堆的问题(在干草堆里面找针)”,
    说的是php里面类似这样的函数http://cn2.php.net/manual/zh/function.strpos.php
    jemygraw
        28
    jemygraw  
    OP
       2014 年 7 月 13 日
    @wulin 欢迎到Go友团评论。
    chemzqm
        29
    chemzqm  
       2014 年 7 月 13 日
    php,Javascript,perl这些脚本语言主要的关注点是如何让开发者更快的编写代码,这就导致了大量的代码依赖于许多模棱两可的特性最终很难维护,而Go的设计者更注重语言的品味,因为相比与少写几行代码,让程序员可以更快速的正确理解代码往往更为重要。
    jemygraw
        30
    jemygraw  
    OP
       2014 年 7 月 13 日
    @chemzqm 终于遇到一个有理性思维的人了。
    est
        31
    est  
       2014 年 7 月 13 日
    这个。。。。。。。。。。。python 的dict 不也一样么。虽然不是随机的,但是是根据hash顺序而不是插入顺序遍历的。
    generic
        32
    generic  
       2014 年 7 月 14 日 via Android
    @jemygraw 你的例子和Java generics没有关系,因为Java在没有generics之前,排序就是像举例那样实现和使用的,有generics之后也一样。唯一区别就像你指出的,Java interface是nominal,go是structural。

    C++/Java的泛型主要为了解决homogeneous container使用时总是需要cast的问题。判断go有没有C++/Java式的泛型,看使用非语言内建容器时是否总需要cast即可。
    generic
        33
    generic  
       2014 年 7 月 14 日 via Android
    @dorentus 有趣的是C++/Java泛型本身也是为了“防止程序员犯错”,即在使用容器时cast错类型。
    要说原因,各语言的泛型系统都很复杂,在新语言初期效费比不高。Java泛型也是相当晚才加上的。
    abscon
        34
    abscon  
       2014 年 7 月 14 日 via Android
    @generic h C++的泛型本意是抽出算法的共性,避免重复代码。妥妥的正能量,没有这么强的针(xiao)对(xin)性(yan)来避免dynamic_cast出错。事实上,C++引入template后开启了而不是关闭了很多可能性,避免继承自一个共同的鸡肋然后cast来cast去这种恶心的做法只是其中的一个可能性而已。
    generic
        35
    generic  
       2014 年 7 月 14 日
    @abscon 你这个解读呢,在现在这个时间点没错。我们还可以再高大上一点:C++的泛型是一种metaprogramming机制。
    可是我们看问题还要有历史的角度。Bjarne Stroustrup在程序语言理论方面并没有很深的涉猎,C++ templates并不是在理论指导下设计,而是逐步演化来的。Templates最初要解决什么问题,看当初引入templates后实现的第一批库即可。
    Templates带来的可能性,是使用过程中逐步发现,而不是有意识设计的结果。(尽管Stroustrup在D&E中把这部分归功于他的设计哲学。注意,仅仅是设计哲学。Stroustrup在设计那些使STL成为可能的语言特性时,本来还是针对homogeneous container的具体问题,而并未有意识地支持metaprogramming。)
    正因为templates这种无意识的特点,用它作metaprogramming时才有各种语法复杂和scalability问题。我们根本上是在用一把由锤子演化来的菜刀。
    不过,即使Java generics这种有意设计的结果也相当复杂,Go暂不采用也很正常。
    abscon
        36
    abscon  
       2014 年 7 月 14 日
    @generic 所以我得祈祷golang的设计者每做一个决定时都全知全能,预见未来,否则就像是剃须的时候把下巴剃伤了
    jemygraw
        37
    jemygraw  
    OP
       2014 年 7 月 14 日 via Android
    @abscon 这个和想生下来就是高帅富是一个逻辑。哈哈。
    kavinyao
        38
    kavinyao  
       2014 年 7 月 14 日   1
    @dorentus 用linked hash map就行,性能牺牲微乎其微。Ruby 1.9之后的hash就是这么实现的。
    abscon
        39
    abscon  
       2014 年 7 月 14 日 via Android
    @jemygraw 我不太清楚,不过 @ddzz 正好是这么看待golang 的粉丝的 http://v2ex.com/t/122446
    jemygraw
        40
    jemygraw  
    OP
       2014 年 7 月 14 日
    @abscon 我突然很想做独裁者。
    bombless
        41
    bombless  
       2014 年 7 月 15 日
    我感到很……这个应该是随机化,因为很多算法的最优和最坏情况的性能差异很大,所以就对输入预先做一点随机化,这样整体性能可以大大提高。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5200 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 77ms UTC 08:39 PVG 16:39 LAX 01:39 JFK 04:39
    Do have faith in what you're doing.
    ubao msn 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