什么是符文?

在Go中rune是什么?

我一直在谷歌,但Golang只说了一行:__ABC0是int32的别名

但是为什么整数会像交换一样被广泛使用呢?

下面是一个函数交换例。 <=-是什么?< / p >

为什么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,以便它可以返回交换后的字符串。但我不明白runebyte在这里是如何工作的。

149774 次浏览

符文文字只是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映射,这应该是很明显的,它在该范围内与美国信息交换标准代码相同。此外,32实际上是字符的大写和小写码位之间的偏移量。因此,通过将32添加到'A',你会得到'a',反之亦然。

来自Go lang发布说明:http://golang.org/doc/go1#rune

符文是一个类型。它占用32位,用于表示Unicode CodePoint。 作为一个类比,用“ASCII”编码的英语字符集有128个码位。这样就可以装进一个字节(8位)。根据这个(错误的)假设,C将字符视为'bytes' char,将'strings'视为'sequence of characters' char*

但你猜怎么着。除了abcde,人类还发明了许多其他的符号。的符号。有太多了,我们需要32位来编码它们。

在golang中,stringbytes的序列。然而,由于多个字节可以表示一个符文代码点,字符串值也可以包含符文。因此,它可以被转换为[]rune,反之亦然。

unicode包http://golang.org/pkg/unicode/可以让你体会到挑战的丰富程度。

我没有足够的声誉张贴评论fabrizioM的回答,所以我将不得不张贴在这里代替。

法布里齐奥的回答在很大程度上是正确的,他当然抓住了问题的本质——尽管必须加以区分。

字符串必然是一个符文序列。它是一个“字节片”的包装,是一个Go数组的包装。这又有什么区别呢?

符文类型必须是一个32位的值,这意味着符文类型的值序列必须具有x*32位的位数。字符串是一个字节序列,长度为x*8位。如果所有字符串实际上都是Unicode,那么这种差异将没有影响。然而,由于字符串是字节片, Go可以使用ASCII或任何其他任意字节编码。

然而,字符串字面量必须写入以UTF-8编码的源文件中。

信息来源:http://blog.golang.org/strings

我尽量使我的语言简单,这样外行也能理解rune

符文是一个字符。就是这样。

它是一个单一的字符。它是来自世界上任何地方任何语言的任何字母表中的一个字符。

来获取我们使用的字符串

double-quotes ""

back-ticks ``

字符串不同于符文。在我们使用的符文中

single-quotes ''

现在一个符文也是int32的别名…嗯什么?

rune是int32的别名的原因是因为我们在如下的编码方案中看到了它 enter image description here < / p >

每个字符映射到一个数字,所以这就是我们要存储的数字。例如,一个映射到97,当我们存储这个数字时,它只是一个数字,所以rune是int32的别名。但不是任何数字。它是一个有32个“0和1”或“4”字节的数字。(注意:UTF-8是一个4字节的编码方案)

符文和字符串有什么关系?

字符串是符文的集合。在以下代码中:

    package main


import (
"fmt"
)


func main() {
fmt.Println([]byte("Hello"))
}

我们尝试将字符串转换为字节流。输出结果为:

[72 101 108 108 111]

我们可以看到,组成该字符串的每个字节都是一个符文。

其他所有人都已经介绍了与符文相关的部分,所以我不打算谈论这个。

然而,还有一个与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")
}

你可以阅读更多在这里

(有一种感觉,上面的答案仍然没有说明差异&string[]rune之间的关系非常清楚,所以我会尝试用一个例子来补充另一个答案。)

正如@Strangework的答案所说,string[]rune是完全不同的。

差异- string &[]rune:

  • string value是一个只读字节片。并且,字符串文字用utf-8编码。string中的每个字符实际上占用1 ~ 3字节,而每个rune占用4字节
  • 对于stringlen()和index都是基于字节的。
  • 对于[]runelen()和index都基于符文(或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的值(因为byteuint8的别名类型,在go中)。
  • 当将string转换为[]rune时,它发现了7个utf8字符,因此有7个符文。

    • 由于[]rune上的len()基于符文,因此最后一行打印出len: 7
    • 如果你通过索引操作[]rune,它将基于符文访问。
      由于每个符文都来自原始字符串中的utf8字符,因此你也可以说len()[]rune上的索引操作都基于utf8字符

符文是一个int32值,因此它是一种Go类型,用于表示Unicode码位。Unicode码位是通常用于表示单个Unicode字符的数值;

程序

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位,这是一个符文。

https://play.golang.org/p/y93woDLs4Qe

rune是int32的别名,在所有方面都等效于int32。它是 用于区分字符值和整型值

l = 108, o = 111

Rune是int32类型的别名。它表示一个单一的Unicode码位。 统一码联盟(Unicode Consortium)为超过100万个独特的字符分配数字值,称为码点。例如,65是字母A的码位,66 ->B (来源:Get Programming with Go)