How should I convert a slice to a string in golang?

huangapple go评论98阅读模式
英文:

How should I convert a slice to a string in golang?

问题

我正在使用strings.Split函数来拆分一个字符串。

我希望我的程序保留数组的一个元素并释放底层数组。

不幸的是,我无法弄清楚如何将一个字符串切片转换为不引用底层字符串的字符串。

我应该像这样做吗:

func unslice(s string) (string) {
  return string([]byte(s))
}

背景是:

  1. 底层字符串非常大
  2. 我想保留的切片非常小
  3. 我想保留的切片将会长时间保留
  4. 程序将长时间运行 - 几周甚至更长时间
  5. 在程序的生命周期内,它将拆分许多这样的字符串(数百万个)

以下是对评论的示例:

func takesBigStringOften(big string) {
    parts := strings.Split(big, " ")

    saveTinyStringForALongTime(parts[0])
}
英文:

I'm using strings.Split to split a string.

I would like my program to retain one of the elements of the array and release the underlying array.

Unfortunately I can't figure out how to convert a slice of a string into a string that doesn't refer to the underlying string.

Am I supposed to do something like this:

func unslice(s string) (string) {
  return string([]byte(s))
}

The background is:

  1. the underlying string is very large
  2. the slice I want to retain is very small
  3. the slice I want to retain will be retained for a long time
  4. the program will run for a long time - weeks or more
  5. during the lifetime of the program it will split many of these strings (millions)

Here is an example in response to the comment.

func takesBigStringOften(big string) {
    parts := strings.Split(big, " ")

    saveTinyStringForALongTime(parts[0])
}

答案1

得分: 3

只是一些进一步的信息。一些基准代码和内存分析显示,截至go 1.5.3版本,这两种方法从堆中分配了相同数量的内存,即无论哪种方式都会创建一个新的副本。在从字节切片构建字符串时,编译器调用一个例程,该例程创建字节的唯一副本,因为字符串是不可变的,而字节切片不是。

$ go tool pprof -alloc_space so002.test cprof0
进入交互模式(输入“help”获取命令列表)
(pprof) list copy
总计:9.66MB
9.62MB 9.62MB(平坦,累计)总计99.55%
. . 15:
. . 16:var global string
. . 17:
. . 18:func benchmarkcopy(b *testing.B, c int) {
. . 19: big := "This is a long string"
. 240B 20: parts := strings.Split(big, " ")
. . 21: old := parts[0]
. . 22: jlimit := 100
. . 23: for i := 0; i < b.N; i++ {
. . 24: for j := 0; j < jlimit; j++ {
3.21MB 3.21MB 25: global = string([]byte(old))
. . 26: }
. . 27: for j := 0; j < jlimit; j++ {
. . 28: b := []byte(old)
3.21MB 3.21MB 29: global = string(b)
. . 30: }
. . 31: for j := 0; j < jlimit; j++ {
3.21MB 3.21MB 32: new := make([]byte, len(old))
. . 33: copy(new, old)
. . 34: global = string(old)
. . 35: }
. . 36: }
. . 37:}

英文:

Just as some further information. Some benchmark code and memory profiling shows that as of go 1.5.3, both methods allocate the same amount of memory from the heap, i.e. a new copy is made either way. In building a string from a byte slice, the compiler calls a routine that makes a unique copy of the bytes - since strings are immutable and byte slices are not.

$ go tool pprof -alloc_space so002.test cprof0
Entering interactive mode (type &quot;help&quot; for commands)
(pprof) list copy
Total: 9.66MB
    9.62MB     9.62MB (flat, cum) 99.55% of Total
         .          .     15:
         .          .     16:var global string
         .          .     17:
         .          .     18:func benchmarkcopy(b *testing.B, c int) {
         .          .     19:	big := &quot;This is a long string&quot;
         .       240B     20:	parts := strings.Split(big, &quot; &quot;)
         .          .     21:	old := parts[0]
         .          .     22:	jlimit := 100
         .          .     23:	for i := 0; i &lt; b.N; i++ {
         .          .     24:		for j := 0; j &lt; jlimit; j++ {
    3.21MB     3.21MB     25:			global = string([]byte(old))
         .          .     26:		}
         .          .     27:		for j := 0; j &lt; jlimit; j++ {
         .          .     28:			b := []byte(old)
    3.21MB     3.21MB     29:			global = string(b)
         .          .     30:		}
         .          .     31:		for j := 0; j &lt; jlimit; j++ {
    3.21MB     3.21MB     32:			new := make([]byte, len(old))
         .          .     33:			copy(new, old)
         .          .     34:			global = string(old)
         .          .     35:		}
         .          .     36:	}
         .          .     37:}

答案2

得分: 2

为了确保 Go 不会在内存中保留底层字符串,你需要显式地将其复制到新的位置:

func unslice(old string) string {
    new := make([]byte, len(old))
    copy(new, old)
    return string(old)
}

SmallString := unslice(BigString[0:7])
英文:

To ensure that Go doesn't keep the underlying string in memory you will have to explicitly copy it to a new location:

func unslice(old string) string {
	new := make([]byte,len(old))
	copy(new,old)
	return string(old)
}

SmallString := unslice(BigString[0:7])

huangapple
  • 本文由 发表于 2016年3月14日 04:32:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/35975456.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定