strings: simplify code using unsafe.StringData

Updates #54854

Change-Id: I93396dc92bd2decba895f2d059e1aeffcd22312c
Reviewed-on: https://go-review.googlesource.com/c/go/+/428158
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
This commit is contained in:
cuiweixie 2022-09-03 14:35:41 +08:00 committed by Gopher Robot
parent 92b8f4e293
commit 2ee075dc47
5 changed files with 7 additions and 12 deletions

View file

@ -45,7 +45,7 @@ func (b *Builder) copyCheck() {
// String returns the accumulated string. // String returns the accumulated string.
func (b *Builder) String() string { func (b *Builder) String() string {
return *(*string)(unsafe.Pointer(&b.buf)) return unsafe.String(unsafe.SliceData(b.buf), len(b.buf))
} }
// Len returns the number of accumulated bytes; b.Len() == len(b.String()). // Len returns the number of accumulated bytes; b.Len() == len(b.String()).

View file

@ -24,5 +24,5 @@ func Clone(s string) string {
} }
b := make([]byte, len(s)) b := make([]byte, len(s))
copy(b, s) copy(b, s)
return *(*string)(unsafe.Pointer(&b)) return unsafe.String(&b[0], len(b))
} }

View file

@ -5,7 +5,6 @@
package strings_test package strings_test
import ( import (
"reflect"
"strings" "strings"
"testing" "testing"
"unsafe" "unsafe"
@ -27,15 +26,12 @@ func TestClone(t *testing.T) {
t.Errorf("Clone(%q) = %q; want %q", input, clone, input) t.Errorf("Clone(%q) = %q; want %q", input, clone, input)
} }
inputHeader := (*reflect.StringHeader)(unsafe.Pointer(&input)) if len(input) != 0 && unsafe.StringData(clone) == unsafe.StringData(input) {
cloneHeader := (*reflect.StringHeader)(unsafe.Pointer(&clone))
if len(input) != 0 && cloneHeader.Data == inputHeader.Data {
t.Errorf("Clone(%q) return value should not reference inputs backing memory.", input) t.Errorf("Clone(%q) return value should not reference inputs backing memory.", input)
} }
emptyHeader := (*reflect.StringHeader)(unsafe.Pointer(&emptyString)) if len(input) == 0 && unsafe.StringData(clone) != unsafe.StringData(emptyString) {
if len(input) == 0 && cloneHeader.Data != emptyHeader.Data { t.Errorf("Clone(%#v) return value should be equal to empty string.", unsafe.StringData(input))
t.Errorf("Clone(%#v) return value should be equal to empty string.", inputHeader)
} }
} }
} }

View file

@ -57,7 +57,7 @@ func TestCompareStrings(t *testing.T) {
// unsafeString converts a []byte to a string with no allocation. // unsafeString converts a []byte to a string with no allocation.
// The caller must not modify b while the result string is in use. // The caller must not modify b while the result string is in use.
unsafeString := func(b []byte) string { unsafeString := func(b []byte) string {
return *(*string)(unsafe.Pointer(&b)) return unsafe.String(unsafe.SliceData(b), len(b))
} }
lengths := make([]int, 0) // lengths to test in ascending order lengths := make([]int, 0) // lengths to test in ascending order

View file

@ -660,8 +660,7 @@ func TestMap(t *testing.T) {
} }
orig := "Input string that we expect not to be copied." orig := "Input string that we expect not to be copied."
m = Map(identity, orig) m = Map(identity, orig)
if (*reflect.StringHeader)(unsafe.Pointer(&orig)).Data != if unsafe.StringData(orig) != unsafe.StringData(m) {
(*reflect.StringHeader)(unsafe.Pointer(&m)).Data {
t.Error("unexpected copy during identity map") t.Error("unexpected copy during identity map")
} }