为什么去看兽医报告uint(0)可能太小而不能换63?

时间:2016-04-04 02:39:58

标签: go

The Go Programming Language book,练习6.5,作者告诉我们使用这个表达式:

32 << (^uint(0) >> 63)

检查平台是32位还是64位。

表达式非常清楚,我们可以使用简单的代码检查结果:

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会向我显示警告?我该如何预防?

2 个答案:

答案 0 :(得分:2)

这是因为uint不是固定的按位长度类型,它可能短到32位,所以不足以让你右移63。

这也是您可以使用此表达式测试平台的原因,因为uint将采用平台上最高效的int类型。

如果在32位平台上,uint的长度为32位,那么右移将提供0,这导致32最终成为{32 << 0的结果1}}。但是在64位平台上,uint给出了64位,因此右移63位会给你1而不是0,最终导致64由于32 << 1提供64

看一下兽医的源代码:

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      }

也就是说,只要您使用uint并右移63位,go vet检查shift,就无法逃脱检查。你可以尝试通过提供要检查的标志来跳过它:

go tool vet -shift=false yourfile.go

答案 1 :(得分:1)

  

为什么去看兽医告诉我这个警告?我该如何预防?

nevets的答案提出:

  

你可以尝试通过提供要检查的标志来跳过它:

go tool vet -shift=false yourfile.go

但是:你不应该使用go tool vet。只有1个}}。或者在这种情况下,只是因为你需要传递一个标志。

然而,从1.10开始(2018年第一季度),这将改变:见this thread

  

请勿使用“go vet”,这对于go tool vet 的工作人员基本上只有用处(就像您通常不会运行“vet一样“)。

     

以前您需要使用“go tool compile”,如果您想控制兽医旗帜,但go tool vet”现在接受“go vet”所有的标志。 (参见“go tool vet”。)

所以go help vet就足够了。