如何在Go编程中将[]byte转换为int

118

我需要创建一个TCP的客户端-服务器示例。在客户端,我读取两个数字并将它们发送到服务器。我遇到的问题是,我无法将[]byte转换为int,因为通信只接受[]byte类型的数据。

有没有办法将[]byte转换为int,或者我可以将int发送到服务器?

非常感谢提供一些示例代码。

谢谢。


只是为了澄清任务,您是要编写客户端和服务器端代码吗?它们都是用Go编写的吗? - Sonia
据我所知,您需要进行位移操作。 - fiorix
将数据发送到网络需要将其转换为字节形式。 - IanB
9个回答

130
你可以使用encoding/binary的ByteOrder来处理16位、32位、64位类型。 Play
package main

import "fmt"
import "encoding/binary"

func main() {
    var mySlice = []byte{244, 244, 244, 244, 244, 244, 244, 244}
    data := binary.BigEndian.Uint64(mySlice)
    fmt.Println(data)
}

4
你提到的"offsets"是什么意思?是指从[]byte的中间位置开始读取吗?如果是,只需要使用BigEndian.Uint64(bigSlice[10:18])(即读取切片中间的字节)。或者你是指其他内容? - David Budworth
2
嗯,我问了这个愚蠢的问题之后就明白了。只是不能编辑它 :D 谢谢。 - majidarif
7
返回的是uint16、uint32和uint64,但不是int。需要将uint转换为int。 - Tinkaal Gogoi
很明显,但一开始想要将byte[]转换为int时并不是这样的:对于byte数组非常小的情况,这种方法是无法工作的。在我的某个案例中,我有一个仅有2个元素的byte数组,而Uint64方法在源代码的这一行失败了:_ = b[7] // bounds check hint to compiler; see golang.org/issue/14808,因为显然索引超出了范围。我需要使用Uint16方法。 - ThePartyTurtle
@TinkalGogoi 使用 int64(value) 将一个值转换为 int64。 - Bill Burdick

21

如果 []byte 是 ASCII 字节数字,则首先将 []byte 转换为字符串,然后使用 strconv 包中的 Atoi 方法将字符串转换为整数。


package main
import (
    "fmt"
    "strconv"
)

func main() {
    byteNumber := []byte("14")
    byteToInt, _ := strconv.Atoi(string(byteNumber))
    fmt.Println(byteToInt)
}

Go playground


3
将int解析为字符串,然后转换为字节数组,再进行反向操作似乎是一种过于冗长的方式。 - Martin Nowosad
是的,将字节转换为整数会更便宜,但我还没有找到方法。 - Tinkaal Gogoi

13

从字节数组开始,您可以使用binary包来进行转换。

例如,如果您想要读取int类型的数据:

buf := bytes.NewBuffer(b) // b is []byte
myfirstint, err := binary.ReadVarint(buf)
anotherint, err := binary.ReadVarint(buf)

使用同一软件包,可以使用通用的Read函数读取无符号整数或浮点数,并可指定所需的字节顺序。


13
Varint是针对协议缓冲区的,可能不是您正在寻找的内容。规范:http://code.google.com/apis/protocolbuffers/docs/encoding.html - fiorix
只是为了澄清,一个32位整数在被Varint编码后可能会使用多达5个字节。 - fiorix
4
这种方法不适用于原帖提出的使用情况。请改用binary.Read()。参考:http://codereview.stackexchange.com/questions/15945/effectively-convert-little-endian-byte-slice-to-int32 - IanB

10
now := []byte{0xFF,0xFF,0xFF,0xFF}
nowBuffer := bytes.NewReader(now)
var  nowVar uint32
binary.Read(nowBuffer,binary.BigEndian,&nowVar)
fmt.Println(nowVar)

4294967295

9
math/big提供了将二进制切片转换为数字的简单易用的方法。playground
package main
import (
    "fmt"
    "math/big"
)
func main() {

    b := []byte{0x01, 0x00, 0x01}

    v := int(big.NewInt(0).SetBytes(b).Uint64())

    fmt.Printf("%v", v)
}

6

要对数字进行字节序列的编码/解码,可以使用encoding/binary包。在文档中有示例:请查看目录中的示例部分。

这些编码函数操作io.Writer接口。net.TCPConn类型实现了io.Writer,因此您可以直接写入/读取网络连接。

如果您的Go程序在连接的两端,您可能需要考虑使用encoding/gob。请参阅文章"Gobs of data",了解使用gob的演练(跳到底部以查看自包含示例)。


你能举个在TCP应用中使用gob的例子吗? - Emanuel
我已经添加了一篇描述gob的文章链接;如果您只想查看代码示例,可以跳到底部。当您构建编码器/解码器时,只需将*TCPConn作为参数传递给gob.NewEncoder / gob.NewDecoder即可。 - axw

3

使用位运算符而不需要额外依赖

func toInt(bytes []byte) int {
    result := 0
    for i := 0; i < 4; i++ {
        result = result << 8
        result += int(bytes[i])

    }

    return result
}

2
如果 []byte 数组中的字节是 ASCII 字符 0 到 9,您可以在循环中将它们转换为 int
var value int
for _, b := range []byte{48, 49, 50, 51, 52} {
    value = value*10 + int(b-48)
}
fmt.Printf("integer value: %d", value)

Go Playground

{{链接1:Go Playground}}


0

binary.Readencoding/binary 中提供了将字节数组转换为数据类型的机制。

请注意,网络字节顺序是BigEndian,所以在这种情况下,您需要指定binary.BigEndian

  package main

  import (
    "bytes"
    "encoding/binary"
    "fmt"
  )

  func main() {
    var myInt int
    b := []byte{0x18, 0x2d} // This could also be a stream
    buf := bytes.NewReader(b)
    err := binary.Read(buf, binary.BigEndian, &myInt) // Make sure you know if the data is LittleEndian or BigEndian
    if err != nil {
        fmt.Println("binary.Read failed:", err)
        return
    }
    fmt.Print(myInt)
  }

阅读此文档可能会有所帮助:https://pkg.go.dev/encoding/binary@go1.17.1#Read


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接