【Go】字符串相关问题

点击阅读更多查看文章内容

字符串遍历问题

在使用for i,v:=range str遍历字符串时

  • str[i]是unit8(byte)类型,返回的是单个字节
    字符串在Go中是以字节序列的形式存储的,而 str[i] 直接访问了这个字节序列中的第 i 个字节。如果字符串中的字符是单字节的ASCII字符,那么 s[i] 就足以表示该字符。但是,如果字符是多字节的Unicode字符,那么 s[i] 就只是该字符的第一个字节,而不是整个字符。

  • v是int32(rune)类型,返回的是字符的unicode编码

1
2
3
4
5
6
7
8
9
10
11
12
func main() {
str := "hello,world!你好,世界!"
for i, _ := range str {
fmt.Print(str[i], " ")
}
//104 101 108 108 111 44 119 111 114 108 100 33 228 229 239 228 231 239
fmt.Println()
for _, v := range str {
fmt.Print(v, " ")
}
//104 101 108 108 111 44 119 111 114 108 100 33 20320 22909 65292 19990 30028 65281
}

字符串高效拼接

Go 中,字符串拼接有多种方式,包括 strings.Join++=)、bytes.Bufferstrings.Builder

方法 适用场景 性能 内存分配次数 线程安全 备注
strings.Join 已知字符串切片拼接 ⭐⭐⭐⭐⭐ 1 次 最快(预分配内存)
+ / += 少量拼接 ⭐⭐ 多次 每次拼接都生成新字符串
bytes.Buffer 通用字节/字符串操作 ⭐⭐⭐ 1 次 适合混合操作字节和字符串
strings.Builder 高性能字符串拼接 ⭐⭐⭐⭐ 1 次 慢于join(零拷贝优化)

(1) strings.Join(最快,适用于已知字符串切片)

特点:先预分配内存,后使用strings.Builder拼接

1
2
parts := []string{"Hello", "World", "!"}
result := strings.Join(parts, " ") // "Hello World !"

适用场景:已有字符串切片,需要拼接成单个字符串。

(2) + / +=(简单但低效)

特点:每次拼接都生成新字符串,导致多次内存分配。

1
2
s := "Hello"
s += " " + "World" + "!" // 每次 += 都生成新字符串

适用场景:少量字符串拼接(如少于 5 次)。

(3) bytes.Buffer(通用,线程安全)

特点

  • 内存预分配,仅 1 次内存分配
  • 线程安全(方法内部加锁)
  • 支持混合写入 string[]bytebyterune
1
2
3
4
5
var buf bytes.Buffer
buf.WriteString("Hello")
buf.WriteString(" ")
buf.WriteString("World!")
result := buf.String() // "Hello World!"

适用场景

  • 需要混合操作字节和字符串。

  • 需要线程安全(但加锁可能影响性能)。

(4) strings.Builder(最高效,非线程安全)

特点

  • 零拷贝优化String() 直接转换底层 []byte)。
  • 最快,比 bytes.Buffer 快约 20%~30%。
  • 非线程安全(需自行管理同步)。

示例

1
2
3
4
5
var builder strings.Builder
builder.WriteString("Hello")
builder.WriteString(" ")
builder.WriteString("World!")
result := builder.String() // "Hello World!"

适用场景

  • 高频字符串拼接(如循环内拼接)。
  • 不需要线程安全(或自行加锁)。
作者

ShiHaonan

发布于

2024-07-09

更新于

2025-04-27

许可协议

评论