[golang 语言] 为啥在 golang 中不支持将 bool 强转成 int?

15 天前
 Charlie17Li

引言

今天写代码,发现bool不能直接强转成int,这就导致如下代码编译错误

type Status int
const StatusSuccess Status = 1
...

status := StatusSuccess
succ += int(status == StatusSuccess)

这种在其他语言,例如 c++看起来非常自然的强转为啥 golang 不支持呢?

第二个问题

于是开始 Google,搜到这篇博客,作者用了 7 中方法实现 bool 转 int ,这里摘抄几个。

方法 1

func boolToInt(b bool) int {
    if b {
        return 1
    }
    return 0
}

方法 2

func Bool2int(b bool) int {
    // The compiler currently only optimizes this form.
    // See issue 6011.
    var i int
    if b {
        i = 1
    } else {
        i = 0
    }
    return i
}

方法 7

func fastBoolConv(b bool) int {
    return int(*(*byte)(unsafe.Pointer(&b)))
}

性能对比

way 1 6449ms
way 2 2868ms
way 3 6378ms
way 6 7268ms
way 7 2987ms

尝试去看方法 2 为啥比方法 1 快,但是没有看懂,有大佬能解释下吗,issue 6011

4598 次点击
所在节点    Go 编程语言
59 条回复
minami
14 天前
这编译器优化能力也太逆天了。。。难怪那么多人黑
aloxaf
14 天前
@mainjzb lz 说的是强转,你这是隐式类型转换
whyso
14 天前
因为你先入为主
dyllen
14 天前
我搞这么多年,没印象在那里需要用到这种特性。
sunny352787
14 天前
能转才不正常吧? C/C++那种对 bool 进行++或者其他计算的操作逻辑意义是啥? bool 就是 bool ,真或假,凭什么假的加 1 就变真了? 0 凭什么就是假的?那我负数为啥又是真了?类型该是啥就是啥,别瞎用。以前写 C++的时候碰到有人给 bool 做数值运算我一定要喷到他以后再也不敢。逻辑就是逻辑,数值就是数值,混用你不出错就怪了。
fffq
14 天前
没必要
fffq
14 天前
语义也变得不明确了,得不偿失
body007
14 天前
防御性编程必备操作,怎么到 Go 这里就行不通了。
aloxaf
14 天前
@povsister 内存布局不一样咋就不能强转了,go 不是照样允许 int32 转 float64 么。

而且就一个 bool 到 int 的强转而已,和你下面说的东西都没啥关系,某些连 i32 -> i64 的隐式转换都不允许的语言照样也允许 bool 强转 i32 。
Charlie17Li
14 天前
@sir283 c++的 bool 实际细节大小和 int 不一样,而且 int 可以直接赋值给 bool
FalconD
14 天前
我不到啊 建议写 if cond {1} else {0}, 感觉还不如 cast
securityCoding
14 天前
大哥,我求你们别搞这些花里胡哨的写法了好吗? 还嫌 c++不够脑残是吧
grzhan
14 天前
发现自己贴错了 issue: https://github.com/golang/go/issues/64825 ( x
这个讨论还提到一个点,就是常量,现在常量由于这个类型转换的限制可能对于同个常量会写两个类型( bool/int ),这在 Go 编译器和运行时的代码里就有出现( src/internal/goexperiment/exp_arenas_on.go ):

const Arenas = true
const ArenasInt = 1

总之这事目前来看没有明确拒绝的理由,更接近于懒得搞,如果有人愿意费力气把这变更做了,感觉 Go 团队这边也会接受。

(其实这种类似的情况在 Go 社区有很多,习惯就好)
FalconD
14 天前
语言是否允许 cast bool → Integer 和 op 的用例不合理是两回事
写 if succ then sc += 1 很好
Ver. 1 和 Ver. 2 有差异只能说编译器乐色
LcDraven
14 天前
@mainjzb if(1 == a)这样写可以避免
dyllen
14 天前
@Kisesy Benchmark 测试没区别呀
aloxaf
14 天前
@sunny352787 坏了,我搜了一下,linux 内核中少说也有几百处 bool 参与数值运算代码

移位的: https://github.com/torvalds/linux/blob/master/sound/soc/codecs/wsa881x.c#L912
按位或: https://github.com/torvalds/linux/blob/master/arch/arm/mach-omap2/display.c#L310
相加的: https://github.com/torvalds/linux/blob/master/arch/arm64/kvm/arm.c#L308
相减的: https://github.com/torvalds/linux/blob/master/arch/arm64/kvm/vgic/vgic.c#L262 (这里虽然用到了强制类型转换,但在某些人看来应该同样罪大恶极)
相乘的: https://github.com/torvalds/linux/blob/master/net/sctp/sm_make_chunk.c#L3689
…… 太多了,更本数不清
aloxaf
14 天前
本来就是个正常的需求,说有取舍也就算了,非要把它批倒批臭。
泛型的事情过去才几年啊,忘啦?那个 proposal 还挂在 issues 上,天天地盯着你们啊!
DOLLOR
14 天前
建议用 if (status == StatusSuccess) succ += 1 形式,语义上更清晰。
qW7bo2FbzbC0
14 天前
go 编委会喜欢打脸,前期各种不方便之处被各种网红文举说成优点和取舍,泛型就是其中之一

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1088998

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX