[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 条回复
DefoliationM
14 天前
那你直接用 c++不就行了,用锤子 go
bli22ard
14 天前
int 互转 bool , 就是应该被阻止的,当你看到 if ddd 时候, 你就可以断定,ddd 是个 bool 值, 而不是还有可能是个 int 。这样不是更清晰吗?搞不到为什么要 bool 能强转 int 。c/c++代码漏洞多不是没有原因的
adoal
14 天前
搞内核和嵌入式的,会把 bool 类型拿来做各种骚操作,是因为 bool 在他们眼里是个 bit field 。

而做应用开发的“新”语言圈子里,这十来年的趋势是恶补以前对 PLT 的不重视,很强调类型系统。从语义上讲,一个 bool 的值域跟数值类型没有任何必然关系,甚至 true 和 false 不一定是 1 和 0 ,也不一定是 other 和 0 ,我记得小时候用 LASER 310 上的 BASIC 时,条件比较运算的结果,假值是 0 ,真值是-1 ,很多 BASIC 都这样的,后来刚开始学 C 时还不适应。
leonshaw
14 天前
为啥 float64 和 rune 都能转 int
sunny352787
14 天前
@aloxaf 有就说明正确吗?动动脑子自己好好想想,存在就是合理的吗?
sunny352787
14 天前
@aloxaf 别拿泛型碰瓷,从夯土锤进化到打桩机不是你用锉刀修正误差的理由
adoal
14 天前
@sunny352787 你回我的语气让我感觉有点摸不着头脑……因为不熟悉 id ,甚至一开始以为你是拿 kernel 代码来支持 bool 和 int 互转的。我的意思明明是,不同场景的需求不同,拿来写业务的,主要矛盾跟写内核和嵌入式的不一样,对 bool 的需求不是从寄存器里直接抠 bit filed ,而是更需要保证不同类型值域的语义正确。说起来咱们才是一伙的,你用反问语气怼我做什么。
adoal
14 天前
@sunny352787 sorry ,看错了,嘿嘿……原来你怼的不是我。
sunny352787
14 天前
@adoal 汗...
c0t
14 天前
@adoal c 标准里就算你用 ub 的方式改了 bool 内存位置的值,再转换还是一样的,true 1, false 0 ,因为标准里规定了这个过程的结果,标准里规定了即正确,未规定则 ub ,这就是一切 c 代码的工作方式,也是 bug 的来源,ub 太多,所以产生太容易。当然,写现代 c++的人在需要保证 memory layout 的时候肯定用各类 *cast 函数。新式语言启用这种 bool -> int cast 的也不少,rust 一样能 bool as i32
FalconD
14 天前
@bli22ard cast 和 conversion 都分不清就别来搞笑了
ugpu
14 天前
@bli22ard 应用层你这么想没问题 你需要的是语义清晰
C/CPP 本身就是底层应用多 . 对于很对硬件层的东西来说 都是 byte 字节...

正轨 cpp 程序员都会用 static_cast. 这样显示的指定是安全的
billccn
14 天前
@povsister #6 楼主的烦恼和 int 和 bool 在内存的布局其实关系不大吧,需要用这个变量的时候都是要把它读进寄存器的,不管在内存里是多长,寄存器都是至少 int 那么长的。

现在因为 golang 缺乏这个转换,还要专门写个条件判断,指令上至少一个比较+一个条件跳转+两次立即数载入,那个条件跳转还容易产生分支预测错误,整体属于掏肠子放屁。
sampeng
14 天前
这种懒还是别偷吧。。0/1 和 false/ture 本来就是两个语意的事。编译器已经告诉你了类型不匹配。这种都属于两个语意也就是两个类型的事了。。必须要求显性的进行转换没啥毛病啊。。。
allanpk716
14 天前
用 go 是希望死板一点,免得有人写出神奇的绕来绕去的代码…比如最喜欢的就是强制格式化要求…
FalconD
14 天前
@sampeng op 不是说 go 没有强转吗
meiyoumingzi6
13 天前
那么问题来了,在 bool 判断的时候 1 是 true 那么 2 呢,py 可都是认为 true
bli22ard
13 天前
@FalconD 如果你不搞笑的话,请列出,分不清 cast 和 conversion 的事实,别做个无脑的喷子。
guzzhao
13 天前
func Bool2int(b bool) int {
i :=0
if b {
i = 1
}
return i
}
这样速度比较快吧

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

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

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

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

© 2021 V2EX