views:

555

answers:

3

In Go, string is a primitive type, it's readonly, every manipulation to it will create a new string.

So, if I want to concatenate strings many times without knowing the length of the resulting string, what's the best way to do it?

The naive way would be:

s := "";
for i := 0; i < 1000; i++ {
    s += getShortStringFromSomewhere();
}
return s;

but that does not seem very efficient.

+4  A: 

You could create a big slice of bytes and copy the bytes of the short strings into it using string slices. There is a function given in "Effective Go":

func Append(slice, data[]byte) []byte {
    l := len(slice);
    if l + len(data) > cap(slice) { // reallocate
     // Allocate double what's needed, for future growth.
     newSlice := make([]byte, (l+len(data))*2);
     // Copy data (could use bytes.Copy()).
     for i, c := range slice {
      newSlice[i] = c
     }
     slice = newSlice;
    }
    slice = slice[0:l+len(data)];
    for i, c := range data {
     slice[l+i] = c
    }
    return slice;
}

Then when the operations are finished, use string ( ) on the big slice of bytes to convert it into a string again.

Kinopiko
+3  A: 

There is a library function in the strings package called "Join": http://golang.org/pkg/strings/#Join

A look at the code of "Join" shows a similar approach to Append function Kinopiko wrote: http://golang.org/src/pkg/strings/strings.go#L119

Usage:

import (
    "fmt";
    "strings";
)

func main() {
    s := []string{"this", "is", "a", "joined", "string\n"};
    fmt.Printf(strings.Join(s, " "));
}

$ ./test.bin
this is a joined string
mbarkhau
+7  A: 

The best way is to use the bytes package. It has a Buffer class, which implements io.Writer.

package main

import ( 
  "bytes"; 
  "fmt";
  )

func main() {

  buffer := bytes.NewBufferString("");

  for i := 0; i < 1000; i++ {
    fmt.Fprint(buffer, "a");
  }

  println(string(buffer.Bytes()));

}

This does it in O(n) time.

marketer