将整数转换为字节数组

时间:2013-06-02 23:45:04

标签: go type-conversion

我有一个接收[]byte的函数,但我拥有的是int,这个转换的最佳方式是什么?

err = a.Write([]byte(myInt))

我想我可以走很长的路,把它变成一个字符串然后把它放到字节中,但听起来很难看,我猜有更好的方法可以做到。

7 个答案:

答案 0 :(得分:42)

我同意Brainstorm的方法:假设您传递的是机器友好的二进制表示,请使用encoding/binary库。 OP表明binary.Write()可能会有一些开销。查看the source实现Write(),我发现它做了一些运行时决策以获得最大的灵活性。

   189  func Write(w io.Writer, order ByteOrder, data interface{}) error {
   190      // Fast path for basic types.
   191      var b [8]byte
   192      var bs []byte
   193      switch v := data.(type) {
   194      case *int8:
   195          bs = b[:1]
   196          b[0] = byte(*v)
   197      case int8:
   198          bs = b[:1]
   199          b[0] = byte(v)
   200      case *uint8:
   201          bs = b[:1]
   202          b[0] = *v
   ...

右? Write()接受一个非常通用的data第三个参数,并且随着Go运行时强制进入编码类型信息,这会产生一些开销。由于Write()在这里做了一些你根本不需要的运行时决策,也许你可以直接调用编码函数并查看它是否表现更好。

这样的事情:

package main

import (
    "encoding/binary"
    "fmt"
)

func main() {
    bs := make([]byte, 4)
    binary.LittleEndian.PutUint32(bs, 31415926)
    fmt.Println(bs)
}

告诉我们这是如何表现的。

否则,如果您只是想获取整数的ASCII表示,则可以获取字符串表示(可能包含strconv.Itoa)并将该字符串强制转换为[]byte类型。

package main

import (
    "fmt"
    "strconv"
)

func main() {
    bs := []byte(strconv.Itoa(31415926))
    fmt.Println(bs)
}

答案 1 :(得分:24)

查看“encoding / binary”包。特别是读写功能:

binary.Write(a, binary.LittleEndian, myInt)

答案 2 :(得分:10)

对不起,这可能有点晚了。但我认为我在go docs上找到了更好的实现。

buf := new(bytes.Buffer)
var num uint16 = 1234
err := binary.Write(buf, binary.LittleEndian, num)
if err != nil {
    fmt.Println("binary.Write failed:", err)
}
fmt.Printf("% x", buf.Bytes())

答案 3 :(得分:2)

我认为 int 类型有任何方法可以将 int 哈希转换为字节,但首先我找到了 math / big 方法 https://golang.org/pkg/math/big/

var f int = 52452356235;          // int
var s = big.NewInt(int64(f))      // int to big Int
var b = s.Bytes()                 // big Int to bytes
// b - byte slise
var r = big.NewInt(0).SetBytes(b) // bytes to big Int
var i int = int(r.Int64())        // big Int to int

https://play.golang.org/p/VAKSGw8XNQq

但是,此方法使用绝对值。 如果多花1个字节,就可以转移符号

func IntToBytes(i int) []byte{
    if i > 0 {
        return append(big.NewInt(int64(i)).Bytes(), byte(1))
    }
    return append(big.NewInt(int64(i)).Bytes(), byte(0))
}
func BytesToInt(b []byte) int{
    if b[len(b)-1]==0 {
        return -int(big.NewInt(0).SetBytes(b[:len(b)-1]).Int64())
    }
    return int(big.NewInt(0).SetBytes(b[:len(b)-1]).Int64())
}

https://play.golang.org/p/mR5Sp5hu4jk

或新的(https://play.golang.org/p/7ZAK4QL96FO)

(该包还提供了填充现有切片的功能)

https://golang.org/pkg/math/big/#Int.FillBytes

答案 4 :(得分:0)

添加此选项以处理基本的uint8到byte []转换

foo := 255 // 1 - 255
ufoo := uint16(foo) 
far := []byte{0,0}
binary.LittleEndian.PutUint16(far, ufoo)
bar := int(far[0]) // back to int
fmt.Println("foo, far, bar : ",foo,far,bar)

输出: foo, far, bar : 255 [255 0] 255

答案 5 :(得分:0)

这是另一种选择,基于 Go 源代码 [1]:

package main

import (
   "encoding/binary"
   "fmt"
   "math/bits"
)

func encodeUint(x uint64) []byte {
   buf := make([]byte, 8)
   binary.BigEndian.PutUint64(buf, x)
   return buf[bits.LeadingZeros64(x) >> 3:]
}

func main() {
   for x := 0; x <= 64; x += 8 {
      buf := encodeUint(1<<x-1)
      fmt.Println(buf)
   }
}

结果:

[]
[255]
[255 255]
[255 255 255]
[255 255 255 255]
[255 255 255 255 255]
[255 255 255 255 255 255]
[255 255 255 255 255 255 255]
[255 255 255 255 255 255 255 255]

math/big快得多:

BenchmarkBig-12         28348621                40.62 ns/op
BenchmarkBit-12         731601145                1.641 ns/op
  1. https://github.com/golang/go/blob/go1.16.5/src/encoding/gob/encode.go#L113-L117

答案 6 :(得分:-4)

将其转换为字符串有什么问题?

[]byte(fmt.Sprintf("%d", myint))