The Go Programming Language
› http://golang.org/
› Go Playground
Go Projects
› Revel Web Framework
Trim21

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

  •  
  •   Trim21 ·
    Trim21 · Jul 9, 2022 · 3195 views
    This topic created in 1577 days ago, the information mentioned may be changed or developed.

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

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

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

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

    19 replies  •  2022-07-18 02:06:49 +08:00
    pastor
    pastor
    Jul 9, 2022
    1
    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
    Trim21
    OP
    Jul 9, 2022
    2
    @pastor #1 go 的向后兼容是不包括使用了 unsafe 包的情况的。
    pastor
    pastor
    Jul 9, 2022
    3
    @Trim21 #2
    原来如此,那可能自动化指定版本比较好了,go 发新版了就新跑一次自动化看报错没,报错了 OP 更新兼容性。github action 里指定版本,或者 action 定时任务每天跑一次 go 最新版,有问题了就提示
    realpg
    realpg
    Jul 9, 2022
    4
    我没搞明白你的逻辑
    你既然没用泛型,那么你为啥要测试泛型兼容度
    如果你想测试的是,go1.18 加了泛型以后,是不是内存分配机制变化了,导致你的 unsafe 的 ptr 操作会不会造成意外的后果
    你可以直接把你本地的 go mod 改成 1.18 编译,然后跑一遍单元测试
    Trim21
    Trim21
    OP
    Jul 9, 2022
    5
    @realpg #4 是的,我怕 go 的内部实现变了我的程序就挂了。

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

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

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

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

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

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

    今天看 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
    Trim21
    OP
    Jul 18, 2022
    19
    所以这个问题的解就是,把 go.mod 写成最新的版本,然后把对应的测试文件加上 build tag 保证旧版本的 go 编译器不会运行这些测试就可以了 - -
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   5391 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 64ms · UTC 02:14 · PVG 10:14 · LAX 18:14 · JFK 21:14
    ♥ Do have faith in what you're doing.