
1、字符在Go语言中字符由rune类型表示rune本质上是int32的别名用于表示Unicode码点。Go没有专门的字符类型字符可以存储在rune或byte类型中具体取决于字符的编码需求。字符字面量用单引号括起来可以是单个字符或转义序列var ch rune Apackage main import fmt import unsafe import _strings func main(){ var ch a fmt.Printf(值%v,类型%T,原样输出%c,占用字节数%d\n,ch,ch,ch,unsafe.Sizeof(ch)) //值97,类型int32,原样输出a,占用字节数4 //上述的值是字符a的Unicode码值类型是int32原样输出就是字符a格式化输出使用%c占用字节数是4个字节和int32一样。 }go语言的字符类型在Go语言中字符类型主要分为以下两种1. byte类型本质是uint8的别名占用1字节8位用于表示ASCII字符0-255范围内的字符声明方式var ch byte A2. rune类型本质是int32的别名占用4字节32位用于表示Unicode字符支持UTF-8编码可以处理中文等非ASCII字符声明方式var ch rune 中关键区别存储空间byte1字节 vsrune4字节编码支持byte仅ASCIIrune支持Unicode使用场景ASCII文本用byte多语言文本需用rune那么我们进一步研究上述我们定义一个字符cha为什么不是byte类型而是rune类型呢在 Go 里单引号字符字面量例如var ch a是一个无类型的整数常量按默认推断会成为runerune是int32的别名所以你看到的类型是int32unsafe.Sizeof(ch)返回 4。byte是uint8的别名占用 1 个字节。如果你想要 1 字节的字符需显式使用byte或转换。package main import fmt import unsafe func main() { var ch a // rune / int32大小 4 var b byte a // byte / uint8大小 1 fmt.Printf(%v %T %d\n, ch, ch, unsafe.Sizeof(ch)) fmt.Printf(%v %T %d\n, b, b, unsafe.Sizeof(b)) }如果你希望类型推断时得到 1 字节使用转换b : byte(a)。字符串里的字符我们可以理解为字符串是由字符组成的那么我们如何访问字符串里的字符package main import fmt import _unsafe import _strings //包前面加上_表示引入这个包但不直接使用它这样可以避免编译器报错 func main(){ str : Hello, World! fmt.Printf(值%v, 原样输出%c类型%T\n,str[2],str[2],str[2])//值108, 原样输出l类型uint8 //str[2]表示字符串str中索引为2的字符l返回的是该字符的ASCII码值类型是uint8 }这种情况类似于c/c访问方式也是借助数组那么go语言里的字符串长度是多少package main import fmt import unsafe import strings //包前面加上_表示引入这个包但不直接使用它这样可以避免编译器报错 func main(){ str : Hello, World! fmt.Printf(值%v, 原样输出%c类型%T\n,str[2],str[2],str[2])//值108, 原样输出l类型uint8 //str[2]表示字符串str中索引为2的字符l返回的是该字符的ASCII码值类型是uint8 fmt.Printf(字符串占用的字节数%d\n,unsafe.Sizeof(str))//字符串占用的内存大小字节数16 //字符串在Go语言中是一个不可变的字节序列包含一个指向底层数据的指针和一个长度字段因此占用16个字节8字节指针 8字节长度。 fmt.Printf(字符串占用的字节数%d\n,len(str))//字符串占用的字节数长度13 //len(str)返回字符串str中字符的数量即字符串的长度。在这个例子中字符串Hello, World!包含13个字符包括空格和标点符号因此len(str)返回13。 }len(s)返回字符串 s 的字节数UTF-8 编码的字节长度。unsafe.Sizeof(s)返回 Go 中string值的内存大小字符串头不是字符串内容长度。字符串在 Go 内部是一个两字段结构指针 长度在 64 位系统上通常是 16字节。如果想要字符Unicode code points的数量用utf8.RuneCountInString(s)或len([]rune(s))。要点unsafe.Sizeof给的是值的表示头部占用多少内存与字符串内容字节数无关len给的是内容的字节长度rune 数需用 utf8 或转换成[]rune计算。同时还需要注意的是一个汉字占用3字节如果字符串里有汉字按照一个汉字3字节长度计算package main import fmt import _unsafe import _strings //包前面加上_表示引入这个包但不直接使用它这样可以避免编译器报错 func main(){ var a 国 fmt.Printf(值%v, 原样输出%c类型%T\n,a,a,a) //值22269, 原样输出国类型int32 //go语言中汉字使用的是utf-8编码utf-8编码十进制中一个汉字占3个字节所以一个汉字在go语言中占用4个字节32位因此类型是int32 }所以如果输出字母的值会使用ascll输出如果是中文/其它则是utf-8编码输出事实上utf-8是ascll的超集两者是一个东西我们可以使用for循环遍历字符串go语言的for循环类似c/c一般去掉括号package main import fmt import _unsafe import _strings //包前面加上_表示引入这个包但不直接使用它这样可以避免编译器报错 func main(){ str : Hello, World! for i :0; i len(str); i { fmt.Printf(%c(%v) , str[i], str[i]) } //H(72) e(101) l(108) l(108) o(111) ,(44) (32) W(87) o(111) r(114) l(108) d(100) !(33) }但是很快发现如果字符串包含中文就失效了func main(){ str : 你好, World! for i :0; i len(str); i { fmt.Printf(%c(%v) , str[i], str[i]) } //ä(228) ½(189) (160) å(229) ¥(165) ½(189) ,(44) (32) W(87) o(111) r(114) l(108) d(100) !(33) }这是因为中文是复合字体for循环相当于输出byte类型上述提到过中文应该用rune类型因此可以使用range输出func main(){ str : 你好, World! for _, ch : range str { fmt.Printf(%c(%v) , ch, ch) }//你(20320) 好(22909) ,(44) (32) W(87) o(111) r(114) l(108) d(100) !(33) }修改字符串在Go语言中字符串是不可变的immutable因此无法直接修改字符串中的某个字符。需要通过以下方法间接实现修改1、将字符串转换为字节数组[]byte修改后再转回字符串注意此方法仅适用于ASCII字符修改多字节字符如中文可能导致乱码。2、处理Unicode字符如中文时使用[]rune类型转换为rune数组修改func main(){ str1 : Hello, World! //强制类型转换 bytes : []byte(str1) //将字符串转换为字节切片(数组) bytes[0] h //修改字节切片的第一个元素 fmt.Println(string(bytes)) //将字节切片转换回字符串并打印 str2 : 是兄弟来砍我 runes : []rune(str2) //将字符串转换为Unicode码点切片 runes[4] 抱 //修改Unicode码点切片的第5个元素 fmt.Println(string(runes)) //将Unicode码点切片转换回字符串并打印 } //hello, World! //是兄弟来抱我