使用Go语言,如何将未知数量的字节追加到向量中并获取字节切片?

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

With Go, how to append unknown number of byte into a vector and get a slice of bytes?

问题

我正在尝试将一个大数编码为字节列表(在Go中为uint8)。
字节数量未知,所以我想使用vector。
但是Go没有提供字节向量,我该怎么办?
是否可以获得这样一个字节向量的切片?

我打算实现数据压缩。
不同于使用相同字节数存储小数和大数,
我使用可变字节数,对小数使用较少字节,对大数使用更多字节。

我的代码无法编译,类型断言无效:

  1 package main
  2 
  3 import (
  4     //"fmt"
  5     "container/vector"
  6 )
  7 
  8 func vbEncodeNumber(n uint) []byte{
  9     bytes := new(vector.Vector)
 10     for {
 11         bytes.Push(n % 128)
 12         if n < 128 {
 13             break
 14         }
 15         n /= 128
 16     }
 17     bytes.Set(bytes.Len()-1, bytes.Last().(byte)+byte(128))
 18     return bytes.Data().([]byte) // <-
 19 }
 20 
 21 func main() { vbEncodeNumber(10000) }

我希望将这样的代码写入二进制文件中,
所以我希望该函数能返回字节数组。

我还没有找到关于vector的代码示例。

英文:

I'm trying to encode a large number to a list of bytes(uint8 in Go).
The number of bytes is unknown, so I'd like to use vector.
But Go doesn't provide vector of byte, what can I do?
And is it possible to get a slice of such a byte vector?

I intends to implement data compression.
Instead of store small and large number with the same number of bytes,
I'm implements a variable bytes that uses less bytes with small number
and more bytes with large number.

My code can not compile, invalid type assertion:

  1 package main
  2 
  3 import (
  4     //"fmt"
  5     "container/vector"
  6 )
  7 
  8 func vbEncodeNumber(n uint) []byte{
  9     bytes := new(vector.Vector)
 10     for {
 11         bytes.Push(n % 128)
 12         if n < 128 {
 13             break
 14         }
 15         n /= 128
 16     }
 17     bytes.Set(bytes.Len()-1, bytes.Last().(byte)+byte(128))
 18     return bytes.Data().([]byte) // <-
 19 }
 20 
 21 func main() { vbEncodeNumber(10000) }

I wish to writes a lot of such code into binary file,
so I wish the func can return byte array.

I haven't find a code example on vector.

答案1

得分: 2

由于您正在尝试表示大数,您可以看看big包是否符合您的需求。

通用的Vector结构可以用来存储字节。它接受一个空接口作为其类型,而任何其他类型都满足该接口。您可以通过Data方法检索接口的切片,但没有办法将其转换为字节的切片而不进行复制。您不能使用类型断言将interface{}的切片转换为其他类型的切片。您需要在函数末尾执行以下操作:(我没有尝试编译此代码,因为我现在无法)

byteSlice = make([]byte, bytes.Len())
for i, _ := range byteSlice {
    byteSlice[i] = bytes.At(i).(byte)
}
return byteSlice
英文:

Since you're trying to represent large numbers, you might see if the big package serves your purposes.

The general Vector struct can be used to store bytes. It accepts an empty interface as its type, and any other type satisfies that interface. You can retrieve a slice of interfaces through the Data method, but there's no way to convert that to a slice of bytes without copying it. You can't use type assertion to turn a slice of interface{} into a slice of something else. You'd have to do something like the following at the end of your function: (I haven't tried compiling this code because I can't right now)

byteSlice = make([]byte, bytes.Len())
for i, _ := range byteSlice {
    byteSlice[i] = bytes.At(i).(byte)
}
return byteSlice

答案2

得分: 2

看一下bytes包和其中的Buffer类型。你可以将整数写入缓冲区作为字节,然后可以使用Bytes()方法来访问缓冲区的字节片段。

英文:

Take a look at the bytes package and the Buffer type there. You can write your ints as bytes into the buffer and then you can use the Bytes() method to access byte slices of the buffer.

答案3

得分: 1

我发现自从语言中添加了通用的append和copy函数以来,向量的用处变得不那么有用了。以下是我如何一次性完成它而减少复制的方法:

package main

import "fmt"

func vbEncodeNumber(n uint) []byte {
    bytes := make([]byte, 0, 4)
    for n > 0 {
        bytes = append(bytes, byte(n%256))
        n >>= 8
    }
    return bytes
}

func main() {
    bytes := vbEncodeNumber(10000)
    for i := len(bytes)-1; i >= 0 ; i-- {
        fmt.Printf("%02x ", bytes[i])
    }
    fmt.Println("")
}
英文:

I've found the vectors to be a lot less useful since the generic append and copy were added to the language. Here's how I'd do it in one shot with less copying:

package main

import "fmt"

func vbEncodeNumber(n uint) []byte {
	bytes := make([]byte, 0, 4)
	for n > 0 {
		bytes = append(bytes, byte(n%256))
		n >>= 8
	}
	return bytes
}

func main() {
	bytes := vbEncodeNumber(10000)
	for i := len(bytes)-1; i >= 0 ; i-- {
		fmt.Printf("%02x ", bytes[i])
	}
	fmt.Println("")
}

huangapple
  • 本文由 发表于 2010年1月29日 11:58:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/2159792.html
匿名

发表评论

匿名网友

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

确定