Go中的rune
是什么?
我一直在谷歌搜索,但Golang只用一行说: rune
是int32
的别名。
但是如何使用整数来交换整数?
以下是函数交换大小写。
什么是<=
和-
?
为什么switch
没有任何论据?
&&
应该是和,但是什么是r <= 'z'
?
func SwapRune(r rune) rune {
switch {
case 'a' <= r && r <= 'z':
return r - 'a' + 'A'
case 'A' <= r && r <= 'Z':
return r - 'A' + 'a'
default:
return r
}
}
大多数来自http://play.golang.org/p/H6wjLZj6lW
func SwapCase(str string) string {
return strings.Map(SwapRune, str)
}
我理解这是将rune
映射到string
,以便它可以返回交换的字符串。但我不明白rune
或byte
在这里是如何运作的。
答案 0 :(得分:113)
符文文字只是32位整数值(但它们是无类型常量,因此它们的类型可以更改)。它们代表unicode代码点。例如,符文字面'a'
实际上是数字97
。
因此,您的程序几乎相当于:
package main
import "fmt"
func SwapRune(r rune) rune {
switch {
case 97 <= r && r <= 122:
return r - 32
case 65 <= r && r <= 90:
return r + 32
default:
return r
}
}
func main() {
fmt.Println(SwapRune('a'))
}
很明显,如果你要查看Unicode映射,它与该范围内的ASCII相同。此外,32实际上是字符的大写和小写代码点之间的偏移。因此,通过将32
添加到'A'
,您会获得'a'
,反之亦然。
答案 1 :(得分:38)
来自Go lang发行说明:http://golang.org/doc/go1#rune
符文是一种类型。它占用32位,意味着代表Unicode CodePoint。
作为类比,以'ASCII'编码的英文字符集具有128个代码点。因此能够适合一个字节(8bit)。从这个(错误的)假设C处理的字符为'字节'char
,'字符串'作为'字符序列'char*
。
但猜猜是什么。除了'abcde ..'符号之外,人类还发明了许多其他符号。还有很多我们需要32位来编码它们。
在golang中,string
是bytes
的序列。但是,由于多个字节可以表示符文代码点,因此字符串值也可以包含符文。因此,它可以转换为[]rune
,反之亦然。
unicode包http://golang.org/pkg/unicode/可以体验挑战的丰富性。
答案 2 :(得分:22)
我没有足够的声誉向fabrizioM answer发表评论,所以我必须在此发布。
法布里奇奥的答案基本上是正确的,他当然抓住了问题的实质 - 尽管必须有所区别。字符串 NOT 必然是一系列符文。它是一个字节片段的包装器, slice 是Go数组的包装器。这有什么不同?
符文类型必须是32位值,这意味着符文类型的值序列必然具有一定数量的位x * 32。字符串是一个字节序列,而是长度为x * 8位。如果所有字符串实际上都是Unicode,则这种差异不会产生任何影响。但是,由于字符串是字节片,因此,Go可以使用ASCII或任何其他任意字节编码。
但是,字符串文字必须写入以UTF-8编码的源中。
答案 3 :(得分:17)
我试图保持我的语言简单,以便外行人理解rune
。
符文是一个角色。就是这样。
这是一个单一的角色。它是来自世界任何地方的任何语言的任何字母表中的字符。
要获取字符串,我们使用
double-quotes ""
OR
back-ticks ``
字符串与符文不同。在符文中我们使用
single-quotes ''
现在符文也是int32
的别名...呃什么?
符文是int32
的别名的原因是因为我们看到了编码方案,如下所示
每个字符映射到某个数字,因此它是我们存储的数字。例如, a 映射到 97 ,当我们存储该数字时,它只是数字,因此rune是int32的别名。 但不仅仅是任何数字。它是一个32'零和1'或'4'字节的数字。(注意:UTF-8是一个4字节编码方案)
符文与字符串的关系如何?
字符串是符文的集合。在以下代码中:
package main
import (
"fmt"
)
func main() {
fmt.Println([]byte("Hello"))
}
我们尝试将字符串转换为字节流。输出是:
[72 101 108 108 111]
我们可以看到构成该字符串的每个字节都是符文。
答案 4 :(得分:7)
其他人都涉及与符文有关的部分,所以我不打算谈论这个。
但是,还有一个问题与switch
没有任何争议有关。这只是因为在Golang中,没有表达式的switch
是表达if / else逻辑的另一种方式。例如,写下这个:
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
与撰写本文相同:
t := time.Now()
if t.Hour() < 12 {
fmt.Println("It's before noon")
} else {
fmt.Println("It's after noon")
}
您可以阅读更多here。
答案 5 :(得分:5)
(感觉上面的答案仍然没有很清楚地说明string
和[]rune
之间的区别和关系,所以我尝试用示例来添加另一个答案。)< / em>
正如@Strangework
的回答所说,string
和[]rune
完全不同。
差异-string
和[]rune
:
string value
是只读字节片。并且,字符串文字以utf-8编码。 string
中的每个字符实际上占用 1〜3 个字节,而每个rune
中的每个字符占用 4 个字节string
,len()
和索引都是基于字节的。[]rune
,len()
和索引都是基于符文(或int32)的。 关系-string
和[]rune
:
string
转换为[]rune
时,该字符串中的每个utf-8字符都将变成rune
。[]rune
转换为string
时,每个rune
在string
中成为utf-8字符。提示:
string
和[]rune
之间进行转换,但是在类型和整体大小上它们仍然是不同的。(我将添加一个示例以更清楚地说明这一点。)
string_rune_compare.go:
// string & rune compare,
package main
import "fmt"
// string & rune compare,
func stringAndRuneCompare() {
// string,
s := "hello你好"
fmt.Printf("%s, type: %T, len: %d\n", s, s, len(s))
fmt.Printf("s[%d]: %v, type: %T\n", 0, s[0], s[0])
li := len(s) - 1 // last index,
fmt.Printf("s[%d]: %v, type: %T\n\n", li, s[li], s[li])
// []rune
rs := []rune(s)
fmt.Printf("%v, type: %T, len: %d\n", rs, rs, len(rs))
}
func main() {
stringAndRuneCompare()
}
执行:
开始运行string_rune_compare.go
输出:
hello你好, type: string, len: 11
s[0]: 104, type: uint8
s[10]: 189, type: uint8
[104 101 108 108 111 20320 22909], type: []int32, len: 7
说明:
字符串hello你好
的长度为11,因为前5个字符每个仅占用1个字节,而后2个中文字符每个占用3个字节。
total bytes = 5 * 1 + 2 * 3 = 11
len()
基于字节,因此打印的第一行len: 11
uint8
的值(因为byte
是uint8
的别名类型,在行中)。 / li>
将string
转换为[]rune
时,它发现了7个utf8字符,因此有7个符文。
len()
上的[]rune
基于符文,因此最后一行打印了len: 7
。[]rune
,它将基于符文访问。len()
上的[]rune
和索引操作都基于utf8字符。答案 6 :(得分:0)
符文是int32值,因此它是Go类型,用于表示Unicode代码点。 Unicode代码点或代码位置是一个数字值,通常用于表示单个Unicode字符。
答案 7 :(得分:0)
程序
package main
import (
"fmt"
)
func main() {
words := "€25 or less"
fmt.Println("as string slice")
fmt.Println(words, len(words))
runes := []rune(words)
fmt.Println("\nas []rune slice")
fmt.Printf("%v, len:%d\n", runes, len(runes))
bytes := []byte(words)
fmt.Println("\nas []byte slice")
fmt.Printf("%v, len:%d\n", bytes, len(bytes))
}
输出
as string slice
€25 or less 13
as []rune slice
[8364 50 53 32 111 114 32 108 101 115 115], len:11
as []byte slice
[226 130 172 50 53 32 111 114 32 108 101 115 115], len:13
如您所见,欧元符号“€”由 3 个字节表示 - 226、130 和 172。 符文代表一个字符 - 任何字符,无论是象形文字。一个符文的 32 位足以代表当今世界上的所有字符。因此,欧元符号“€”的符文表示为 8364。
对于 128 个 ASCII 字符,一个字节(8 位)就足够了。因此,数字或字母的符文和字节表示是相同的。例如:2 用 50 表示。
字符串的字节表示总是大于或等于其符文表示的长度,因为某些字符由多于一个字节但在 32 位以内表示,这是符文。