一些编译时刻断言技巧 - V2EX
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 1227 次点击
    这是一个创建于 2348 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有时候,我们希望在编译时刻就能够判断某些条件是否成立,而不是等到运行时刻报错。但是 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     Solana     4465 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 10:03 PVG 18:03 LAX 02:03 JFK 05:03
    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