字符串是编程中最常用的数据类型之一。Go语言中的字符串是只读的字节切片,支持UTF-8编码。标准库中的strings、strconv、unicode、regexp等包提供了强大的字符串处理能力。本章将系统介绍字符串的常用操作,以及高效处理字符串的最佳实践。
rune代表Unicode码点;使用strings.Builder高效拼接字符串。
字符串本质上是只读的字节序列。使用len()获取字节长度,而非字符数量。如需遍历字符,应使用for range。
package main
import "fmt"
func main() {
s := "Go语言"
fmt.Println("字节长度:", len(s)) // 8 (G o 语 言 每个中文字符占3字节)
fmt.Println("字符数:", len([]rune(s))) // 4
for i, ch := range s { // range 按 rune 遍历
fmt.Printf("%d: %c\n", i, ch)
}
}
import "strings"
s := "hello world"
fmt.Println(strings.Contains(s, "world")) // true
fmt.Println(strings.ContainsAny(s, "abc")) // false
fmt.Println(strings.HasPrefix(s, "he")) // true
fmt.Println(strings.HasSuffix(s, "ld")) // true
fmt.Println(strings.Index(s, "o")) // 4 (第一次出现)
fmt.Println(strings.LastIndex(s, "o")) // 7
fmt.Println(strings.Count(s, "l")) // 3
upper := strings.ToUpper("hello") // HELLO
lower := strings.ToLower("WORLD") // world
title := strings.Title("hello world") // Hello World (注意:仅单词首字母大写)
s := " hello "
fmt.Println(strings.TrimSpace(s)) // "hello"
fmt.Println(strings.Trim(s, " ")) // 同上
fmt.Println(strings.TrimLeft(s, " ")) // "hello "
fmt.Println(strings.TrimRight(s, " ")) // " hello"
fmt.Println(strings.TrimPrefix("file.txt", "file.")) // "txt"
// 分割
arr := strings.Split("a,b,c", ",") // []string{"a","b","c"}
arr2 := strings.SplitN("a,b,c", ",", 2) // []string{"a","b,c"}
arr3 := strings.Fields("hello world") // 按空白分割,自动忽略多余空格: ["hello","world"]
// 合并
joined := strings.Join(arr, "-") // "a-b-c"
// 替换 (n为-1表示全部替换)
newStr := strings.Replace("go go go", "go", "Go", 2) // "Go Go go"
newStr2 := strings.ReplaceAll("go go", "go", "Go") // "Go Go"
repeated := strings.Repeat("na", 3) // "nanana"
import "strconv"
// 字符串转整数
i, err := strconv.Atoi("123") // 123, nil
i2, err := strconv.ParseInt("ff", 16, 64) // 255, nil
u, err := strconv.ParseUint("100", 10, 64) // 100, nil
// 整数转字符串
s := strconv.Itoa(456) // "456"
s2 := strconv.FormatInt(255, 16) // "ff"
// 浮点数转换
f, err := strconv.ParseFloat("3.1415", 64) // 3.1415, nil
s3 := strconv.FormatFloat(3.1415, 'f', -1, 64) // "3.1415"
// 布尔转换
b, err := strconv.ParseBool("true") // true, nil
s4 := strconv.FormatBool(true) // "true"
使用+拼接大量字符串效率低下。推荐使用strings.Builder(Go 1.10+)。
var builder strings.Builder
builder.WriteString("Hello")
builder.WriteString(", ")
builder.WriteString("World")
builder.WriteByte('!')
result := builder.String() // "Hello, World!"
fmt.Println(result)
// 预分配容量可提高效率
builder.Grow(100) // 预分配100字节容量
+或fmt.Sprintf也可;大量拼接或循环中务必使用strings.Builder。regexp包提供了强大的模式匹配功能。
import "regexp"
// 匹配测试
matched, _ := regexp.MatchString(`\d+`, "abc123def") // true
// 编译正则表达式
re := regexp.MustCompile(`\d+`)
// 查找首个匹配
first := re.FindString("abc123def456") // "123"
// 查找所有匹配
all := re.FindAllString("a1b2c3", -1) // ["1","2","3"]
// 替换
replaced := re.ReplaceAllString("a1b2c3", "X") // "aXbXcX"
// 分组提取
reEmail := regexp.MustCompile(`(\w+)@(\w+)\.com`)
parts := reEmail.FindStringSubmatch("user@example.com")
fmt.Println(parts[1]) // "user"
对于字节数据,使用bytes包,其API与strings包类似,但操作[]byte。
import "bytes"
b := []byte("hello world")
contains := bytes.Contains(b, []byte("world"))
split := bytes.Split(b, []byte(" "))
unicode/utf8和unicode包提供UTF-8编解码及字符类别判断。
import "unicode/utf8"
s := "Go语言"
fmt.Println(utf8.RuneCountInString(s)) // 4
fmt.Println(utf8.ValidString(s)) // true
// 判断字符类别
import "unicode"
for _, ch := range s {
if unicode.IsLetter(ch) {
fmt.Printf("%c 是字母\n", ch)
}
}
package main
import (
"fmt"
"strings"
)
func main() {
logLines := []string{
"[INFO] 2025-01-15 服务启动",
"[ERROR] 2025-01-15 数据库连接失败",
"[INFO] 2025-01-15 重试连接",
"[ERROR] 2025-01-15 超时",
"[WARN] 2025-01-15 配置过期",
}
var infoCount, errorCount int
for _, line := range logLines {
switch {
case strings.Contains(line, "[INFO]"):
infoCount++
case strings.Contains(line, "[ERROR]"):
errorCount++
}
// 提取日期(假设格式固定)
if idx := strings.Index(line, "2025"); idx != -1 {
date := strings.Fields(line)[1] // 第二个字段为日期
fmt.Println("日志日期:", date)
}
}
fmt.Printf("统计: INFO=%d, ERROR=%d\n", infoCount, errorCount)
// 高效拼接统计结果
var builder strings.Builder
builder.WriteString("最终报告: ")
builder.WriteString(fmt.Sprintf("INFO:%d, ERROR:%d", infoCount, errorCount))
fmt.Println(builder.String())
}
strings、strconv、regexp等包,可以轻松应对文本处理、日志解析、数据校验等需求。下一章我们将学习Go语言中的JSON处理。