【问题标题】:Go variables escape to the heap when using the add operator to concatenate strings [closed]使用 add 运算符连接字符串时,Go 变量转义到堆[关闭]
【发布时间】:2021-03-07 20:33:15
【问题描述】:

关于此代码的问题。为什么变量会逃到堆中

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

我发现如果使用fmt.Sprintf 它也会导致变量逃逸到堆中

【问题讨论】:

  • 这是一个实现细节。其他编译器或编译器版本可能不会在这里使用堆。

标签: go memory-management stack heap-memory escape-analysis


【解决方案1】:

导致转义的不是串联而是对fmt 包的调用。

如果您改为调用内置的println() 函数,它不会:

println(connection)

运行go run -gcflags "-m -l" main.go:

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

fmt.Println()的情况下,编译器无法保证传递的值会发生什么,所以它把它放在堆上。

【讨论】:

  • 感谢您的解释。所以使用 strings.builder 会比使用 fmt.Sprintf 更好吗?如果加入很多字符串..我必须写很多sb.WriteString然后sb.String().你有什么好方法吗?
  • 是的,通常strings.Builder() 更快@xiaodonghuan,因为它避免了内存分配。最简单的确定方法是编写基准测试并使用-benchmem 运行它。
  • 是的strings.Builder() 更快;但是对于这么小的操作,我不认为它真的会表现得更好。因此,不要因为如此微小的改进(或者可能不会)而失去代码的可读性。经验法则:做基准测试!
猜你喜欢
  • 2015-08-28
  • 2013-08-03
  • 2020-06-10
  • 2012-05-07
  • 1970-01-01
  • 2020-06-20
  • 2014-09-03
  • 2021-08-13
  • 2013-06-26
相关资源
最近更新 更多