有想参与 go 开源项目的吗?有一个简单但好玩的,实现 go 泛型 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
ChristopherWu

有想参与 go 开源项目的吗?有一个简单但好玩的,实现 go 泛型

  •  3
     
  •   ChristopherWu 2020 年 6 月 18 日 4025 次点击
    这是一个创建于 2136 天前的主题,其中的信息可能已经有所发展或是发生改变。

    等不及 go 泛型发布,我先实现了(类似 C++ 的 template )

    https://github.com/PioneerIncubator/betterGo 这个项目就是我带着一位师弟实现的,有兴趣的同学一起开发哈~

    betterGo

    Better Go implement parts that I think Golang missed

    Real Generic

    Provide the real interface{} to you so that you can use it in your code. Before deployment, just use translator to generate specify type code, in which way will not affect your performance.

    Here are all generic functions:

    • enum.Reduce
    • enum.Map

    Implementation

    Use go ast to analyse your code where using generic functions, generate specify function for your types and replace your original call.

    What I actually do

    I do this shit for you :P

    betterGo

    Join Us

    Background

    现在的 Go 语言不支持泛型(像 C++中的 template 、Java 中的 interface )

    目前,为实现泛型的需求,在 Go 语言中往往有如下几种方式<sup>1</sup>

    1. Interface ( with method ) 优点:无需三方库,代码干净而且通用。 缺点:需要一些额外的代码量,以及也许没那么夸张的运行时开销。
    2. Use type assertions 优点:无需三方库,代码干净。 缺点:需要执行类型断言,接口转换的运行时开销,没有编译时类型检查。
    3. Reflection 优点:干净 缺点:相当大的运行时开销,没有编译时类型检查。
    4. Code generation 优点:非常干净的代码(取决工具),编译时类型检查(有些工具甚至允许编写针对通用代码模板的测试),没有运行时开销。 缺点:构建需要第三方工具,如果一个模板为不同的目标类型多次实例化,编译后二进制文件较大。

    betterGo就是通过code generation来实现泛型

    如何使用

    如果你想使用 betterGo 来通过自动生成代码的方式实现泛型,可以看下面的例子:

    在项目中包含了测试用例,例如,需要使用泛型的代码是test/map/map.go,如果想用interface{} 的函数就是enum.Map 这样子用。

    如果想生成具体类型的函数,就运行这行命令:go run main.go -w -f test/map/map.go

    然后你发现 test/map/map.go 改变了,enum.Map 变成了: enum.MapOriginFn(origin, fn)

    然后你看项目目录下生成了: utils/enum/map.go,就是具体类型的函数

    参与项目

    如果想和我们一起完成项目的开发,可以直接看代码,然后看到 ast 相关的包,就简单进去看看,猜猜什么意思,应该就可以理解这个项目以及代码了。

    如果想从理论出发的话,可以简单看看这本书: https://github.com/chai2010/go-ast-book,其实他也就是把 ast 包里的代码简单讲讲。

    想参与具体开发的话,又没有想改进的地方,可以看看项目接下来的TODO List

    技术思路

    1. 导入需要操作的文件,可以是文件 /目录

    2. 通过 AST 进行语法分析

      AST 能分析出每条语句的性质,如:

      • GenDecl (一般声明):包括 import 、常量声明、变量声明、类型声明
      • AssignStmt(赋值语句):包括赋值语句和短的变量声明(a := 1)
      • FuncDecl(函数声明)
      • TypeAssertExpr(类型断言)
      • CallExpr(函数调用语句)
    3. 当分析到包含变量的值 /类型的语句时(AssignStmtFuncDecl)会对变量的值和类型进行记录,并建立二者之间的映射关系,以便于在后续环节中能够通过变量名获取变量的类型

    4. 当发现函数调用语句(CallExpr)时,会检查该函数是否为我们提供的函数,如果是,则通过上一步中记录的参数名对应的类型生成专门处理该类型的一份代码,并存储到指定路径下(如果之前已经生成过相同类型的代码则不重复生成)

    5. 将原代码中的原来的函数调用语句替换成新的函数调用语句,使其调用上一步中新生成的函数,并更新 import 的包

    Reference

    [1] Go 有什麽泛型的实现方法? - 达的回答 - 知乎
    11 条回复    2020-06-23 15:23:28 +08:00
    zzzzeno
        1
    zzzzeno  
       2020 年 6 月 18 日
    山老师!永远滴神!
    ChristopherWu
        2
    ChristopherWu  
    OP
       2020 年 6 月 18 日
    @zzzzeno 别水贴,讲讲参与开发的感觉体验
    fiypig
        3
    fiypig  
       2020 年 6 月 18 日
    能力有限 ,支持一下
    zzzzeno
        4
    zzzzeno  
       2020 年 6 月 18 日
    我是小菜鸡师弟,项目之前就是我和山老师两个人一起在搞。讲道理我觉得项目的 idea 超酷
    Jirajine
        5
    Jirajine  
       2020 年 6 月 18 日
    这不就是 monomorphization 么,缺点是不够动态和体积疯涨,好处是零开销。
    ChristopherWu
        6
    ChristopherWu  
    OP
       2020 年 6 月 18 日
    @Jirajine 对,才知道`Monomorphization means generating specialized versions of generic functions.`
    ccpp132
        7
    ccpp132  
       2020 年 6 月 18 日
    我觉得不如像 java 那样编译期检查+运行时擦除类型信息用同一份 code 。
    Go 的性能还不值得 C++ Template 的搞法。
    ChristopherWu
        8
    ChristopherWu  
    OP
       2020 年 6 月 18 日
    @ccpp132 那要发明新语法,对于没有影响力的人,很难真正流行出去的,哈哈。
    现在我这个方法是折中,提供两份版本,语法没有任何变动。
    OakScript
        9
    OakScript  
       2020 年 6 月 18 日
    可以理解成把 linker 的部分通过集成到 go generate 的方式生成代码来做?感觉应该是没啥问题的,除了代码体积膨胀之外
    ChristopherWu
        10
    ChristopherWu  
    OP
       2020 年 6 月 18 日
    @OakScript 对的,是这样子。
    chai2010
        11
    chai2010  
       2020 年 6 月 23 日   1
    我就是那个把 ast 包里的代码简单讲讲的《 Go 语法树入门开启自制编程语言和编译器之旅》作者。

    其实作者这类工作都是基于 ast 做再处理,gofmt 和 golint 检查也是基于 ast 做分析。
    甚至基于 ast 可以扩展出新的语法来,比如七牛面向数据科学语言的 Go+语言。

    当然,为了写这个书,我们也定制了一个凹语言:目前已经是一个可以嵌入 Go 语言的脚本语言,
    也是基于 Go 语言的 ast 定制,在语言的基本功能完成之后我们会公开代码。

    欢迎关注 https://github.com/chai2010/go-ast-book
    关于     帮助文档   自助推广系统     博客     API     FAQ     Solana     1116 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 55ms UTC 18:13 PVG 02:13 LAX 11:13 JFK 14:13
    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