【问题标题】:Generic Go function to save bytes into a fixed-size byte array buffer将字节保存到固定大小的字节数组缓冲区中的通用 Go 函数
【发布时间】:2014-05-30 14:24:47
【问题描述】:

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

我认为附加到切片并不是一个完美的选择,因为数组不应该增长。 但是,该函数应处理任何数组大小。 我正在考虑对数组进行切片以使函数接受任何数组大小。 请参阅下面的草图。

有没有更清洁的方法?

播放: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')

【问题讨论】:

  • 你当前的函数有什么问题?
  • @OneOfOne 它需要对数组进行切片才能接受任何数组大小。我觉得传递一个切片加上它的底层数组大小很笨拙......我希望有一个更干净的惯用方式。
  • @JimB 数组加上它的大小出现在我在函数下方添加的使用模式中。
  • 好的,我明白了。但是你为什么首先使用数组?
  • 我感觉你在这里关注的是错误的事情。你想解决什么问题?

标签: arrays go slice


【解决方案1】:

您几乎肯定想要使用切片而不是数组。切片具有三样东西:底层支持数组、容量和长度。容量“cap”告诉您底层支持数组的大小。

因此,您可以在检查 len(s) &lt; 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 {
    ... handle error
}

【讨论】:

  • 谢谢,我觉得你的建议确实更好。
【解决方案2】:

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

如果有一组您知道自己会接受的尺寸,您可以使用buf interface{} 并在您想要的尺寸上使用类型开关。我假设您知道数组大小,因为它们在编译时必须保持不变。

除此之外,您还需要使用反射来实际查找数组大小,并将元素存储在数组中。

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

【讨论】:

  • 我的数组大小很少,并且担心在代码中多次出现一些固定大小的类型(例如 [200]byte、[1000]byte、[64000]byte)。从您的回答中,我看到定义一些自定义数组类型(如类型 Buf1 [100]byte、类型 Buf2 [1000]byte、类型 Buf3 [64000]byte)或仅使用切片并防止它们增长(正如@Anonymous 所建议的那样)。
猜你喜欢
  • 2019-03-12
  • 2011-12-23
  • 1970-01-01
  • 2017-09-29
  • 2013-09-24
  • 2010-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多