在 Go 中,字符串本质上是一个不可变的只读的字节数组,也是一片连续的内存空间。
1、字面量
-
普通字符串
使用
""双引号,支持转义,不支持多行(要换行只能使用/n转义)。func main() { fmt.Println("hello \nword") } //输出 //hello //word -
原生字符串
使用反引号``,不支持转义,支持多行,原生字符串里的字符会原封不动的输出。
func main() { fmt.Println(`hello word`) } //输出 //hello //word
2、字符串的访问
-
字符串本质是字节数组,所以字符串的访问和数组的访问一样的。
-
字符串无法修改,只能覆盖。
import "fmt" func main() { //字符串的修改 str := "hello world" //str[0] = 'H' //无法修改,无法通过编译。 fmt.Println(str) str = "new hello world"//允许覆盖 fmt.Println(str) //字符串的转换 bytes := []byte(str) //将字符串转成byte数组,属于复制行为,将str的值复制一份,赋值给新的内存地址。 fmt.Println(bytes) bytes[0] = 'H' //修改的是新的字符串byte fmt.Println("old string: ", str, " new string: ", string(bytes)) }
3、字符串的长度
字符串的长度,其实并不是字面量的长度,而是字节数组的长度,只是大多数时候都是ANSCII字符,刚好能用一个字节表示,所以恰好与字面量长度相等,求字符串长度使用内置函数len。
import (
"fmt"
"unicode/utf8"
)
func main() {
str1 := "hello world" //一个英文字母占一个字节
str2 := "你好 世界" //在unicode中,一个中文字符,占三个字节
fmt.Println(len(str1), len(str2)) //11 13,len函数计算的字节数
fmt.Println(utf8.RuneCountInString(str1), utf8.RuneCountInString(str2)) //11 5,计算的是unicode字符数
}
4、字符串的拷贝
- 拷贝的两种方式:内置函数
copy和string.clone函数。
import (
"fmt"
"strings"
)
func main() {
str := "Hello World"
fmt.Println("old string:", str)
//使用内置函数完成copy
newStr := make([]byte, len(str)) //先根据原字符创建字节数组
copy(newStr, str)
fmt.Println("copy string:", string(newStr))
//使用strings.clone
cloneStr := strings.Clone(str)
fmt.Println("clone string:", cloneStr)
}
5、字符串的拼接
-
性能较差的两种方式(适合对性能要求不高的场景)
- 使用
+拼接
import ( "fmt" ) func main() { str1 := "hello" str2 := "world" str3 := str1 + str2 fmt.Println(str3) }- 使用
字节数组拼接
import ( "fmt" ) func main() { str1 := "hello " str2 := "world1" bytes1 := []byte(str1) bytes := append(bytes1, str2...) fmt.Println(string(bytes)) } - 使用
-
性能要求高场景下:
strings.Builder
import (
"fmt"
"strings"
)
func main() {
builder := strings.Builder{}
builder.WriteString("hello ")
builder.WriteString("world ")
builder.WriteString("go")
fmt.Println(builder.String())
}
6、字符串的遍历
- 使用
for遍历字符
import "fmt"
func main() {
str := "Hello World,第一个程序!"
//本质上遍历的是字节数组
//如果字符为英文字符,则刚好是一个字节
//如果字符为中文字符,则一个中文字符需要占3个字节,而遍历时,只有一个字节,所以产生乱码
for i := 0; i < len(str); i++ {
fmt.Printf("%c", str[i])
}
}
- 使用
for range遍历
import "fmt"
func main() {
str := "Hello World,第一个程序!"
//for range中,r的单位是一个rune(将str默认转成[]rune)
//rune本质上是int32,最大容量是3个字节,刚好存储一个中文字符,所以输出中文不会乱码
for i, r := range str {
fmt.Println(i, string(r))
}
}
- 使用
uft8包下的函数
func main() {
str := "hello 世界!"
for i, w := 0, 0; i < len(str); i += w {
r, width := utf8.DecodeRuneInString(str[i:])
fmt.Println(string(r))
w = width
}
}