你在第一次尝试中所做的 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)
我仍然不认为它更具可读性或价值。
连续优化
根据下面留下的 cmets,@EliasVanOotegem 对上面的解决方案进行了基准测试(在空切片上使用追加)并将其与所需字节切片的总容量相加并一次性分配该内存进行比较。后者的效率稍高一些(~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
}