0

Question about this code . why variables escape to heap

func main() {
    port := "8080"
    host := "localhost:"
    connection := host + port
    fmt.Println(connection)
}

gorun -gcflags "-m -l" main.go

# command-line-arguments
./main.go:12:21: host + port escapes to heap
./main.go:13:13: ... argument does not escape
./main.go:13:13: connection escapes to heap

And I found if use fmt.Sprintf it also cause the variables escape to heap

icza
  • 389,944
  • 63
  • 907
  • 827
  • This is an implementation detail. Other compilers or compiler versions might not use the heap here. – Volker Nov 25 '20 at 06:26

1 Answers1

4

It's not the concatenation but the call to the fmt package that causes the escape.

If you call the builtin println() function instead, it won't:

println(connection)

Running go run -gcflags "-m -l" main.go:

# command-line-arguments
./main.go:12:21: host + port does not escape
localhost:8080

In case of fmt.Println() the compiler can't guarantee what will happen to the passed value, so it puts it on the heap.

icza
  • 389,944
  • 63
  • 907
  • 827
  • Thanks for explain. so use the strings.builder will be better than use fmt.Sprintf right? If join many string.. I must write many `sb.WriteString` then `sb.String()`.Do you have a good way ? – xiaodong huan Nov 25 '20 at 01:32
  • Yeah, usually `strings.Builder()` is faster @xiaodonghuan, since it avoids memory allocations. The easiest way to know for sure is to write a benchmark and run it with `-benchmem`. – Martin Tournoij Nov 25 '20 at 04:04
  • Yes `strings.Builder()` is faster; but for such small operations, I don't think it's really going to perform better. So don't lose the readability of the code for such tiny improvements (or maybe not). Rule of thumb: Do benchmarks! – shmsr Nov 25 '20 at 05:36