我正在尝试将字节数组初始化为数字和字符串的混合。我已经设法通过使用一对追加,或通过将字符串拆分为单独的字符来做到这一点,但是出于可读性考虑,有没有一种方法可以将其作为包含字符串的单个初始值设定项呢?
// method 1, with two appends
a := []byte{1, 2}
a = append(a, []byte("foo")...);
a = append(a, 3, 4);
// method 2, splitting the string into chars
b := []byte{1, 2, 'f', 'o', 'o', 3, 4)
答案 0 :(得分:3)
您在3行中的首次尝试所做的工作可能比任何一种方法都更具可读性:
(您可以在Go Playground上尝试所有示例。)
// Doing one-by-one:
a := []byte{1, 2}
a = append(a, []byte("foo")...)
a = append(a, 3, 4)
fmt.Println(a)
// Using individual chars:
a = []byte{1, 2, 'f', 'o', 'o', 3, 4}
fmt.Println(a)
// Using a single string literal:
a = []byte("\x01\x02foo\x03\x04")
fmt.Println(a)
// Using several "nested" appends:
a = append(append([]byte{1, 2}, []byte("foo")...), 3, 4)
fmt.Println(a)
除非您创建了辅助函数:
func concat(s ...[]byte) []byte {
var res []byte
for _, v := range s {
res = append(res, v...)
}
return res
}
然后使用它:
// With a utility function:
a = concat([]byte{1, 2}, []byte("foo"), []byte{3, 4})
fmt.Println(a)
// With a utility function, formatted differently:
a = concat(
[]byte{1, 2},
[]byte("foo"),
[]byte{3, 4},
)
fmt.Println(a)
您也可以使用单个键合成文字和单个copy()
调用来“插入”字符串:
// With keyed literal and copy:
a = []byte{1, 2, 5: 3, 4}
copy(a[2:], "foo")
fmt.Println(a)
尽管如此,我仍然认为它不更具可读性或价值。
根据下面的评论,@ EliasVanOotegem对上述解决方案进行了基准测试(在空片上使用append),并将其与求和字节片的总容量求和并一次性分配该内存进行了比较。后者的效率更高(〜20%),所以我将在下面列出该版本:
func concat(s ...[]byte) []byte {
c := 0
for _, v := range s {
c += len(v)
}
res := make([]byte, 0, c) // allocate everything
for _, v := range s {
res = append(res, v...)
}
return res
}
我个人将使用以下优化版本,由于它使用内置copy()
,因此不需要片头分配:
func concat(s ...[]byte) []byte {
size := 0
for _, v := range s {
size += len(v)
}
res, i := make([]byte, size), 0
for _, v := range s {
i += copy(res[i:], v)
}
return res
}
答案 1 :(得分:2)
我想我误解了您最初尝试的内容。您可以将其编写为嵌入十六进制的字符串:
c := []byte("\x01\x02foo\x03\x04")
答案 2 :(得分:0)
FWIW:可以在附加调用中删除对[]byte(...)
的转换:
a := []byte{65, 66}
a = append(a, "foo"...)
a = append(a, 67, 68)
fmt.Printf("%s", a)
// outputs : ABfooCD