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

请教一个问题,一个 go1.17 的库要怎么测试泛型是否正常工作?

  •  
  •   Trim21 ·
    Trim21 · 2022-07-09 15:53:34 +08:00 · 2281 次点击
    这是一个创建于 879 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近写了个 golang 的库,我没有用到泛型也不需要泛型,所以就在 go.mod 里面写了 go 1.17

    但是因为用到了 unsafereflect 这些直接操作了内存,所以有必要测试一下 1.18 的泛型能不能正常工作。

    但是因为我在 go.mod 里面写的版本要求是 1.17 ,所以不能使用泛型语法。 //go:build go1.18 之类的条件编译也不能解决这个问题,因为 go.mod 里面写的还是 1.17 ,所以就算泛型测试在 go1.18 下才会运行,还是不能用泛型语法。

    难道只能额外加一个文件夹,额外写一个 go.mod 用 replace 指向我的库的位置,然后用在 ci 里用多个 go 版本跑我的库的测试和这个额外的文件夹里的 go1.18 测试?

    19 条回复    2022-07-18 02:06:49 +08:00
    pastor
        1
    pastor  
       2022-07-09 16:07:33 +08:00
    go 向后兼容,比如 1.18 的 go 兼容 1.17 及更低版本的 go 的代码,并不是说 mod 里你声明了 1.17 就只能用 1.17 ,而应该是最低要求 1.17 的 go ,但是 1.18 也是可以用你的库的,所以你只要用 1.18 的 go 测试你的库 ok 就可以了

    如果 OP 的库不是依赖 1.17 相比于低版本 go 新增的新特性,OP 甚至可以考虑把 mod 里指定更低的 go 版本

    我只是喜欢 go ,自己实际项目用 go 的占比不是最多所以不敢确定对错,请 OP 实操为准
    Trim21
        2
    Trim21  
    OP
       2022-07-09 16:11:14 +08:00
    @pastor #1 go 的向后兼容是不包括使用了 unsafe 包的情况的。
    pastor
        3
    pastor  
       2022-07-09 16:21:03 +08:00
    @Trim21 #2
    原来如此,那可能自动化指定版本比较好了,go 发新版了就新跑一次自动化看报错没,报错了 OP 更新兼容性。github action 里指定版本,或者 action 定时任务每天跑一次 go 最新版,有问题了就提示
    realpg
        4
    realpg  
       2022-07-09 16:40:19 +08:00
    我没搞明白你的逻辑
    你既然没用泛型,那么你为啥要测试泛型兼容度
    如果你想测试的是,go1.18 加了泛型以后,是不是内存分配机制变化了,导致你的 unsafe 的 ptr 操作会不会造成意外的后果
    你可以直接把你本地的 go mod 改成 1.18 编译,然后跑一遍单元测试
    Trim21
        5
    Trim21  
    OP
       2022-07-09 17:06:54 +08:00
    @realpg #4 是的,我怕 go 的内部实现变了我的程序就挂了。

    这样的话没法 commit 测试文件到仓库里。
    realpg
        6
    realpg  
       2022-07-09 17:07:52 +08:00
    @Trim21 #5
    额 为啥要 commit 仓库
    你本地连个单元测试都不能跑?
    pastor
        7
    pastor  
       2022-07-09 17:17:31 +08:00
    @Trim21 #5
    github action 定时任务,隔一段时间用最新的 go 跑一次测试,如果测试失败了仓库的 actioin 里会有失败的。再加上 slack/discord 机器人,你就能及时收到通知然后自己去做新版本兼容了。

    或者自己弄 cicd 的钩子也行。
    Trim21
        8
    Trim21  
    OP
       2022-07-09 17:20:07 +08:00
    @pastor #7 我一开始也是这样想的,但是这么搞的话本地测试有点麻烦 - -
    pastor
        9
    pastor  
       2022-07-09 17:47:58 +08:00   ❤️ 1
    @Trim21 #8
    本地也还好,go 自带安装管理多版本的功能,然后用对应的版本来搞,比如 `go1.10.7 test ...`,参考官方:
    go.dev/doc/manage-install

    图省事的话,自己写个脚本自动去查询、安装最新版本以及跑测试就好了,action 里也可以复用
    janxin
        10
    janxin  
       2022-07-09 18:10:37 +08:00   ❤️ 1
    本质问题是测试用例管理问题吧,只是在低版本中 skip 掉某些特殊用例而已。

    以 Github Action 为例,比如说低版本中已存在的测试用例,只需在版本列表中加入新版本即可。

    对于新的泛型测试用例,放在不用的 Go 测试项目中,只是添加一个新的 action YAML 即可。
    Trim21
        11
    Trim21  
    OP
       2022-07-09 18:24:48 +08:00
    @pastor #9 原来还能这样,那就方便多了
    Trim21
        12
    Trim21  
    OP
       2022-07-09 18:25:39 +08:00
    @janxin #10 是的,最终变成这么搞了,一个仓库里写了好几个 go.mod 。。。
    vibbow
        13
    vibbow  
       2022-07-09 19:50:13 +08:00   ❤️ 1
    @pastor golang 不是 100%向后兼容的。
    至少 SSL 这块不是。
    kappa
        14
    kappa  
       2022-07-09 20:14:23 +08:00
    用 build tag 指定呢

    ```
    // +build go1.18
    ```
    janxin
        15
    janxin  
       2022-07-09 22:37:15 +08:00   ❤️ 1
    @vibbow 不保证实现兼容,只是代码编译兼容性保证 https://go.dev/doc/go1compat
    pastor
        16
    pastor  
       2022-07-09 23:03:54 +08:00
    @vibbow 如 #15 @janxin 所说,加上楼主的问题,语言兼容性好像只是 unsafe 需要注意。这个帖子让我对 go 兼容性加深了认识,哈哈哈,感谢 OP 、各位
    Trim21
        17
    Trim21  
    OP
       2022-07-10 07:31:11 +08:00 via Android
    @kappa 不行,如果用 go1.18+编译器的话这个文件就会满足编译条件,然后因为用到了泛型语法就会报错。
    Trim21
        18
    Trim21  
    OP
       2022-07-18 02:05:28 +08:00
    时隔一个星期后的更新。

    今天看 zap 的代码才发现,自己理解错 go.mod 文件中这个 go 版本号的含义了。其实 go.mod 里面填的 go 版本并不会限制下游用户使用的 go 版本,甚至不会限制库开发者用到的 go 版本... 就算 go.mod 写了 N ,只要没用到 go N 引入的新特性,照样可以用 N-1 版本的编译器来开发和测试,甚至运行。甚至 go mod 写了 N-1 的其他用户也是可以引入你的包的。

    比如 zap 的 go.mod https://github.com/uber-go/zap/blob/master/go.mod#L3 是写了 1.18 的,想要支持 1.17 版本,只要把所有的泛型代码所在的文件加上 build tag 就可以了...
    Trim21
        19
    Trim21  
    OP
       2022-07-18 02:06:49 +08:00
    所以这个问题的解就是,把 go.mod 写成最新的版本,然后把对应的测试文件加上 build tag 保证旧版本的 go 编译器不会运行这些测试就可以了 - -
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5709 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 02:58 · PVG 10:58 · LAX 18:58 · JFK 21:58
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.