内容简介:Go 中的字符串值得特别关注,与其他语言相比,Go 中的字符串实现方式有所不同。在Go中,使用双引号输出:
Go 中的字符串值得特别关注,与其他语言相比,Go 中的字符串实现方式有所不同。
字符串
在 Go 中,使用双引号 ""
声明字符串:
s := "Hello world" fmt.Println("len(s):",len(s)) fmt.Println(s); 复制代码
输出:
len(s): 11 Hello world 复制代码
上面的代码声明了字符串 s
, len
函数返回字符串 s
的字节数(包括空格)。 在 Go 中,字符串其实是只读的字节切片 。
s := "Hello world" for i:=0;i<len(s);i++ { fmt.Print(s[i]," ") } 复制代码
你觉得上面的代码会输出什么,是一个个字母吗?其实不是:
72 101 108 108 111 32 119 111 114 108 100 复制代码
输出的是每个字母在ASCII 码表上对应的十进制数字。 正如大家熟知的,Go 语言采用 UTF-8
编码,这种编码方式与 ASCII
编码兼容,只不过 ASCII
编码只需 1 个字节,而 UTF-8
需要 1-4 个字节表示一个符号。
s := "Hello world" for i:=0;i<len(s) ;i++ { fmt.Printf("%c ",s[i]) } fmt.Println("") for i:=0;i<len(s) ;i++ { fmt.Printf("%v ",s[i]) } fmt.Println("") for i:=0;i<len(s) ;i++ { fmt.Printf("%x ",s[i]) } fmt.Println("") for i:=0;i<len(s) ;i++ { fmt.Printf("%T ",s[i]) } 复制代码
输出 :
H e l l o w o r l d 72 101 108 108 111 32 119 111 114 108 100 48 65 6c 6c 6f 20 77 6f 72 6c 64 uint8 uint8 uint8 uint8 uint8 uint8 uint8 uint8 uint8 uint8 uint8 复制代码
上面的代码, %v
格式化输出字节对应的十进制值; %x
以十六进制输出; %T
格式化输出值的类型。从结果可以看出,值的类型都是 uint8
即 byte
类型, type
是 uint8
的别名, byte
类型在我的文章中有所介绍。 我们来看下: 一个字符串中包含非 ASCII
码的字符 会是怎样的情况。
s := "Hellõ World" fmt.Println("len(s):", len(s)) for i := 0; i < len(s); i++ { fmt.Printf("%c ", s[i]) } fmt.Println("") for i := 0; i < len(s); i++ { fmt.Printf("%v ", s[i]) } fmt.Println("") for i := 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) } 复制代码
输出 :
len(s): 12 H e l l à µ W o r l d 72 101 108 108 195 181 32 87 111 114 108 100 48 65 6c 6c c3 b5 20 57 6f 72 6c 64 复制代码
上面的例子中,将 o
替换成 õ
。从结果可以看出,字符串的字节长度是 12 ,说明 õ
占用两个字节。然而 õ
的输出变成了 Ã µ
, õ
的 Unicode
码点是 U+00F5
,其UTF-8 编码 占两个字节 c3
、 b5
。 for
循环按字节读取, c3
(十进制 195 )对应字符 Ã
, b5
(十进制 181 )对应字符 µ
(详见这里)。 熟悉 ASCII
、 UTF-8
和 Unicode
更有利于理解这些知识,关于这些知识,不会在本文展开细讲,有兴趣的可以参考这里。 UTF-8
编码中,一个码点占用至少一字节,如果我们还是以一个码点占用一个字节去打印字符肯定会出问题,就像上面的例子一样。那有没有办法解决这个问题,好在 Go 为我们提供了 rune
。
Rune
rune
是 Go 的内置数据类型,是 int32
的别名,表示 Go 中的 Unicode
代码点。用 rune
数据类型,开发人员就不必关心代码点占用几个字节了。
s := "Hellõ World" r := []rune(s) fmt.Println("len(r):", len(r)) for i := 0; i < len(r); i++ { fmt.Printf("%c ", r[i]) } fmt.Println("") for i := 0; i < len(r); i++ { fmt.Printf("%v ", r[i]) } fmt.Println("") for i := 0; i < len(r); i++ { fmt.Printf("%x ", r[i]) } fmt.Println("") for i := 0; i < len(r); i++ { fmt.Printf("%T ", r[i]) } 复制代码
输出 :
len(r): 11 H e l l õ W o r l d 72 101 108 108 245 32 87 111 114 108 100 48 65 6c 6c f5 20 57 6f 72 6c 64 int32 int32 int32 int32 int32 int32 int32 int32 int32 int32 int32 复制代码
上面的代码,字符串 s
通过类型转化成了 rune
切片。 õ
的 Unicode
码点就是 U+00F5
,对应十进制的 245 ,参考这。切片 r
的长度就是:11 ;输出的 int32
,印证了 rune
是 int32
的别名。
for range
字符串
上面的例子已经很好解决了之前遇到的问题,有种更好的方式 -- range string
。使用 range
循环一个字符串,将返回 rune
类型的字符和字节索引。
s := "HellõWorld" for index, char := range s { fmt.Printf("%c starts at byte index %d \n", char,index) } 复制代码
输出 :
H starts at byte index 0 e starts at byte index 1 l starts at byte index 2 l starts at byte index 3 õ starts at byte index 4 W starts at byte index 6 o starts at byte index 7 r starts at byte index 8 l starts at byte index 9 d starts at byte index 10 复制代码
从输出结果可以看出, õ
占用了两个字节:索引 4 和 5。
文章读到这,可能会有个疑问,怎么获取字符串的长度呢?
Length of the string
可以使用 RuneCountInString()
函数,原型是这样的:
func RuneCountInString(s string) (n int) 复制代码
返回字符串中 rune
字符的个数。
s := "Hellõ 中国" length := utf8.RuneCountInString(s) fmt.Println(length) 复制代码
输出:8
字符串是不可变的
前面我们已经说过,字符串是只读的字节切片,一旦创建,是不可更改的。如果强制修改,就会报错:
s := "Hello World" s[0] = "h" 复制代码
报错: cannot assign to s[0]
这篇文章有几个比较 重要 的点:
- 字符串是只读的字节切片;
-
rune
表示 Go 中的Unicode
代码点; - Go 采用
UTF-8
编码,这种编码方式是Unicode
的实现方式之一; - 熟悉
ASCII
、UTF-8
和Unicode
,可以参考这,更有利于理解这篇文章;
希望这篇文章能够解决你对 Go string
的一些疑问,有不懂的可以留言讨论!
关注公众号「Golang来了」,获取最新文章!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据挖掘导论
Pang-Ning Tan、Michael Steinbach、Vipin Kumar / 范明、范宏建 / 人民邮电出版社 / 2010-12-10 / 69.00元
本书全面介绍了数据挖掘,涵盖了五个主题:数据、分类、关联分析、聚类和异常检测。除异常检测外,每个主题都有两章。前一章涵盖基本概念、代表性算法和评估技术,而后一章讨论高级概念和算法。这样读者在透彻地理解数据挖掘的基础的同时,还能够了解更多重要的高级主题。 本书是明尼苏达大学和密歇根州立大学数据挖掘课程的教材,由于独具特色,正式出版之前就已经被斯坦福大学、得克萨斯大学奥斯汀分校等众多名校采用。 ......一起来看看 《数据挖掘导论》 这本书的介绍吧!