字符串中的符文

问题描述 投票:0回答:1

我正在学习 Go By Examples,字符串和符文部分非常混乱。

运行这个:

    sample := "\xbd\xb2\x3d\xbc\x20\xe2\x8c\x98"
    fmt.Println(sample)
    fmt.Printf("%%q: %q\n", sample)
    fmt.Printf("%%+q: %+q\n", sample)

产生这个:

��=� ⌘
%q: "\xbd\xb2=\xbc ⌘"
%+q: "\xbd\xb2=\xbc \u2318"

..这很好。第一个、第二个和第四个符文似乎是不可打印的,我猜这意味着

\xbd
\xb2
\xbc
根本不被 Unicode 或其他东西支持(如果我错了,请纠正我),所以它们显示高达 �
%q
%+q
也正确转义了这 3 个不可打印的符文。

但是现在当我像这样迭代字符串时:

    for _, runeValue := range sample {
        fmt.Printf("% x, %q, %+q\n", runeValue, runeValue, runeValue)
    }

突然,3个不可打印的符文没有被

%q
转义并保持为�,并且
%+q
试图揭示它们的底层代码点,这显然是不正确的:

 fffd, '�', '\ufffd'
 fffd, '�', '\ufffd'
 3d,   '=' ,  '='
 fffd, '�', '\ufffd'
 20,   ' ' ,  ' '
 2318, '⌘', '\u2318'

更奇怪的是,如果我将字符串作为字节切片进行迭代:

    for _, runeValue := range []byte(sample) {
        fmt.Printf("% x, %q, %+q\n", runeValue, runeValue, runeValue)
    }

突然之间,这些符文不再是不可打印的,并且它们的底层代码点是正确的:

 bd, '½', '\u00bd'
 b2, '²', '\u00b2'
 3d, '=', '='
 bc, '¼', '\u00bc'
 20, ' ', ' '
 e2, 'â', '\u00e2'
 8c, '\u008c', '\u008c'
 98, '\u0098', '\u0098'

有人可以解释一下这里发生了什么吗?

string go unicode utf-8 rune
1个回答
0
投票

fmt.Printf
将在幕后发挥很多作用,通过类型检查等方式呈现尽可能多的有用信息。如果您想验证字符串(或字节切片)是否有效
UTF-8
使用标准库包
encoding/utf8
.

例如:

import "unicode/utf8"

var sample = "\xbd\xb2\x3d\xbc\x20\xe2\x8c\x98"

fmt.Printf("%q valid? %v\n", sample, utf8.ValidString(sample)) // reports "false"

扫描字符串的各个符文,我们可以识别是什么使该字符串无效(从

UTF-8
编码的角度来看)。注意:十六进制值
0xfffd
表示遇到了错误的符文。该错误值被定义为包常量 utf8.RuneError:

for _, r := range sample {

    validRune := r != utf8.RuneError // is 0xfffd? i.e. bad rune?

    if validRune {
        fmt.Printf("'%c' validRune: true   hex: %4x\n", r, r)
    } else {
        fmt.Printf("'%c' validRune: false\n", r)
    }
}

https://go.dev/play/p/9NO9xMvcxCp

产生:

'�' validRune: false
'�' validRune: false
'=' validRune: true   hex:   3d
'�' validRune: false
' ' validRune: true   hex:   20
'⌘' validRune: true   hex: 2318
© www.soinside.com 2019 - 2024. All rights reserved.