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

一些编译时刻断言技巧

  •  
  •   liulaomo · 2019-07-13 11:41:52 +08:00 · 652 次点击
    这是一个创建于 1721 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有时候,我们希望在编译时刻就能够判断某些条件是否成立,而不是等到运行时刻报错。但是 Go 并没有提供在编译时刻直接判断某个条件是否成立的功能。那么该如何做到这一点呢?

    事实上,我们可以利用容器类型的组合字面值中的常量键值和下标不能重复这一规则来实现编译时刻断言。比如,下面这两个映射组合字面是编译通不过的:

    // error: 键值 true 重复了
    var _ = map[bool]int{true: 1, true: 2}
    // error: 键值 false 重复了
    var _ = map[bool]int{false: -1, false: 0}
    

    而下面这个是没问题的:

    var _ = map[bool]int{true: 1, false: 0}
    

    利用这一规则,我们可以在编译时刻断言任意常量表达式条件。

    用例一:有时候一个程序明确不支持 32 架构,则可以在代码中加入下面这行来防止此程序在 32 位的架构上被编译出可执行程序。

    var _ = map[bool]int{true: 1, ^uint(0) >> 63 == 0: 0}
    

    其中的^uint(0) >> 63为另外一个编译时刻的小技巧。它的估值结果在 32 位的架构上为 0,而在 64 位的架构上为 1。

    用例二:保证某个整数设置N(一个常量)必须大于等于另一个整数设置M(也是一个常量)。

    var _ = map[bool]int{true: 1, N >= M: 0}
    

    用例三:保证某个常量字符串S不为空。

    var _ = map[bool]int{true: 1, len(S) == 0: 0}
    

    上面几个用例都比较简单,在实践中,被断言的条件可以很复杂,只要此条件可以在编译时刻被估值即可。

    其实,对于上面第二个和第三个用例,它们各自还有若干编译时刻断言方法。比如,对于第二个用例,我们可以使用下面的各个方法来断言整数设置N大于等于另一个整数设置M

    func _(x []int) {_ = x[N-M]}
    func _(){_ = []int{N-M: 0}}
    func _([N-M]int){}
    var _ [N-M]int
    const _ uint = N-M
    type _ [N-M]int
    var _ uint = N/M - 1
    

    对于第三个用例,我们也可以使用下面的各个方法来断言一个字符串常量不为空。

    var _ = map[bool]int{false: 0, S != "": 1}
    type _ [len(S)-1]int
    var _ = S[:1]
    var _ = S[0]
    const _ = 1/len(S)
    

    本文首发在微信 Go 101 公众号,欢迎各位转载本文。Go 101 公众号将尽量在每周发表一篇原创短文,有意关注者请扫描下面的二维码。

    101-group-qrcode-1.jpg

    关于更多 Go 语言编程中的事实、细节和技巧,请访问《 Go 语言 101 》官方网站:https://gfw.go101.org。如果官网被墙,请访问《 Go 语言 101 》 github 项目:https://github.com/golang101/golang101

    2 条回复    2019-07-13 20:58:53 +08:00
    secondwtq
        1
    secondwtq  
       2019-07-13 13:19:42 +08:00 via iPad
    C++11 有了 static_assert,方便很多
    Go 其实也可以加入类似的东西,文中方法挺 hack 的
    不过我猜 Go 设计团队应该不会认为这是一个有效的需求…
    slanternsw
        2
    slanternsw  
       2019-07-13 20:58:53 +08:00 via Android
    ugly hack....
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2839 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 14:31 · PVG 22:31 · LAX 07:31 · JFK 10:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.