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

时间:2018-07-16 14:07:16

标签: string go append slice

我正在尝试将字节数组初始化为数字和字符串的混合。我已经设法通过使用一对追加,或通过将字符串拆分为单独的字符来做到这一点,但是出于可读性考虑,有没有一种方法可以将其作为包含字符串的单个初始值设定项呢?

// 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 个答案:

答案 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)

尽管如此,我仍然认为它不更具可读性或价值。


Concat优化

根据下面的评论,@ 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

Kubernetes ExternalIP