引入
用于保存一段文本内容,Go 的字符串是 UTF-8 编码的。字符串是程序里用得最多的类型之一,处理用户输入、拼接日志、解析文件都离不开它。Go 的字符串是不可变的,这个设计和很多语言不一样,搞清楚它的特性和常用操作方式很重要。
正文
定义
定义
字符串是一段不可变的 UTF-8 编码字节序列。Go 里用双引号
"…"创建解释字符串,用反引号`…`创建原始字符串。strings包提供了丰富的字符串操作函数。
语法
// 解释字符串(支持转义)
var s1 string = "hello\nworld"
// 原始字符串(不转义)
var s2 string = `hello\nworld`
// 字符串拼接
var s3 string = "hello" + " " + "world"例子
创建字符串
s1 := "hello" // 解释字符串
s2 := `hello\nworld` // 原始字符串,\n 不会被转义
s3 := "" // 空字符串
fmt.Println(s1) // hello
fmt.Println(s2) // hello\nworld双引号字符串支持转义字符(\n、\t、\\ 等),反引号字符串原样保留所有内容,适合写多行文本或正则表达式。
字符串拼接
// + 运算符
s := "hello" + " " + "world"
// fmt.Sprintf
s = fmt.Sprintf("%s is %d years old", "Tom", 20)
// strings.Builder(大量拼接时性能最好)
var sb strings.Builder
sb.WriteString("hello")
sb.WriteString(" ")
sb.WriteString("world")
s = sb.String()少量拼接用 +,需要格式化用 fmt.Sprintf,循环里大量拼接用 strings.Builder。
常用操作
import "strings"
s := "Hello, World!"
strings.Contains(s, "World") // true
strings.HasPrefix(s, "Hello") // true
strings.HasSuffix(s, "!") // true
strings.Index(s, "World") // 7
strings.Replace(s, "World", "Go", 1) // "Hello, Go!"
strings.ToLower(s) // "hello, world!"
strings.ToUpper(s) // "HELLO, WORLD!"
strings.TrimSpace(" hi ") // "hi"
strings.Split("a,b,c", ",") // ["a" "b" "c"]
strings.Join([]string{"a", "b"}, "-") // "a-b"
strings.Repeat("ab", 3) // "ababab"
strings.Count("banana", "a") // 3长度和索引
s := "你好"
len(s) // 6(字节数,不是字符数)
utf8.RuneCountInString(s) // 2(字符数)
// 按字节索引
s[0] // 228(第一个字节)
// 按字符遍历
for i, r := range s {
fmt.Printf("%d: %c\n", i, r)
}
// 0: 你
// 3: 好len() 返回的是字节数,不是字符数。中文字符在 UTF-8 里占 3 个字节,所以 "你好" 的长度是 6。
字符串和字节切片互转
s := "hello"
// 字符串转字节切片
b := []byte(s) // [104 101 108 108 111]
// 字节切片转字符串
s2 := string(b) // "hello"因为字符串不可变,所以每次转换都会复制一份数据。
字符串比较
s1 := "abc"
s2 := "abc"
s1 == s2 // true(逐字节比较)Go 的字符串比较是逐字节的,不是按 Unicode 码点比较。
常见写法
| 写法 | 说明 |
|---|---|
"hello" | 解释字符串,支持转义 |
`raw` | 原始字符串,不转义 |
s1 + s2 | 简单拼接 |
fmt.Sprintf("%s", s) | 格式化拼接 |
strings.Builder | 高性能大量拼接 |
strings.Contains(s, sub) | 判断是否包含 |
strings.Split(s, sep) | 按分隔符切割 |
strings.Join(ss, sep) | 切片拼接为字符串 |
[]byte(s) | 字符串转字节切片 |
string(b) | 字节切片转字符串 |
特点
- 字符串是不可变的,任何修改操作都会创建新字符串
len()返回字节数,不是字符数,中文等多字节字符要注意- 用
range遍历字符串时,迭代的是 Unicode 码点(rune),不是字节 - 双引号字符串支持转义,反引号字符串原样保留
strings包是字符串操作的首选工具- 大量拼接用
strings.Builder,性能比+好很多 - 字符串的零值是
""(空字符串),不是nil
理解
Go 的字符串设计核心就是不可变 + UTF-8。不可变意味着安全(多线程不用加锁)但也意味着每次修改都是新对象。UTF-8 意味着能正确处理全球文字,但 len() 返回的是字节数不是字符数这个坑要记住。日常操作用 strings 包就够了,大量拼接记得用 strings.Builder。
引出
字符串里经常要处理数字文本,比如把 "42" 变成 42。接下来看 Go 数字,了解 Go 里整型和浮点型的详细用法,以及数字和字符串之间的转换。