英文:
Why go vet report uint(0) might be too small for shift of 63?
问题
《The Go Programming Language》书籍中的练习6.5中,作者告诉我们可以使用以下表达式来检查平台是32位还是64位:
32 << (^uint(0) >> 63)
这个表达式很清楚,我们可以用以下简单的代码来检查结果:
package main
import "fmt"
func main() {
fmt.Println(32 << (^uint(0) >> 63))
}
在32位平台上,代码输出0
,在64位平台上输出64
。
然而,当我使用go vet
命令检查这个文件时,我收到了以下警告:
$ go vet ex6-5.go
ex6-5.go:6: ^uint(0) might be too small for shift of 63
exit status 1
为什么go vet
会显示这个警告?我该如何避免它?
英文:
The Go Programming Language book, exercise 6.5, the author told us using this expression:
32 << (^uint(0) >> 63)
to check whether the platform is 32-bit or 64-bit.
The expression is quite clear, and we can check the result with a simple code:
package main
import "fmt"
func main() {
fmt.Println(32 << (^uint(0) >> 63))
}
The code print 0
on 32-bit platform and 64
on 64-bit platform.
However, using go vet
with the file, I receive the warning:
$ go vet ex6-5.go
ex6-5.go:6: ^uint(0) might be too small for shift of 63
exit status 1
Why does go vet
show me that warnings? How can I prevent it?
答案1
得分: 2
这是因为uint
不是一个固定的位长度类型,它可以是32位,所以不能满足你右移63位的要求。
这也是为什么你可以使用这个表达式来测试平台,因为uint
会在平台上选择最高效的int
类型。
如果在32位平台上,uint
是32位长度,因此右移操作会得到0
,这导致最终结果为32 << 0
的结果为32
。但是在64位平台上,uint
给出64位,因此右移63位会得到1
而不是0
,这导致最终结果为32 << 1
的结果为64
。
看一下vet
的源代码:
71 case types.Int, types.Uint, types.Uintptr:
72 // 这些类型的长度可能只有32位,但不会更小。
73 size = 32
74 msg = "可能是"
...
78 if amt >= size {
79 ident := f.gofmt(x)
80 f.Badf(node.Pos(), "%s %stoo small for shift of %d", ident, msg, amt)
81 }
也就是说,只要你使用uint
并右移63位,并且使用go vet
检查shift
,就无法避免这个检查。你可以尝试通过提供标志来跳过检查:
go tool vet -shift=false yourfile.go
英文:
This is because uint
is not a fixed bitwise length type, it could be as short as a 32 bits, so not sufficient for you to right shift by 63.
This is also the reason why you could use this expression to test the platform, since uint
would take the most efficient int
type on the platform.
If on 32-bit platform, uint
is 32-bit length, and thus the right shift would give 0
, which causes 32
in the end as the result of 32 << 0
. But on 64-bit platform, uint
gives 64-bit, and thus right shift 63 bits would give you 1
instead of 0
, which results in 64
at the end since 32 << 1
gives 64
.
Take a look at the source code of vet:
71 case types.Int, types.Uint, types.Uintptr:
72 // These types may be as small as 32 bits, but no smaller.
73 size = 32
74 msg = "might be "
...
78 if amt >= size {
79 ident := f.gofmt(x)
80 f.Badf(node.Pos(), "%s %stoo small for shift of %d", ident, msg, amt)
81 }
That is to say, as long as you are using uint and right shift by 63 bits, with go vet
checking shift
, there's no way to escape the check. You could try to skip that by providing the flag to check:
go tool vet -shift=false yourfile.go
答案2
得分: 1
为什么go vet会显示警告?我该如何防止它显示警告?
nevets的答案提到:
你可以尝试通过提供标志来跳过检查:
go tool vet -shift=false yourfile.go
但是:你不应该使用go tool vet
,而是使用go vet
。只有在这种情况下,你需要传递一个标志。
然而,从Go 1.10(2018年第一季度)开始,情况将发生变化:参见这个讨论:
不要使用"go tool vet",它基本上只对那些在开发"vet"的人有用(就像你通常不运行"go tool compile"一样)。
以前,如果你想要控制vet标志,你需要使用"go tool vet",但是"go vet"现在接受所有"go tool vet"的标志。(参见"go help vet")
因此,go vet -shift=false yourfile.go
就足够了。
英文:
> Why does go vet show me that warnings? How can I prevent it?
nevets's answer proposed:
> You could try to skip that by providing the flag to check:
go tool vet -shift=false yourfile.go
But: You should not use go tool vet
. Only go vet
. Or in this case, only because you need to pass a flag.
However, starting go 1.10 (Q1 2018), that will change: see this thread:
> Do not use "go tool vet
", which is essentially only useful to people working on vet
(just like you don't typically run "go tool compile
").
>
> Previously you needed to use "go tool vet
" if you wanted control over vet flags, but "go vet
" now accepts all the flags that "go tool vet
" does. (See "go help vet
".)
So go vet -shift=false yourfile.go
should be enough.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论