String concatenation

February 9, 2024

Today we’re looking at a deceptively short section of the spec: String concatenation…

String concatenation

Strings can be concatenated using the + operator or the += assignment operator:

s := "hi" + string(c)
s += " and good bye"

String addition creates a new string by concatenating the operands.

That’s it.

Short, and sweet, eh?

Except that it’s not quite so sweet, when you consider the implications of the last sentence: Every time you use + or += for a string, you create a new string. This is because strings in Go are immutable.

x := "Hello"
x = "world" // Creates a new string, discarding the old one, to be cleaned up by the Garbage Collector

This means that if you’re coming from a lanugage like PHP, JavaScript, or Perl, where it’s common to build strings incrementally, you could be inadvertently wasting a lot of memory and stressing your garbage collector.

message := "Hello, " + name
message += "Thank you for using my amazing app!"
message += "Here at " + companyName + " we take your patronage seriously!"
message += "On the other hand, we ignore the memory consumption of our"
message += "application."

That’s what not to do. 😉 Every instance of message += discards the old (ever larger) value of the string, and allocates memory for the new version.

Depending on your exact situation, there are a number of alternatives. Check out this StackOverflow post for a number of alternatives, but a good general purpose one is the strings.Builder type in the standard library. It makes the code a bit more verbose, but much more efficient:

var b strings.Builder
b.WriteString("Hello, " + name)
b.WriteString("Thank you for using my amazing app!")
b.WriteString("Here at " + companyName + " we take your patronage seriously!")
b.WriteString("We also care about  the memory consumption of our")
b.WriteString("application.")

message := b.String()

Quotes from The Go Programming Language Specification Version of August 2, 2023


Share this

Direct to your inbox, daily. I respect your privacy .

Unsure? Browse the archive .

Related Content


Evaluation of range expressions

For statements with range clause … The range expression x is evaluated once before beginning the loop, with one exception: if at most one iteration variable is present and len(x) is constant, the range expression is not evaluated. The first part of this seems pretty self-evident, as it follows the same pattern as a for statement with a for clause: The expression needs to be evaluated once before the loop executes.


Converting rune slices to strings

Yesterday we started through the list of rules and special cases for converting to and from string types. Let’s continue… Conversions to and from a string type … Converting a slice of runes to a string type yields a string that is the concatenation of the individual rune values converted to strings. string([]rune{0x767d, 0x9d6c, 0x7fd4}) // "\u767d\u9d6c\u7fd4" == "白鵬翔" string([]rune{}) // "" string([]rune(nil)) // "" type runes []rune string(runes{0x767d, 0x9d6c, 0x7fd4}) // "\u767d\u9d6c\u7fd4" == "白鵬翔" type myRune rune string([]myRune{0x266b, 0x266c}) // "\u266b\u266c" == "♫♬" myString([]myRune{0x1f30e}) // "\U0001f30e" == "🌎" I think this one is pretty intuitive.


Conversions to and from a string type

Before I dive in to today’s spec discussion… are you enjoying this series? If so, would you do me a favor and help spread the word? Can you share a link to this message with a fellow Gopher, or on your work chat? Conversion to and from string types is a minefield of special cases in Go. So this will take at least a couple of days. Let’s dive in.

Get daily content like this in your inbox!

Subscribe