go - 为什么golang strings.Builder 是这样实现String()的?

标签 go

实现是

// String returns the accumulated string.
func (b *Builder) String() string {
    return *(*string)(unsafe.Pointer(&b.buf))
}

根据我的测试,将 []byte 转换为字符串使用“写时复制”,或者编译器生成深复制指令,如果其中任何一个正在更改内部 slice :
{
        a := []byte{'a'}
        s1 := string(a)
        a[0] = 'b'
        fmt.Println(s1) // a
    }

    {
        a := "a"
        b := []byte(a)
        b[0] = 'b'
        fmt.Println(a) // a
    }

那么如果按照下面的方式实现会发生什么?
// String returns the accumulated string.
func (b *Builder) String() string {
    return string(b.buf)
}

最佳答案

给定足够大的字符串,类型转换需要内存分配,而使用 unsafe 包的转换不需要:

package main

import (
    "testing"
    "unsafe"
)

func BenchmarkConversion(b *testing.B) {
    buf := make([]byte, 16<<10)
    b.ResetTimer()

    for i := 0; i < b.N; i++ {
        var _ string = string(buf)
    }
}

func BenchmarkUnsafe(b *testing.B) {
    buf := make([]byte, 16<<10)
    b.ResetTimer()

    for i := 0; i < b.N; i++ {
        var _ string = *(*string)(unsafe.Pointer(&buf))
    }
}
$ go test -bench=. -benchmem
goos: linux
goarch: amd64
BenchmarkConversion-8            307087      3897 ns/op     16384 B/op     1 allocs/op
BenchmarkUnsafe-8            1000000000     0.299 ns/op         0 B/op     0 allocs/op
PASS
ok      _/tmp/tmp.KECLzZwkUn    1.579s

关于go - 为什么golang strings.Builder 是这样实现String()的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62018471/

相关文章:

go - 可以使用 go HTTP 客户端访问 TCP 数据包详细信息吗?

转到函数调用的类型

go - 使用MultipartRequest上传文件

inheritance - 以另一个接口(interface)的形式实现一个接口(interface)

Go 服务器在 arm64 上返回损坏的图像

go - Gitlab-CI 运行器 : ignore self-signed certificate

go - 使用以编程方式编写并连接到os.stdin的stdin执行命令

Go os.Truncate() 不重置文件光标

arrays - 下面的 Go 数组操作是做什么的?

go - 所有 goroutines 都处于休眠状态