mirror of
https://github.com/golang/go
synced 2024-11-17 14:14:56 -07:00
strings: add Clone function
The new strings.Clone function copies the input string without the returned cloned string referencing the input strings memory. goarch: amd64 cpu: Intel(R) Core(TM) i5-1038NG7 CPU @ 2.00GHz name time/op Clone-8 24.2ns ± 2% name alloc/op Clone-8 48.0B ± 0% name allocs/op Clone-8 1.00 ± 0% Update #45038 Fixes #40200 Change-Id: Id9116c21c14328ec3931ef9a67a2e4f30ff301f9 Reviewed-on: https://go-review.googlesource.com/c/go/+/345849 Trust: Martin Möhrmann <martin@golang.org> Run-TryBot: Martin Möhrmann <martin@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Joe Tsai <joetsai@digital-static.net> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
bced369a50
commit
e74e363a6b
23
src/strings/clone.go
Normal file
23
src/strings/clone.go
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package strings
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Clone returns a fresh copy of s.
|
||||
// It guarantees to make a copy of s into a new allocation,
|
||||
// which can be important when retaining only a small substring
|
||||
// of a much larger string. Using Clone can help such programs
|
||||
// use less memory. Of course, since using Clone makes a copy,
|
||||
// overuse of Clone can make programs use more memory.
|
||||
// Clone should typically be used only rarely, and only when
|
||||
// profiling indicates that it is needed.
|
||||
func Clone(s string) string {
|
||||
b := make([]byte, len(s))
|
||||
copy(b, s)
|
||||
return *(*string)(unsafe.Pointer(&b))
|
||||
}
|
40
src/strings/clone_test.go
Normal file
40
src/strings/clone_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.ß
|
||||
|
||||
package strings_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func TestClone(t *testing.T) {
|
||||
var cloneTests = []string{
|
||||
"",
|
||||
"short",
|
||||
strings.Repeat("a", 42),
|
||||
}
|
||||
for _, input := range cloneTests {
|
||||
clone := strings.Clone(input)
|
||||
if clone != input {
|
||||
t.Errorf("Clone(%q) = %q; want %q", input, clone, input)
|
||||
}
|
||||
|
||||
inputHeader := (*reflect.StringHeader)(unsafe.Pointer(&input))
|
||||
cloneHeader := (*reflect.StringHeader)(unsafe.Pointer(&clone))
|
||||
if inputHeader.Data == cloneHeader.Data {
|
||||
t.Errorf("Clone(%q) return value should not reference inputs backing memory.", input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkClone(b *testing.B) {
|
||||
var str = strings.Repeat("a", 42)
|
||||
b.ReportAllocs()
|
||||
for i := 0; i < b.N; i++ {
|
||||
stringSink = strings.Clone(str)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user