不积跬步,无以至千里;不积小流,无以成江海。
码字不易,点赞再看。
byte
占用1个节字,也就是 8 个比特位,所以它和 uint8 类型本质上没有区别,它表示的是 ACSII 表中的一个字符。
如下这段代码,分别定义了 byte 类型和 uint8 类型的变量 a 和 b
import "fmt"
func main() {
var a byte = 65
// 8进制写法: var c byte = '\101' 其中 \ 是固定前缀
// 16进制写法: var c byte = '\x41' 其中 \x 是固定前缀
var b uint8 = 66
fmt.Printf("a 的值: %c \nb 的值: %c", a, b)
// 或者使用 string 函数
// fmt.Println("a 的值: ", string(a)," \nb 的值: ", string(b))
}
在 ASCII 表中,由于字母 A 的ASCII 的编号为 65 ,字母 B 的ASCII 编号为 66,所以上面的代码也可以写成这样
import "fmt"
func main() {
var a byte = 'A'
var b uint8 = 'B'
fmt.Printf("a 的值: %c \nb 的值: %c", a, b)
}
两段代码输出的结果都一样
a 的值: A
b 的值: B
rune
占用4个字节,共32位比特位,所以它和 int32 本质上也没有区别。它表示的是一个 Unicode字符(Unicode是一个可以表示世界范围内的绝大部分字符的编码规范)由于 byte 类型能表示的值是有限,只有 2^8=256 个。当需要处理中文
、日文
或者其他复合字符
时,则需要用到rune类型。
import (
"fmt"
"unsafe"
)
func main() {
var a byte = 'A'
var b rune = 'B'
fmt.Printf("a 占用 %d 个字节数\nb 占用 %d 个字节数", unsafe.Sizeof(a), unsafe.Sizeof(b))
}
输出:
a 占用 1 个字节数
b 占用 4 个字节数
不管是 byte 还是 rune ,都是使用 单引号
,而没使用 双引号
。
注意:在 Go 中单引号与 双引号并不是等价的
。
单引号用来表示 字符
,在上面的例子里,如果你使用双引号,就意味着你要定义一个字符串,赋值时与前面声明的前面会不一致,这样在编译的时候就会出错。
cannot use "B" (type untyped string) as type rune in assignment
####### 疑问
byte 和 uint8 没有区别,rune 和 int32 没有区别,那为什么还要多出 byte 和 rune 类型呢?不是多此一举
理由很简单,因为uint8 和 int32 ,直观上让人以为这是一个数值,但是实际上,它也可以表示一个字符,所以为了消除这种直观错觉,就诞生了 byte 和 rune 这两个别名类型。
string
Go语言中的字符串以原生数据类型出现,使用字符串就像使用其他原生数据类型(int、bool、float32、float64 等)一样。 Go 语言里的字符串的内部实现使用UTF-8编码。 字符串的值为双引号(")中的内容,可以在Go语言的源码中直接添加非ASCII码字符,例如:
s1 := "hello"
s2 := "你好"
golang中的字符串底层实际上是一个 byte数组
。因此可能会出现下面这种情况
str := "hello 世界"
fmt.Println(len(str)) //输出 12
我们期望得到的结果应该是8,原因是golang中的string底层是由一个byte数组实现的,而golang默认的编码是utf-8,一个中文字符占 3个字节
,所以得到的长度是12,想要得到我们想要的结果也很简单,golang中的unicode/utf8
包提供了用utf-8获取长度的方法
str := "hello 世界"
fmt.Println(utf8.RuneCountInString(str)) //8
上面说了byte类型实际上是一个int8类型,int8适合表达ascii编码的字符,而int32可以表达更多的数,可以更容易的处理unicode字符,因此,我们可以通过rune类型来处理unicode字符
str := "hello 世界"
str2 := []rune(str)
fmt.Println(len(str2)) //8
这里会将申请一块内存,然后将str的内容复制到这块内存,实际上这块内存是一个rune类型的切片,而str2拿到的是一个rune类型的切片的引用,我们可以很容易的证明这是一个引用
str := "hello 世界"
str2 := []rune(str)
t := str2
t[0] = 'w'
fmt.Println(string(str2)) //“wello 世界”
通过把str2赋值给t,t上改变的数据,实际上是改变的是t指向的rune切片,因此,str也会跟着改变
字符串的遍历
// 遍历字符串
func traversalString() {
s := "hello 世界"
for i := 0; i < len(s); i++ { //byte
fmt.Printf("%v(%c) ", s[i], s[i])
}
fmt.Println()
for _, r := range s { //rune
fmt.Printf("%v(%c) ", r, r)
}
fmt.Println()
}
修改字符串
要修改字符串,需要先将其转换成[]rune或[]byte,完成后再转换为string。无论哪种转换,都会重新分配内存,并复制字节数组。
func changeString() {
s1 := "big"
// 强制类型转换
byteS1 := []byte(s1)
byteS1[0] = 'p'
fmt.Println(string(byteS1))
s2 := "白萝卜"
runeS2 := []rune(s2)
runeS2[0] = '红'
fmt.Println(string(runeS2))
}
字符串转义符
Go 语言的字符串常见转义符包含回车、换行、单双引号、制表符等,如下表所示。
例如:
package main
import (
"fmt"
)
func main() {
fmt.Println("str := \"d:\\Code\\work\\go.exe\"")
}
多行字符串
Go语言中要定义一个多行字符串时,就必须使用反引号字符:
s1 := `第一行
第二行
第三行
`
fmt.Println(s1)
反引号
间换行将被作为字符串中的换行,但是 所有
的转义字符均无效,文本将会原样输出。
字符串的常用操作
点关注 不迷路
如果你从本篇内容有收获,求 点赞
,求 关注
,求 转发
,让更多的人学习到。
如果本文有任何错误,请批评指教,不胜感激
有疑问加站长微信联系(非本文作者)