【问题标题】:Convert byte array of ASCII numeric characters to int using GO language使用 GO 语言将 ASCII 数字字符的字节数组转换为 int
【发布时间】:2015-02-01 23:12:16
【问题描述】:

我看到了一些与我遇到的完全相同的问题的答案:如何在 GO 编程语言中将字节数组转换为 int?

我写了下面的函数来将字节数组转换为int

func convertByteToInt(in []byte) int32 {
    return  (int32(in[0]) << 24 | int32(in[1]) << 16 | int32(in[2]) << 8 | int32(in[3]))
}

在此之前,我确保字节数组具有正确的(基数 256)值。 in[0] = 54(ASCII 表示 6), in[1] = 54(ASCII 表示 6), in[2] = 49(ASCII 表示 1), in[3] = 49(ASCII 表示 1)。

所以我希望从字节数组中检索整数 6611 值,但我最终得到了 909521201。我无法理解在如此简单的转换中到底发生了什么。 有人可以闪光吗?

谢谢

【问题讨论】:

  • 您有一个整数,格式为 [] 字节中的十进制数字字符串。将您的 []byte 转换为字符串并使用 strconv.Atoi 和朋友。 Bitfiddling 在这里完全是无稽之谈。 (不值得回答。)

标签: arrays go type-conversion int


【解决方案1】:

@Volker 在他的评论中是正确的,你的数组中没有 binary 数字,你有一个 ASCII 字符串。但是,您尝试将其解码为二进制。请注意,如果您正在处理二进制数,则无需验证任何输入(可能除了长度),因为所有单字节值都是有效的。

@Ainar-G 提供了一种将 ASCII 数字转换为整数的方法。

比较这两种方法:(http://play.golang.org/p/_wufZ4P_aE)

buf := []byte{54, 54, 49, 49}

x, _ := strconv.Atoi(string(buf))
fmt.Println(x)

这打印出6611;但是看看这个:

var y int32
_ = binary.Read(bytes.NewReader(buf), binary.BigEndian, &y)
fmt.Println(y)

这打印出 909521201,这正是您得到的(并且没有预料到的)。附带说明一下,您将其手动解码为 BigEndian,所以这不是“如此简单的转换”,因为还有更多因素需要考虑。

您从 ASCII 手工制作的转换大致如下所示:

var x int32
for _, c := range in {
    x = x*10 + int32(c - '0')
}
return x

但是使用strconv 是可行的方法。

【讨论】:

    【解决方案2】:

    将您的字节转换为字符串并使用strconv.Atoi

    b := []byte{54, 54, 49, 49}
    s := string(b)
    i, err := strconv.Atoi(s)
    if err != nil {
        panic(err)
    }
    fmt.Println(i)
    

    游乐场:http://play.golang.org/p/NiobWHZ9gd

    【讨论】:

    • 感谢您的回答。我得到了它与这些一起工作。考虑在 GO 中需要这种转换,是不是因为 GO 是“严格类型”语言,所以像 C 中的类型转换(通常使用 void *)在这里是不可能的?因为字节数组类似于 C 中的 char*/char[],通常用作发送/接收缓冲区。
    • @Yogi,检查我的答案。
    【解决方案3】:

    添加到@tomasz 的答案,如果您想以二进制格式存储数字并且不关心字节序,您可以使用指针:

    b := []byte{239, 190, 173, 222}
    v := *(*uint32)(unsafe.Pointer(&b[0]))
    fmt.Printf("0x%X\n", v)
    fmt.Printf("%v", *(*[4]byte)(unsafe.Pointer(&v)))
    

    playground

    【讨论】:

      【解决方案4】:

      如果您只需要转换 []byte 中的简单正值 int,如本例中的 []byte{'6', '6', '1', '1'}[]byte{54, 54, 49, 49}(相同),则为一个非常简单的 for 循环在[]byte 上添加int,就可以了,就像这样:

      var (
          myInt, i int
          myBytes = []byte{'6', '6', '1', '1'}
          v byte
      )
      for ; i < len(myBytes); i++ {
                  v = myBytes[i] - '0'
                  myInt *= 10
                  myInt += int(v)
      }
      

      ...仅此而已。

      查看Playground中的完整工作代码

      【讨论】:

      • 您能否详细说明v = myBytes[i] - '0' 是如何计算的?这实际上是做什么的?谢谢
      • 当然,如果您看到 ASCII 表,您就会明白这一点。减去 ASCII '0'(十进制 48)从字节值中减少 48。在上面的示例中,ASCII '6' 实际上是字节 54,如果将字节直接移动到 v 它将具有字节的十进制值 54,但您正在寻找 int 值 6 而不是 54 对吗?那么你必须减去它的零值(ASCII '0' - 十进制 48) 54-48=6 这是 int。字节54的值,在操场上玩一点,它会变得更清晰。
      猜你喜欢
      • 2014-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-31
      • 2023-03-24
      • 2011-08-06
      相关资源
      最近更新 更多