通用的Go函数,用于将字节保存到固定大小的字节数组缓冲区中。

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

Generic Go function to save bytes into a fixed-size byte array buffer

问题

如何编写一个通用的Go函数将字节推入字节数组?

我想,追加到切片可能不是一个完美的选择,因为数组不应该增长。
然而,该函数应该处理任何数组大小。
我考虑将数组切片化,以便函数接受任何数组大小。
请参考下面的示例。

是否有更简洁的方法?

Play链接:http://play.golang.org/p/Gii9-JM33E

func push(buf []byte, size int, b byte) (int, error) {
    max := len(buf)

    if max < 1 {
        return size, fmt.Errorf("buffer underflow: max=%d char=%d", max, b)
    }

    if size >= max {
        return size, fmt.Errorf("buffer overflow: size=%d max=%d char=%d", size, max, b)
    }

    buf[size] = b

    return size + 1, nil
}

用法:

buf := [3]byte{}
size := 0
var err error
size, err = push(buf[:], size, 'a')
英文:

How do I to write a generic Go function to push bytes into a byte array?

I suppose appending to a slice is not a perfect fit, because the array should not grow.
However the function should handle any array size.
I am considering to slice the array just to make the function accept any array size.
See my sketch below.

Is there a cleaner way?

Play: http://play.golang.org/p/Gii9-JM33E

func push(buf []byte, size int, b byte) (int, error) {
    max := len(buf)

    if max &lt; 1 {
        return size, fmt.Errorf(&quot;buffer underflow: max=%d char=%d&quot;, max, b)
    }

    if size &gt;= max {
        return size, fmt.Errorf(&quot;buffer overflow: size=%d max=%d char=%d&quot;, size, max, b)
    }

    buf[size] = b

    return size + 1, nil
}

Usage:

buf := [3]byte{}
size := 0
var err error
size, err = push(buf[:], size, &#39;a&#39;)

答案1

得分: 2

你几乎肯定想使用切片而不是数组。切片有三个属性:底层支持的数组、容量和长度。容量“cap”告诉你底层数组的大小。

因此,你可以在检查len(s) < cap(s)之后使用append来避免重新分配。或者如果你想要一个函数,可以像这样写:

func pushByte(s []byte, b byte) ([]byte, error) {
    if len(s) == cap(s) {
        return s, errors.New("capacity reached")
    }
    return append(s, b), nil
}

你可以像这样使用它:

s := make([]byte, 0, 10)
var err error
if s, err = pushByte(s, 10); err != nil {
    ... 处理错误
}
英文:

You almost certainly want to use a slice instead of an array. A slice has three things: an underlying backing array, a capacity, and a length. The capacity "cap" tells you the size of the underlying backing array.

So, you can use append after checking that len(s) &lt; cap(s) to avoid any reallocation. Or if you want to make a function, perhaps something like this:

func pushByte(s []byte, b byte) ([]byte, error) {
    if len(s) == cap(s) {
        return s, errors.New(&quot;capacity reached&quot;)
    }
    return append(s, b), nil
}

You'd use it something like this:

s := make([]byte, 0, 10)
var err error
if s, err = pushByte(s, 10); err != nil {
    ... handle error
}

答案2

得分: 1

数组的大小是其类型的一部分。

如果你知道你将要接受的一组大小,你可以使用buf interface{}并在你想要的大小上进行类型切换。我假设你知道数组的大小,因为它们必须在编译时是常量。

除此之外,你需要使用反射来实际找到数组的大小,并在数组中存储元素。

很少需要使用数组而不是切片。你可能需要重新考虑为什么必须传递不同大小的数组。

英文:

The size of an array is part if its type.

If there's a set of sizes you know you are going to accept, you could take a buf interface{} with a type switch on the sizes you want. I would assume you know the array sizes, since they must be constant at compile time.

Other than that you would need to use reflection to actually find the array size, and store elements within the array.

It's very infrequent you need to use an array instead of a slice. You may want to reconsider why you have to pass arrays of varying sizes around.

huangapple
  • 本文由 发表于 2014年5月30日 22:24:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/23956929.html
匿名

发表评论

匿名网友

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

确定