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

2 天前
 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

4212 次点击
所在节点    Go 编程语言
59 条回复
shiyunjin
2 天前
https://0x0f.me/blog/golang-compiler-optimization/
这篇文章不是解释了吗?
编译器优化了
Kisesy
2 天前
我测了一下,go 1.23 方法 1 跟 2 好像都优化了
Trim21
2 天前
Kisesy
2 天前
@Trim21 我又看了一下,确实,刚才我用 VScode 看汇编显示不出来,现在显示出来了,方法 1 多了一个跳转
不过,测基准,差不多
wen20
2 天前
统统 cast 库转换
povsister
2 天前
先说行不行
int 和 bool ,在内存布局上就是完全不一样的,通常来说 bool 算上 padding 也不会有一个 int 那么大。
那何来“强转”一说?

再说是不是
go 的出现,就是 google 的工程师为了解决 c/c++的某些问题。包括但不限于:隐式类型转换,void*,滥用模板元编程,晦涩的 memory model 等等。但是你想做的事情又把问题带了回来。
c0t
2 天前
只是因为标准没写吧,c 倒是有 "A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.",不过 reinterpret_cast<int>(bool) 应该也不允许?
Kisesy
2 天前
最简单和优化的写法还是得看 https://github.com/golang/go/issues/6011
看来不能用 return 1 和 0 的方式,这样不优化,需要把 1 和 0 赋值给变量再返回才行
c0t
2 天前
@c0t 更具体的 https://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_conversions ,也说了,这不是 cast/conversion ,而是 integer promotion
grzhan
2 天前
我翻了下 Go 的 Github Issue ,其实有非常多人的提过这个 int(bool) proposal 。
包括今年也有关于这个的讨论: https://github.com/golang/go/issues/6011

看得出来不少 Go 团队的成员是支持加入这个特性的,主要反对的人是 rsc ,他认为这个变更工作量很大,同时觉得收益不高,Go 团队时间有限,要搞的话你们自己搞:1. spec 的变更; 2. 编译器和 go/types 的变更; 3. 把 Go 主仓库相关代码更新了以尽可能用上这个新特性,来证明这个特性对于 Go 而言是有用的。

所以感觉更接近 Go 早期版本忽视了这个特性,然后现在随着 Go 发展要加进这个特性工作量大了就懒得搞了。
Kisesy
2 天前
@Trim21 老兄,帮忙再看一下,之前测基准没啥区别,感觉是不是直接内联优化了 https://godbolt.org/z/fh7WqMvhx
mainjzb
2 天前
千万别加入这种沙雕转换。
写 C++的时候偶尔手误就会写成
if( a=b) // or (a =1 )
{
// do
}

检查一小时才能在一个角落里看到错误
sunfall
2 天前
@mainjzb 现在的编译器都会对这种错误警告的,当然,如果不关注警告另说。
realpg
1 天前
这么喜欢骚操作 还是回去 C 吧
sir283
1 天前
有没有可能,c/c++的 bool 就是 0 跟 1 ?不过是加了个 typedef ?你用 while(1){}也能实现 bool true 的功能。不要把你 JavaScript 的坏习惯带到 go 里面,更不要强行扯到 c/c++上。
kandaakihito
1 天前
@sunfall #13 很多人写代码压根不看 IDE 的警告,一打开文件右侧全是飘黄警告
bruce0
1 天前
@kandaakihito 确实是这样, 我让团队的同学都在 ide 里配置一下 golangci-lint 这个东西, 很多人不配置,还有的配置了不用,不看, 导致很多基础的,有问题的代码都提交上来了, 我发现了再去找他们, 现在 ide 和一些工具挺智能的, 很多常见的坑都能发现
lisxour
1 天前
@sunfall 项目大起来,几十个 warning 那不都很正常,只要不飘红,很少关注 warning ,无意中多一个 warning 也很难注意到
Sunzehui
1 天前
JavaScript 欢迎你,隐式转换多到飞起,爽歪歪
ferock
1 天前
好贴

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

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

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

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

© 2021 V2EX