4 回答

TA贡献1831条经验 获得超9个赞
Go 中的字符串一旦创建就不可变。去规范
我会更喜欢下面的builder。您继续添加到构建器的缓冲区(可变)WriteString 并且一旦完成调用String返回指针而不是缓冲区切片的另一个副本的方法。
somestring := "Hello Go"
var sb strings.Builder
if _, err := sb.WriteString(somestring); err != nil {
//log & return
}
newstring := sb.String()
从 go 源码检查 builder 的 String() 的实现。它返回指针并转换为 *string。没有第二份。
// String returns the accumulated string.
func (b *Builder) String() string {
return *(*string)(unsafe.Pointer(&b.buf))
}

TA贡献1828条经验 获得超13个赞
另一种选择是,从 go 1.18(2021 年第四季度)开始:
sCopy := strings.Clone(s)
它来自问题40200和45038,并从 CL(更改列表)334884和345849 开始
字节,字符串:添加克隆
直接使用
[]byte
并且string
很常见并且需要经常复制它们。
此更改Clone
为字符串和字节添加了一个助手来满足此需求。
还添加了一个基准,以提供证据说明为什么bytes.Clone
使用copy
.字符串:添加克隆功能
新
strings.Clone
函数复制输入字符串,但返回的克隆字符串不引用输入字符串内存
// 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))
}

TA贡献1842条经验 获得超12个赞
字符串被实现为指向底层字节数组和字符串长度的指针。当您从现有字符串创建切片时,新字符串仍指向基础数组,可能指向该数组中具有不同长度的不同偏移量。这样,许多小字符串可以使用单个底层大数组。
正如您所指出的,如果您有一个大字符串并将其解析为较小的字符串,那么您最终会将大字符串保留在内存中,因为 GC 只知道底层数组和指向它的指针。有两种方法可以处理这个问题:
不要使用大字符串,而是保留
[]byte
或使用基于字节流的读取器/扫描器,并在解析时从输入创建字符串。这样 GC 将[]byte
在解析完成时收集底层,并且您将拥有没有底层大块的字符串。执行您已经描述的操作,并使用
string([]byte(s[x:y]))
或使用copy
.

TA贡献1744条经验 获得超4个赞
使用以下函数深度复制字符串:
func deepCopy(s string) string {
b := make([]byte, len(s))
copy(b, s)
return *(*string)(unsafe.Pointer(&b))
}
该函数将数据复制到新分配的字节片中。该函数使用 unsafe 包将切片标头转换为不复制字节的字符串标头。
如果直接使用 unsafe 包是一个问题,那么使用strings.Builder。strings.Builder 类型在幕后执行不安全的恶作剧。
func deepCopy(s string) string {
var sb strings.Builder
sb.WriteString(s)
return sb.String()
}
无需检查 sb.WriteString 返回的错误。Builder.WriteString方法有错误返回,所以 Builder 类型满足 io.StringWriter接口,而不是因为 WriteString 可以返回非 nil 错误。
- 4 回答
- 0 关注
- 170 浏览
添加回答
举报