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

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

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

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

    好吧,可能是原文。

    感谢楼主翻译。
    dndx
        7
    dndx  
       2014-07-13 14:07:34 +08:00   ❤️ 1
    这哪能叫什么特性,更像是帮助不合格的程序员写出正确的代码的 Hack 。

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

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

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

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

    上面的例子供参考,以后不发了,有污尊眼,敬请谅解。
    hhkbp2
        19
    hhkbp2  
       2014-07-13 15:44:54 +08:00
    @jemygraw 接口+适配只能解决一部分,而且多了一层,本来编译器可以自动​推导的事情,由人去手工写一遍
    jemygraw
        20
    jemygraw  
    OP
       2014-07-13 15:52:09 +08:00   ❤️ 1
    @hhkbp2 嗯,我觉得你可以不用Go,选择java比较好。
    dorentus
        21
    dorentus  
       2014-07-13 16:09:07 +08:00
    看了 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-07-13 16:14:59 +08:00
    @jemygraw
    说到范型,几乎很难提到 Java 的啊,前有 C++,后有 C#,都比 Java 更早提供范型机制。

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

    至于javascript和php迁就用户的缺点,我就不讨论了,我也不知道。
    但是,有一点就是用户的需求往往只能呵呵呵。
    abscon
        25
    abscon  
       2014-07-13 21:18:49 +08:00 via Android
    很好,我决定使用哈希表时顺便取得一个随机数,因为现在的实现确保了我可以做到这一点。golang不会因此又修改实现吧?
    jemygraw
        26
    jemygraw  
    OP
       2014-07-13 21:21:21 +08:00 via Android
    @abscon 应该不会。
    wulin
        27
    wulin  
       2014-07-13 22:56:54 +08:00
    “针与干草堆的问题(在干草堆里面找针)”,
    说的是php里面类似这样的函数http://cn2.php.net/manual/zh/function.strpos.php
    jemygraw
        28
    jemygraw  
    OP
       2014-07-13 23:08:50 +08:00
    @wulin 欢迎到Go友团评论。
    chemzqm
        29
    chemzqm  
       2014-07-13 23:17:56 +08:00
    php,javascript,perl这些脚本语言主要的关注点是如何让开发者更快的编写代码,这就导致了大量的代码依赖于许多模棱两可的特性最终很难维护,而Go的设计者更注重语言的品味,因为相比与少写几行代码,让程序员可以更快速的正确理解代码往往更为重要。
    jemygraw
        30
    jemygraw  
    OP
       2014-07-13 23:25:44 +08:00
    @chemzqm 终于遇到一个有理性思维的人了。
    est
        31
    est  
       2014-07-13 23:45:58 +08:00
    这个。。。。。。。。。。。python 的dict 不也一样么。虽然不是随机的,但是是根据hash顺序而不是插入顺序遍历的。
    generic
        32
    generic  
       2014-07-14 08:16:07 +08:00 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-07-14 08:21:30 +08:00 via Android
    @dorentus 有趣的是C++/Java泛型本身也是为了“防止程序员犯错”,即在使用容器时cast错类型。
    要说原因,各语言的泛型系统都很复杂,在新语言初期效费比不高。Java泛型也是相当晚才加上的。
    abscon
        34
    abscon  
       2014-07-14 10:01:34 +08:00 via Android
    @generic h C++的泛型本意是抽出算法的共性,避免重复代码。妥妥的正能量,没有这么强的针(xiao)对(xin)性(yan)来避免dynamic_cast出错。事实上,C++引入template后开启了而不是关闭了很多可能性,避免继承自一个共同的鸡肋然后cast来cast去这种恶心的做法只是其中的一个可能性而已。
    generic
        35
    generic  
       2014-07-14 10:20:11 +08:00
    @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-07-14 10:44:16 +08:00
    @generic 所以我得祈祷golang的设计者每做一个决定时都全知全能,预见未来,否则就像是剃须的时候把下巴剃伤了
    jemygraw
        37
    jemygraw  
    OP
       2014-07-14 12:30:39 +08:00 via Android
    @abscon 这个和想生下来就是高帅富是一个逻辑。哈哈。
    kavinyao
        38
    kavinyao  
       2014-07-14 17:17:16 +08:00   ❤️ 1
    @dorentus 用linked hash map就行,性能牺牲微乎其微。Ruby 1.9之后的hash就是这么实现的。
    abscon
        39
    abscon  
       2014-07-14 18:56:00 +08:00 via Android
    @jemygraw 我不太清楚,不过 @ddzz 正好是这么看待golang 的粉丝的 http://v2ex.com/t/122446
    jemygraw
        40
    jemygraw  
    OP
       2014-07-14 22:40:49 +08:00
    @abscon 我突然很想做独裁者。
    bombless
        41
    bombless  
       2014-07-15 01:24:20 +08:00
    我感到很囧……这个应该是随机化,因为很多算法的最优和最坏情况的性能差异很大,所以就对输入预先做一点随机化,这样整体性能可以大大提高。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   6002 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 02:31 · PVG 10:31 · LAX 18:31 · JFK 21:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.