什么是符文?

时间:2013-10-11 05:14:58

标签: go rune

Go中的rune是什么?

我一直在谷歌搜索,但Golang只用一行说: runeint32 的别名。

但是如何使用整数来交换整数?

以下是函数交换大小写。 什么是<=-

为什么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在这里是如何运作的。

8 个答案:

答案 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中,stringbytes的序列。但是,由于多个字节可以表示符文代码点,因此字符串值也可以包含符文。因此,它可以转换为[]rune,反之亦然。

unicode包http://golang.org/pkg/unicode/可以体验挑战的丰富性。

答案 2 :(得分:22)

我没有足够的声誉向fabrizioM answer发表评论,所以我必须在此发布。

法布里奇奥的答案基本上是正确的,他当然抓住了问题的实质 - 尽管必须有所区别。

字符串 NOT 必然是一系列符文。它是一个字节片段的包装器, slice 是Go数组的包装器。这有什么不同?

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

但是,字符串文字必须写入以UTF-8编码的源中。

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

答案 3 :(得分:17)

我试图保持我的语言简单,以便外行人理解rune

符文是一个角色。就是这样。

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

要获取字符串,我们使用

double-quotes ""

OR

back-ticks ``

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

single-quotes ''

现在符文也是int32的别名...呃什么?

符文是int32的别名的原因是因为我们看到了编码方案,如下所示 enter image description here

每个字符映射到某个数字,因此它是我们存储的数字。例如, 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 个字节
  • 对于stringlen()和索引都是基于字节的。
  • 对于[]runelen()和索引都是基于符文(或int32)的。

关系-string[]rune

  • 当您从string转换为[]rune时,该字符串中的每个utf-8字符都将变成rune
  • 类似地,在反向转换中,当从[]rune转换为string时,每个runestring中成为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的别名类型,在行中)。 / li>
  • string转换为[]rune时,它发现了7个utf8字符,因此有7个符文。

    • 由于len()上的[]rune基于符文,因此最后一行打印了len: 7
    • 如果您通过索引操作[]rune,它将基于符文访问。
      由于每个符文都来自原始字符串中的utf8字符,因此您也可以说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 位以内表示,这是符文。

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