go数组初始化包含字符串文字



我正在尝试将字节数组初始化为数字和字符串的混合。我已经设法使用了一对附加符,或者通过将字符串拆分为单独的字符来完成,但为了可读性,有没有办法将其作为包含字符串的单个初始值设定项来完成?

// 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)

您在3行中的第一次尝试可能比任何一行都更可读:

(你可以在围棋场上尝试所有的例子。(

// 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("x01x02foox03x04")
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对上面的解决方案进行了基准测试(在空片上使用追加(,并将其与所需字节片的总容量相加并一次性分配内存进行了比较。后者的效率略高(约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
}

我想我误解了你最初的尝试。你可以把它写成一个嵌入了十六进制的字符串:

c := []byte("x01x02foox03x04")

FWIW:可以在追加调用中删除对[]byte(...)的强制转换

a := []byte{65, 66}
a = append(a, "foo"...)
a = append(a, 67, 68)
fmt.Printf("%s", a)
// outputs : ABfooCD

在play.golang.org 上查看

相关内容

最新更新