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

标签 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 行写的内容可能比任何一行代码都更具可读性:

(您可以尝试 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 对上述解决方案进行了基准测试(在空 slice 上使用追加)并将其与所需字节 slice 的总容量相加并一次性分配该内存进行比较。后者的效率略高 (~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
}

我个人会使用以下优化版本,它不需要 slice header 分配,因为它使用内置 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
}

关于string - 包含字符串文字的数组初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51363767/

相关文章:

go - 关于goroutine无限循环和内存分配的问题

arrays - Redis reJson : JSON. ARRAYAPPEND 返回 WRONGTYPE 针对持有错误类型值的键的操作

java - 对于两个相等的字符串,Equals() 不返回 true

mysql - 从简单的选择查询 TADOQuery Delphi 捕获值

performance - Go:基于类的方法是否比功能更高效?

python - numpy.append() 的困难。当我自己在 IDLE 中输入它时它有效,但在运行时无效

python - 如何有条件地将 pandas 系列 append 到另一个数据框

c++ - 字符串解析的优雅解决方案

string - 查找最小字符串数以完全覆盖字符的逻辑

go - Go 中 slice 内的对象