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

go 泛型出炉,看起来还是不错的

  •  1
     
  •   dbskcnc · 2019-07-27 22:34:15 +08:00 · 11819 次点击
    这是一个创建于 1944 天前的主题,其中的信息可能已经有所发展或是发生改变。

    https://go.googlesource.com/proposal/+/4a54a00950b56dd0096482d0edae46969d7432a6/design/go2draft-contracts.md

    Summary

    While this document is long and detailed, the actual design reduces to a few major points.

    Functions and types can have type parameters, which are defined using optional contracts.
    Contracts describe the methods required and the builtin types permitted for a type argument.
    Contracts describe the methods and operations permitted for a type parameter.
    Type inference will often permit omitting type arguments when calling functions with type parameters.
    

    This design is completely backward compatible, in that any valid Go 1 program will still be valid if this design is adopted (assuming contract is treated as a pseudo-keyword that is only meaningful at top level).

    We believe that this design addresses people's needs for generic programming in Go, without making the language any more complex than necessary.

    We can't truly know the impact on the language without years of experience with this design. That said, here are some speculations.

    第 1 条附言  ·  2019-08-01 10:45:16 +08:00
    作者的新 blog 说得更详细: https://blog.golang.org/why-generics
    66 条回复    2019-08-02 23:34:53 +08:00
    gamexg
        1
    gamexg  
       2019-07-27 22:48:25 +08:00
    这个大概什么时间能够用上?
    trait
        2
    trait  
       2019-07-27 23:53:57 +08:00 via iPhone   ❤️ 9
    Why not use the syntax F<T> like C++ and Java?
    When parsing code within a function, such as v := F<T>, at the point of seeing the < it's ambiguous whether we are seeing a type instantiation or an expression using the < operator. Resolving that requires effectively unbounded lookahead. In general we strive to keep the Go parser simple.

    啧啧,go 语言组这么菜的吗,上次 try QA 也拿 parse 当说事,你们什么时候能认识到对用户 simple 和你实现 simple 不是一回事?
    ipwx
        3
    ipwx  
       2019-07-28 00:01:12 +08:00
    @trait 所以 Go 语言设计者一直都很蛇精病
    useben
        4
    useben  
       2019-07-28 00:11:22 +08:00
    大概看了下,没有历史包袱就是好。引入了类似接口定义的约定和关键字 contract,看起来还不错
    sillyousu
        5
    sillyousu  
       2019-07-28 00:14:38 +08:00
    @trait

    帮你高亮
    Resolving that requires effectively unbounded lookahead.
    GM
        6
    GM  
       2019-07-28 00:21:56 +08:00
    @sillyousu 所以就理所当然地把复杂性丢给了用户?
    xfriday
        7
    xfriday  
       2019-07-28 00:27:42 +08:00
    大概看了下,contract 似乎可以取代 interface 了,功能更强
    xfriday
        8
    xfriday  
       2019-07-28 00:30:30 +08:00
    @GM “ In general we strive to keep the Go parser simple.” 人家 go team 收你钱了?开发组有自己理念,你没有权利绑架,你不是上帝
    lynskylate
        9
    lynskylate  
       2019-07-28 00:35:45 +08:00 via Android
    @xfriday 开发者不是社区的一部分? go 不是社区驱动的?
    sillyousu
        10
    sillyousu  
       2019-07-28 00:36:12 +08:00   ❤️ 1
    @GM

    这里面有很多考虑因素吧:编译速度、Go parser 复杂度、周边工具复杂度( lint、代码补全)、是否兼容现有的语法。

    比起熟悉的语法,我选择上面这些。
    lynskylate
        11
    lynskylate  
       2019-07-28 00:44:08 +08:00 via Android
    @ipwx keep thr Go parser simple 这个实在是太不能理解了,一个编译器的前端和用户有什么关系,c++parser 留下了羡慕的眼泪
    ptyfork
        12
    ptyfork  
       2019-07-28 00:53:51 +08:00
    @GM
    用 F<T> 就简单了? 那不过是用多了 java 先入为主而已。
    引进范型就一定引入复杂度,对使用者和语言开发者都是负担,跟所用的语法关系反而关系不是很大
    反而就目前 Go 中的设计,没有历史包袱,简单看了一下,跟 Go 语言之前的语法一致性保持的很好,对新手来说更友好。
    reus
        13
    reus  
       2019-07-28 02:10:30 +08:00
    @trait 你可以了解一下为什么 C++会引入 typename 这个东西,你真以为<>是“对用户 simple ”?
    reus
        14
    reus  
       2019-07-28 02:12:54 +08:00
    @xfriday 并不能,interface 是一个类型,例如 []io.Reader,在运行期,元素可以是任意实现了 io.Reader 的类型。但假如是 []T,那元素只能是特化了的那个类型。interface 是用于运行期动态分发的。
    reus
        15
    reus  
       2019-07-28 02:13:51 +08:00
    @lynskylate go team 不是开发者一部分?整个编译器都是 go 写的,好不好用,他们自己不会判断啊?就你聪明。
    reus
        16
    reus  
       2019-07-28 02:24:16 +08:00
    @sillyousu 他可能没写过 parser 吧,根本不知道 unbounded lookahead 代表什么。


    @trait 敢说提案作者菜,看来你比 Ian Lance Taylor 还牛逼?
    reus
        17
    reus  
       2019-07-28 02:32:08 +08:00
    @GM 难道把 () 改成 <>,就降低了复杂性?泛型就是以类型作为参数,既然是参数,那放在括号里,有什么问题? T(int) 就是以 int 为参数,特化出一个新的类型。
    linghutf
        18
    linghutf  
       2019-07-28 07:28:39 +08:00 via Android
    什么时候能上?
    nguoidiqua
        19
    nguoidiqua  
       2019-07-28 08:40:33 +08:00 via Android   ❤️ 1
    很多人真是先入为主,老实说当初 Java 的泛型我是很迷糊的,当然搞熟了就会觉得很简单很自然了。

    但如果你因为这样就觉得非此不可,那么就是自己封闭了自己认识新事物的能力,过去的习惯不知不觉就成了你思想的枷锁。
    trait
        20
    trait  
       2019-07-28 09:25:00 +08:00 via iPhone
    @sillyousu 现在的 parser 技术实现 lookahead 不要太简单,这并不会让 go parser 更 simple
    trait
        21
    trait  
       2019-07-28 09:33:50 +08:00 via iPhone   ❤️ 9
    某些 gopher 是没有任何思考能力的,当初有人抱怨为什么 err 这么简陋,为什么静态语言不给范型,这些人像传教士一样在各大论坛强行定义 simple,认为这些东西会让 go 过于复杂,如今 go 开始加这些“繁琐”特性,又开始各角度自洽
    ugly =/= simple,连 parser 这种都有一套完整的自动化流水线模块都交给用户肉眼 parse,真的 simple
    pisc
        22
    pisc  
       2019-07-28 10:40:59 +08:00 via Android
    @reus > 泛型就是以类型作为参数,既然是参数,那放在括号里,有什么问题?

    为什么 type parameters 可以 currying,而其他参数不能呢?
    mywaiting
        23
    mywaiting  
       2019-07-28 10:54:38 +08:00
    看完楼上的回答,我决定继续写 python
    Sasasu
        24
    Sasasu  
       2019-07-28 11:04:52 +08:00
    啥时候有编译到 go 的语言
    jhdxr
        25
    jhdxr  
       2019-07-28 11:23:35 +08:00   ❤️ 1
    @reus 是是是,整个 v2 就你写过 parser。别的语言的实现也都全是傻逼 X。golang 最厉害了,吼不吼啊?





    为什么要用于 F<T>?
    (对于有 C++/JAVA 经验的人)你看到的第一眼大概就能猜到这是什么东西。
    (对于没有 C++/JAVA 经验的人)你看到的第一眼至少知道这是一个新玩意,并且绝对不会和 () 的那些语法混淆。

    go 吹:没关系我自己累点眼花没事,parser 千万不能受累
    artandlol
        26
    artandlol  
       2019-07-28 11:29:00 +08:00 via Android
    golang 相对于其他语言,赶紧更加严谨,所以会导致整体落后。跟苹果在很多功能方面落后安卓一个道理
    rockyou12
        27
    rockyou12  
       2019-07-28 11:40:42 +08:00
    写 python 要游标卡尺,写 go 以后要啥?啥东西数括号比较方便?
    stephen9357
        28
    stephen9357  
       2019-07-28 11:43:03 +08:00   ❤️ 1
    @reus 别杠了,Go team 是开发者的一部分,那 Golang 的使用者就不是了么?你这逻辑硬伤很严重。人家看不惯这种做法,表示反对怎么就不行了,非得 Golang 怎么做都叫好你才满意么,赶紧相互 block 吧,别瞎哔哔了,看着都尴尬。
    wo642436249
        29
    wo642436249  
       2019-07-28 11:53:40 +08:00 via Android
    看一堆人在这里争来争去,估计没有一个是在大厂工作😂
    reus
        30
    reus  
       2019-07-28 12:22:38 +08:00
    @pisc go 这个提案的泛型参数并不能 currying,如果泛型需要 A, B, C 三个类型,那特化时就必须一起传入,并不能 currying。所以你的说法不成立。
    scnace
        31
    scnace  
       2019-07-28 12:28:01 +08:00 via Android
    contract 和 try 的概念大概 18 年就被 Go Team 提出来了吧 ,现在 try 被社区否决了,contract 还能活多久🙈
    reus
        32
    reus  
       2019-07-28 12:32:20 +08:00   ❤️ 3
    @jhdxr parser 当然不能受累,编译快本来就是 go 的目标之一。别的语言不在乎编译速度,只是取舍不同,我可没有说过取舍不同就是傻叉,是你自己脑补的,别泼脏水啊。我可不是因为想吹 go 才这样说,纯粹是觉得有人傻逼,忍不住要吐槽啊。

    所有 ML 系语言都是用 (),scala 用 [],D 用 (),Haskell 也没有 <>,为啥非得为了照顾一些连基本的学习能力都没有的人,而选择一种会带来歧义和降低编译速度的语法?

    当然,如果 go team 能发现一种算法,让 <> 不需要 unbounded lookahead,我也能接受。本来就是个鸡毛蒜皮的事情,就只有菜鸡才纠结语法问题。go 连类型位置都和 C++ / java 不一样了,适应不了的人,何苦要用。
    reus
        33
    reus  
       2019-07-28 12:37:05 +08:00
    @stephen9357 “看不惯”不是什么理性的理由,不是什么技术上的理由,纯粹是一个人学习能力低下,适应能力低下的表现。不用 <> 是有技术上的理由的,你不能用非理性非技术的理由,去反驳一个技术性的理由。

    我是觉得“社区驱动”本来就是非常搞笑的事情,你社区驱动过什么了?
    hhjj3388
        34
    hhjj3388  
       2019-07-28 12:38:54 +08:00
    @jhdxr 没错··搞个() 让人混淆, 那个什么接收者也是 () 加参数() 加返回值()```````````````
    ruimz
        35
    ruimz  
       2019-07-28 12:51:46 +08:00 via Android
    @reus 这个问题同样给你,你社区驱动过什么了?你没社区驱动过就觉得搞笑?
    讨论就讨论,不要付诸人身攻击。
    congeec
        36
    congeec  
       2019-07-28 12:52:52 +08:00 via iPhone
    @trait #21 对啊。 规范和实现绑在一块儿的语言用起来就是别扭。python 是这样,js 是这样,还好 rust 已经开始移除 turbofish
    ::<>了
    reus
        37
    reus  
       2019-07-28 13:11:40 +08:00
    @trait lookahead 从来都不是问题,问题在于时间复杂度,现在 go 语法用 lalr(1) 就能解析,O(n)就能解析,引入带歧义的语法,可能连 parser generator 都不能用了,像 C++ 一样。甚至需要引入 typename 这种纯粹是为了消除歧义的东西。

    go 粉自然有傻逼,尤其是那些做培训的,本身水平就低,又整天喊“学不动”,尬吹什么大道至简。
    go 黑的傻逼,不比这些 go 粉少,一看到和自己学过的东西有一点点不同,张嘴就是 ugly,为黑而黑。你跟他说技术原因,根本理解不了,根本就懒得去理解,整天想的就是怎么“黑”。
    lynskylate
        38
    lynskylate  
       2019-07-28 13:14:24 +08:00 via Android
    @congeec ?? python 规范和实现并不是绑在一起的啊,pypy jython ironpython,python 的各种实现有哪种语言比他多?唯一诟病的只有 c 拓展,python 暴露了太多内部细节导致 c 拓展不能在各种实现中迁移罢了
    reus
        39
    reus  
       2019-07-28 13:15:10 +08:00
    @ruimz 我不知道你在说什么,“ go 是社区驱动的语言”,我认为是伪命题,语言设计,除了 go team 的人,有谁参与过? go module 更是直接否定社区的 dep。try 也不是社区“驱动”,而是社区“阻止”,毫无建设性的反对。
    reus
        40
    reus  
       2019-07-28 13:16:45 +08:00
    @congeec go 有 google go, gcc go, llvm go, tiny go, gopherjs 等等实现,规范和实现不绑定
    reus
        41
    reus  
       2019-07-28 13:19:09 +08:00
    @ruimz 我点进这个主题,本来也是想有技术上的讨论,谁知道看到一些菜鸡在那里拿些鸡毛蒜皮就说什么“这么菜”,“蛇精病”,实在忍受不了这些为黑而黑的人。
    liulaomo
        42
    liulaomo  
       2019-07-28 13:31:39 +08:00
    @reus

    > “ go 是社区驱动的语言”,我认为是伪命题,语言设计,除了 go team 的人,有谁参与过? go module 更是直接否定社区的 dep。try 也不是社区“驱动”,而是社区“阻止”,毫无建设性的反对。

    这个不完全对。很多人都参与,但基本上都被 Go team 给否决了, ;D
    liulaomo
        43
    liulaomo  
       2019-07-28 13:35:48 +08:00
    其实不用<>可以理解,但是不用[],就有点难以理解了。难道要和内置范型走两条路线?
    liulaomo
        44
    liulaomo  
       2019-07-28 13:41:28 +08:00
    @reus 其实说“ go 是社区驱动的语言”,并不为过。虽然语言本身基本上都是 Go team 设计的,但是 Go 能走到今天,离不开很多关键社区项目选择了 Go,也离不开众多 contributors 提出的众多 issues。其实 Go 在某些方面并不是和现在很多使用了 Go 开发的项目,Go 只是一个在当时相对比较好的选择。Go 能走到今天,得感谢这些项目的选择(相互感谢吧)。
    reus
        45
    reus  
       2019-07-28 13:45:23 +08:00
    @liulaomo 绝大部分都是水平不够,社区从来没有人能提出像这个泛型提案这种篇幅的完整设计。但就算设计好了,甚至实现了,像 dep,问题解决得不好,也同样会被官方否决。社区能参与的,也就对官方设计提提建议,或者 vendor 这种改动小的。
    Hellert
        46
    Hellert  
       2019-07-28 13:45:43 +08:00
    现在的错误处理可以接受,泛型有没有也无所谓,啥时候把内置十进制小数 decimal 类型提上日程啊,写财务类的程序没有这个真是麻烦死。
    reus
        47
    reus  
       2019-07-28 13:48:50 +08:00
    @liulaomo 那是对“ go 生态”的驱动,我前面说的其实是对“ go 语言”本身的驱动。我挺讨厌拿“社区”来绑架官方对语言的设计的人,自己一时不适应,甚至根本未完全理解一个设计,就提出反对
    liulaomo
        48
    liulaomo  
       2019-07-28 13:51:00 +08:00
    @reus 有很多小的提案,至少我本人感觉不错,但基本都被 Go team 否决了。

    btw,你觉得这个范型提案如何: https://www.v2ex.com/t/586881
    pisc
        49
    pisc  
       2019-07-28 14:48:25 +08:00 via Android
    @reus 你居然用 ML、Haskell 举例。。。要用<>还是()说实话根本不要紧,不过就是考量怎么不显式用∀来引入 type variable 而已。

    > 泛型就是以类型作为参数,既然是参数,那放在括号里,有什么问题? T(int) 就是以 int 为参数,特化出一个新的类型。

    这是你的原话,我不是说 type level 之间是 currying 的,我说的是如果真像你说的,int 是很 trivial 的参数的话,为什么 type level 和 value level 之间是 currying 的,也就是 application 的时候是 T(int)(a, b)而不是 T(int, a, b),为什么?不就是 type parameter 和 value parameter 在 golang 并不是那么 trivial 的关系么,所以为什么()不见得比[]或<>好的原因,因为是不同的 level,用相同的符号是很容易有歧义的。

    你要是像其他语言 type variable 和 value variable 都可以当作普通变量调用和传递,那当然没问题了,你又举了 haskell 的例子,haskell 用个毛的<>,haskell 本身就是 separated annotation 而且可以直接写∀,当然不用考虑这些幺蛾子了。
    pisc
        50
    pisc  
       2019-07-28 14:53:12 +08:00 via Android
    @reus > 我是觉得“社区驱动”本来就是非常搞笑的事情,你社区驱动过什么了?

    要是没有大把学习能力差、品味奇葩、张口闭口大道至简的 go 用户组成的社区,你 go 这破烂玩意儿能火?
    reus
        51
    reus  
       2019-07-28 15:18:22 +08:00 via Android
    @pisc 因为类型参数不是函数签名的一部分,所以放不同的括号。可以理解成两次“调用”,一次做特化,一次调用特化后的函数。阅读时就可以这样类比理解,而不是一看到没用<>就说什么不好读。我举例是想说明,不是每一门有泛型的语言都用<>,别扭曲我的原意。

    我十分希望 go 不要火,不要吸引培训机构,不要有脑残粉,不要惹上你这样的(消音)黑。
    tairan2006
        52
    tairan2006  
       2019-07-28 16:58:41 +08:00
    `<>`这个是不是会降低编译速度呀,虽然语法本身无所谓的
    duanquanyong
        53
    duanquanyong  
       2019-07-28 17:36:38 +08:00
    @tairan2006 语法也有所谓的, `<>` 是有歧义的,可以单独出现,作为小于号或者大于号
    GM
        54
    GM  
       2019-07-28 17:48:27 +08:00
    @xfriday
    作为一个 Go 用户,对 Go 的一部分设计有意见还不允许我发表了?真有意思。
    我发表这个观点收你钱了?这句话还给你。
    dbskcnc
        55
    dbskcnc  
    OP
       2019-07-28 19:43:58 +08:00
    吵得是挺热闹的,但是似乎没 get 到重点
    在 go 语言的设计原则下(简单不烧脑,便于工程实践,性能基本够用),增加泛型确实不是个轻松的事情,现有的其它语言解都有这样或者那样的弊端。

    目前这个至少是衡量了各方面限制做出的一个可行解,放出来,经过各路神仙打磨,可用性还算是可以的,至少通用数据结构和算法库可以跟上当前编程语言界的水平

    对于对此方案的各种意见,其实也只是我们各种 go 粉或者 go 黑的自 high 罢了,以 go team 浸淫计算机编程数几十年的功力,人家确实都懒得搭话,毕竟差距就是那么大,简单点就我们项目开发时一些新手的技术选型提议,多数只是天真的人云亦云罢了,真的很难有深刻的思考和实践
    darknoll
        56
    darknoll  
       2019-07-29 09:12:15 +08:00
    @GM 爱用用,不用滚。
    neoblackcap
        57
    neoblackcap  
       2019-07-29 10:43:01 +08:00
    @dbskcnc golang 作者原先就吐槽 C++的编译速度,因此他们坚持不能降低编译速度这个逻辑是自洽的。当然大家觉得好不好就另外一说。

    不是说 go team 的经验足就代表他们比提案者厉害,有压倒性优势。大家都是受现代编译语言影响的人,提案者可不单单代表自己的知识储备,他还受这个业界最新的 PL 研究,多年来的 PL 实践影响。因此片面说其他人水平不够高是让人难以理解的。

    其实不要说那么多,就是他们的追求跟大众的追求不协调而已。他们追求编译快速,自己觉得简单使用的语言,逻辑自洽。但是这说出来大家能接受吗?语言动了根本追求,哪怕是能做啊,那不就打了自己的脸?这才是根本问题。
    laumm1314
        58
    laumm1314  
       2019-07-29 11:09:49 +08:00
    范型怎么设计都不可避免其复杂性,go 引入范型是必须的么?
    judeng
        59
    judeng  
       2019-07-29 11:18:03 +08:00
    @jhdxr 为什么要用于 F<T>?
    (对于有 C++/JAVA 经验的人)你看到的第一眼大概就能猜到这是什么东西。
    (对于没有 C++/JAVA 经验的人)你看到的第一眼至少知道这是一个新玩意,并且绝对不会和 () 的那些语法混淆。
    -----------------------
    如果是仅这个原因,我觉得 parser 更简单点好
    dbskcnc
        60
    dbskcnc  
    OP
       2019-07-29 11:18:54 +08:00
    @neoblackcap
    1. 编译速度这个真的很有竞争力,使用 C++编译过大一点的系统,那感觉真的是解放(如果加上 go mod 的方便,那感觉就更不一样),当然也会有人指责说生成代码优化得不够好
    2. go team 的人也不是原地踏步好不好,秒杀绝大部分人是没有问题的,当然三个臭皮匠顶个诸葛亮,go team 目前至少面上还是做了集思广益的工作
    3. 这个很中肯,以目前 go 的水准,已经符合不少实际需要, 只是不少人也喜欢花衣裳
    araraloren
        61
    araraloren  
       2019-07-29 14:18:08 +08:00
    感觉这里好多人都是咸吃萝卜淡操心,你是个语言的使用者,自然是怎么方便怎么来
    简单即是复杂,parser 复杂不复杂和你们有多少关系??
    reus
        62
    reus  
       2019-07-29 22:41:06 +08:00   ❤️ 1
    @araraloren 怎么没关系?编译时间变长,开发体验就下降了。原本 O(n) 跑完 parse 部分,现在可能要 O(n ^ 3),能忍?!
    前段时间 cloudflare 被一个正则匹配搞挂一大片,你不要以为 parser / recognizer 真的是什么“自动化流水线模块”,文法不好处理,parser 分分钟榨干你的 CPU !
    C++之前有近十年的时间,是不能连写 >> 的,一定要加个空格写成 > >。好处理的话,从一开始就不会出现这种问题。何况,() 和 <>,真的能分出谁方便谁不方便?
    lxml
        63
    lxml  
       2019-07-31 02:50:41 +08:00
    go team 感觉截止到目前为止,感觉设计方案上没啥大坑,毕竟老头子们见得多了
    liulaomo
        64
    liulaomo  
       2019-07-31 09:53:04 +08:00
    @lxml 老头子们基本都退了,现在是年轻人操盘。Rob Pike 是相当抵触 type alias 的。
    reus
        65
    reus  
       2019-08-02 10:01:33 +08:00
    @liulaomo Robert Griesmer 是老头子,Ian Lance Taylor 也是老头子,年轻人做 runtime,老头子设计语言
    liulaomo
        66
    liulaomo  
       2019-08-02 23:34:53 +08:00
    @reus Robert Griesmer 和 Ian Lance Taylor 俩人应该都没到 60,还算中年吧。;)
    不过现在貌似 Russ Cox 的话语权最大。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1074 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 19:19 · PVG 03:19 · LAX 11:19 · JFK 14:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.