276

runeGo中的 a 是什么?

我一直在谷歌搜索,但 Golang 只在一行中说:runeint32.

但是整数怎么会像交换案例一样到处使用呢?

下面是一个函数swapcase。什么是<=-

为什么没有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

4

9 回答 9

205

符文文字只是 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',反之亦然。

于 2013-10-11T05:58:28.720 回答
77

来自 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 中, astringbytes. 但是,由于多个字节可以表示一个符文代码点,因此字符串值也可以包含符文。因此,它可以转换为 a []rune,反之亦然。

unicode 包http://golang.org/pkg/unicode/可以让您领略挑战的丰富性。

于 2013-10-11T19:28:46.677 回答
47

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

符文是一个字符。而已。

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

要获取我们使用的字符串

double-quotes ""

或者

back-ticks ``

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

single-quotes ''

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

rune 是别名的原因int32是因为我们看到使用如下编码方案 在此处输入图像描述

每个字符都映射到某个数字,因此它就是我们要存储的数字。例如,a映射到97,当我们存储该数字时,它只是数字,因此 rune 是 int32 的别名。但不仅仅是任何数字。它是一个包含 32 个“零和一”或“4”字节的数字。(注:UTF-8 是一种 4 字节的编码方案)

符文与弦有什么关系?

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

    package main

    import (
        "fmt"
    )

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

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

[72 101 108 108 111]

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

于 2017-09-16T12:04:38.220 回答
39

我没有足够的声誉来对 fabrizioM 的回答发表评论,所以我将不得不在此处发布。

Fabrizio 的回答在很大程度上是正确的,他当然抓住了问题的本质——尽管必须做出区分。

字符串不一定是符文序列。它是“字节切片”的包装器,切片是 Go 数组的包装器。这有什么区别?

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

但是,字符串文字需要写入以 UTF-8 编码的源代码中。

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

于 2015-07-08T17:31:04.760 回答
32

(感觉上面的答案仍然没有很清楚地说明和之间的差异和关系string[]rune所以我会尝试通过示例添加另一个答案。)

正如@Strangework's answer所说,string并且[]rune完全不同。

差异 - string& []rune:

  • string value是一个只读字节片。并且,字符串文字以 utf-8 编码。每个 char instring实际上占用1 ~ 3个字节,而每个rune占用4个字节
  • 对于string,len()和 index 都是基于字节的。
  • 对于[]rune,len()和 index 都基于 rune (或 int32)。

关系 - string& []rune:

  • 当您从 转换为string[]rune,该字符串中的每个 utf-8 字符都变为rune.
  • 同样,在反向转换中,当从[]runeto转换时string,每个runestring.

提示:

  • 您可以在 和 之间进行转换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
    • 由于字符串上的索引也是基于字节的,因此以下 2 行打印类型的值uint8(因为在 gobyte中是 , 的别名类型uint8)。
  • 将 转换为string[]rune,它找到了 7 个 utf8 字符,即 7 个​​符文。

    • 由于len()on[]rune是基于 rune 的,因此最后一行打印len: 7.
    • 如果您[]rune通过索引操作,它将根据符文访问。
      由于每个符文都来自原始字符串中的一个 utf8 字符,因此您也可以说两者len()和索引操作[]rune都是基于 utf8 字符。
于 2018-07-31T10:47:20.400 回答
9

符文相关的部分大家都讲过了,我就不多说了。

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

你可以在这里阅读更多。

于 2017-11-02T19:00:31.480 回答
2

程序

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

于 2021-05-05T07:24:01.590 回答
2

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

于 2018-09-02T18:00:34.190 回答
1

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

l = 108, o = 111

于 2021-08-26T18:25:01.910 回答