为什么go vet报告uint(0)的移位可能太小,只有63?

huangapple go评论75阅读模式
英文:

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 &lt;&lt; (^uint(0) &gt;&gt; 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 &quot;fmt&quot;

func main() {
	fmt.Println(32 &lt;&lt; (^uint(0) &gt;&gt; 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 &lt;&lt; 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 &lt;&lt; 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 = &quot;might be &quot;
...
78		if amt &gt;= size {
79			ident := f.gofmt(x)
80			f.Badf(node.Pos(), &quot;%s %stoo small for shift of %d&quot;, 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.

huangapple
  • 本文由 发表于 2016年4月4日 10:39:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/36393806.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定