将一个整数转换为字节数组

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

Convert an integer to a byte array

问题

我有一个接收[]byte的函数,但我有的是一个int,怎么样才能最好地进行转换?

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

我猜我可以走一条冗长的路,将其转换为字符串,然后将其放入字节中,但这听起来很丑陋,我猜应该有更好的方法来做这件事。

英文:

I have a function which receives a []byte but what I have is an int, what is the best way to go about this conversion ?

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

I guess I could go the long way and get it into a string and put that into bytes, but it sounds ugly and I guess there are better ways to do it.

答案1

得分: 77

我同意Brainstorm的方法:假设你正在传递一个机器友好的二进制表示,可以使用encoding/binary库。OP建议binary.Write()可能会有一些开销。查看Write()的实现源码,我发现它做了一些运行时决策以实现最大的灵活性。

func Write(w io.Writer, order ByteOrder, data interface{}) error {
    // Fast path for basic types.
    var b [8]byte
    var bs []byte
    switch v := data.(type) {
    case *int8:
        bs = b[:1]
        b[0] = byte(*v)
    case int8:
        bs = b[:1]
        b[0] = byte(v)
    case *uint8:
        bs = b[:1]
        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)
}
英文:

I agree with Brainstorm's approach: assuming that you're passing a machine-friendly binary representation, use the encoding/binary library. The OP suggests that binary.Write() might have some overhead. Looking at the source for the implementation of Write(), I see that it does some runtime decisions for maximum flexibility.

func Write(w io.Writer, order ByteOrder, data interface{}) error {
    // Fast path for basic types.
    var b [8]byte
    var bs []byte
    switch v := data.(type) {
    case *int8:
        bs = b[:1]
        b[0] = byte(*v)
    case int8:
        bs = b[:1]
        b[0] = byte(v)
    case *uint8:
        bs = b[:1]
        b[0] = *v
    ...

Right? Write() takes in a very generic data third argument, and that's imposing some overhead as the Go runtime then is forced into encoding type information. Since Write() is doing some runtime decisions here that you simply don't need in your situation, maybe you can just directly call the encoding functions and see if it performs better.

Something like this:

package main

import (
	"encoding/binary"
	"fmt"
)

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

Let us know how this performs.

Otherwise, if you're just trying to get an ASCII representation of the integer, you can get the string representation (probably with strconv.Itoa) and cast that string to the []byte type.

package main

import (
	"fmt"
	"strconv"
)

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

答案2

得分: 34

请查看"encoding/binary"包。特别是ReadWrite函数:

binary.Write(a, binary.LittleEndian, myInt)
英文:

Check out the "encoding/binary" package. Particularly the Read and Write functions:

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

答案3

得分: 25

抱歉,可能有点晚了。但我认为我在go文档中找到了一个更好的实现。

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())
英文:

Sorry, this might be a bit late. But I think I found a better implementation on the 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())

答案4

得分: 3

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

然而,这种方法使用了绝对值。
如果你多花费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())
}

或者使用new(https://play.golang.org/p/7ZAK4QL96FO)

(该包还提供了将数据填充到现有切片的函数)

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

英文:

i thought int type has any method for getting int hash to bytes, but first i find math / big method for this
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

However, this method uses an absolute value.
If you spend 1 byte more, you can transfer the sign

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

or new(https://play.golang.org/p/7ZAK4QL96FO)

(The package also provides functions for fill into an existing slice)

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

答案5

得分: 1

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

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

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

英文:

Adding this option for dealing with basic uint8 to byte[] conversion

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)

output :
foo, far, bar : 255 [255 0] 255

答案6

得分: 1

这是另一种选项,基于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
英文:

Here is another option, based on the Go source code 1:

package main

import (
   &quot;encoding/binary&quot;
   &quot;fmt&quot;
   &quot;math/bits&quot;
)

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

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

Result:

[]
[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]

Much faster than 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

答案7

得分: 0

将整数转换为字节切片。

英文:

Convert Integer to byte slice.

import (
	&quot;bytes&quot;
	&quot;encoding/binary&quot;
	&quot;log&quot;
)

func IntToBytes(num int64) []byte {
	buff := new(bytes.Buffer)
	bigOrLittleEndian := binary.BigEndian
	err := binary.Write(buff, bigOrLittleEndian, num)
	if err != nil {
		log.Panic(err)
	}

	return buff.Bytes()
}

答案8

得分: 0

也许简单的方法是使用protobuf,参见Protocol Buffer Basics: Go

定义消息如下:

message MyData {
  int32 id = 1;
}

了解更多,请参见Defining your protocol format

// 写入
out, err := proto.Marshal(mydata)

详细了解,请参见Writing a Message

英文:

Maybe the simple way is using protobuf, see the Protocol Buffer Basics: Go

define message like

message MyData {
  int32 id = 1;
}

get more in Defining your protocol format

// Write
out, err := proto.Marshal(mydata)

read more in Writing a Message

答案9

得分: 0

尝试使用math/big包将字节数组转换为整数,并将整数转换为字节数组。

package main

import (
	"fmt"
	"math/big"
)

func main() {
	// 将整数转换为字节数组
	var int_to_encode int64 = 65535
	var bytes_array []byte = big.NewInt(int_to_encode).Bytes()
	fmt.Println("字节数组", bytes_array)

	// 将字节数组转换为整数
	var decoded_int int64 = new(big.Int).SetBytes(bytes_array).Int64()
	fmt.Println("解码后的整数", decoded_int)
}
英文:

Try math/big package to convert bytes array to int and to convert int to bytes array.

package main

import (
	&quot;fmt&quot;
	&quot;math/big&quot;
)

func main() {
	// Convert int to []byte
	var int_to_encode int64 = 65535
	var bytes_array []byte = big.NewInt(int_to_encode).Bytes()
	fmt.Println(&quot;bytes array&quot;, bytes_array)

	// Convert []byte to int
	var decoded_int int64 = new(big.Int).SetBytes(bytes_array).Int64()
	fmt.Println(&quot;decoded int&quot;, decoded_int)
}




</details>



# 答案10
**得分**: 0

这是最直接(也是最短(也是最安全)(也可能是最高效))的方法:

`buf.Bytes()` 的类型是字节切片。

```go
	var val uint32 = 42
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.LittleEndian, val)
	if err != nil {
		fmt.Println("binary.Write 失败:", err)
	}
	fmt.Printf("% x\n", buf.Bytes())

参见 https://stackoverflow.com/a/74819602/589493

英文:

This is the most straight forward (and shortest (and safest) (and maybe most performant)) way:

buf.Bytes() is of type bytes slice.

	var val uint32 = 42
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.LittleEndian, val)
	if err != nil {
		fmt.Println(&quot;binary.Write failed:&quot;, err)
	}
	fmt.Printf(&quot;% x\n&quot;, buf.Bytes())

see also https://stackoverflow.com/a/74819602/589493

答案11

得分: -6

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

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

What's wrong with converting it to a string?

[]byte(fmt.Sprintf(&quot;%d&quot;, myint))

huangapple
  • 本文由 发表于 2013年6月3日 07:45:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/16888357.html
匿名

发表评论

匿名网友

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

确定