在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
在go中,所有字符都是utf8编码的,一个英文字符占1个字节,一个中文汉字占3个字节。 假如有一个字符串str,str:="我是koushr" 一、取字节长度: 方法1: len(str)。是的,len函数处理字符串时,取的是字节数,而不是字符数。 方法2: 利用utf8包的DecodeRuneInString函数,函数的第一个返回值即是字节数。?????
二、取字符长度: 转成rune数组,取数组长度
三、取子字符串: go内置了一种方法,在字符串后面直接跟中括号,中括号里面用冒号分隔两个数字,第一个数字是起始索引,第二个数字是终止索引,最终截取的字符串包括前面不包括后面,这个截取方法是按照字节截取的,即那两个数字都是字节索引。如果字符串都是英文,那么字节索引就是字符索引,如果包含中文或者特殊字符,那么字节索引就不是字符索引了。 标准做法是,把字符串转成rune数组,然后截取这个数组(数组截取和go内置的字符串截取方式一样,都是后面直接跟中括号。。。),截取时传字符索引即可,把截取到的数组转成字符串即可得到想要的字符串。 示例如下: func main() { str := "我是中国人" a := str[1:3] fmt.Println(a) b := []rune(str) c := b[1:3] fmt.Println(string(c)) }
四、子串索引 strings包的indexXXX方法,返回的字节索引。 示例如下: func main() { str := "我是中国人" a := "是" i := strings.Index(str, a) fmt.Println(i) } 上例i的值是3,而不是1。 如果想返回字符索引,则需要我们自定义一个函数,函数处理逻辑是先获取子串的字节索引,然后把这个索引之前的字符串截取出来,转成rune数组,而数组长度就是子串的字符索引。 示例如下: func main() { str := "我是中国人" a := "是" j := UnicodeIndex(str, a) fmt.Println(j) } func UnicodeIndex(str, substr string) int { // 子串在字符串的字节位置 result := strings.Index(str, substr) if result >= 0 { prefix := str[0:result] // 将子串之前的字符串转换成[]rune rs := []rune(prefix) // 获得子串之前的字符串的长度,便是子串在字符串的字符位置 result = len(rs) } return result }
基础概念: 在go中,string本质上是一个字节数组([]byte)。 Unicode和UTF-8的关系: Unicode是一个编码表,和ASCII是同一种东西。2021年9月公布的Unicode14.0版本已经有14.4w+个字符。基本上每年都会公布一个版本,扩增一些新字符。 UTF-8是一种对Unicode的编码方式,和UTF-16、UTF-16BE、UTF-16LE是同一种东西。UTF-8对一个字符使用1-4个字节进行编码。 字符在编码表中的编号叫做Code Point,中文翻译成码点。 rune的值表示字符的码点。将string转换成rune数组,数组里面其实就是一个个字符对应的码点。因为Unicode已经有14.4w+个字符,所以rune的最大值不能小于14.4w+,而int16最大值是216/2-1即32767,不满足要求,所以rune底层类型至少是int32。rune底层类型正是int32,int32最大值是10.5亿,足够了。 |
请发表评论