rune
、byte
和string
都是Go
的内置类型
byte
- byte是
uint8
的别名,在所有方面都等同于uint8
- 按惯例,它用于区分字节值和8位无符号整数值。
- byte是
rune
rune
是int32
的别名,在所有方面都等同于int32
- 按惯例,它用于区分字符值和整数值。
string
- string是所有8位字节字符串的集合,通常但不一定代表UTF-8编码的文本
- 字符串可能为空,但是不能为
nil
- 字符串类型的值是不可变的
- 由上面得解释我们大概可以明白
rune
可以表示得比byte
多string
类型的底层是一个byte
数组- 以上解释都来此
Go
源码注释
-
刚刚上面标注了字节和字符,现在我们来梳理字符和字节的概念
-
存储单位 字节
- 计算机存储信息的最小单位,称之为位
bit
,二进制的一个0
或1
叫一位 - 计算机存储容量基本单位是字节
Byte
,8个二进制位组成1
个字节
- 计算机存储信息的最小单位,称之为位
-
信息表示单位 字符
- 字符 是一种符号,像 英文
a
和中文阿
就是不同字符 - 不同的字符在不同的编码格式下,所需要的存储单位不一样
ASCLII
编码中一个英文字母一字节,一个汉字两字节UTF-8
编码中 一个英文字母一字节,一个常见汉字3字节,不常用的超大字符集汉字4字节
- 字符 是一种符号,像 英文
Go
源码文件默认采用Unicode
字符集,Unicode
码点和内存中字节序列的变换实现使用了UTF-8
,这使得Go
编程无需考虑编码转换的问题非常方便- 从编码上来分析
byte
用来强调一个字节代表的数据(例如字符a
就是97
),而不是数字;rune
用来表示Unicode
的码点,即一个字符
- 通俗一点
byte
只能操作简单的字符,不支持中文操作rune
能操作任何字符
- 代码演示
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
str := "hello 世界!"
fmt.Println(str)
fmt.Println(len(str))
fmt.Println(utf8.RuneCountInString(str))
fmt.Println(str[1])
fmt.Println(string(str[1]))
fmt.Println(str[1:])
fmt.Println(str[7:])
}
*************************************
输出
hello 世界!
13
9
101
e
ello 世界!
��界!
- 会输出
hello 世界!
,这证明Go
是UTF-8
编码的,输出长度为13
这说明了一个汉字3字节 - 输出
ello 世界!
说明string
底层的数据结构是数组 - 输出
��界!
说明string
底层是一个byte
数组,不然不会乱码
package main
import "fmt"
func StrChangeByRune(str *string, i int, ch rune) {
temp := []rune(*str)
temp[i] = ch
*str = string(temp)
}
func StrChangeByByte(str *string, i int, ch byte) {
temp := []byte(*str)
temp[i] = ch
*str = string(temp)
}
func main() {
str := "你好 hello"
str1 := "你好 hello"
StrChangeByRune(&str, 1, 'A')
StrChangeByByte(&str1, 1, 'A')
fmt.Println(str)
fmt.Println(str1)
}
*******************************
输出
你A hello
�A�好 hello
- 由输出
你A hello
和�A�好 hello
可以看出 byte
的操作单位是一个字节,可以理解为一个英文字符rune
的操作单位是一个字符,不管这个字符是什么字符