Golang中如何处理无效的字符:Ä

Golang中如何处理无效的字符:Ä 根据这个网站,我得到的瑞典字母“Ä”的符文值是无效的……

ASCII Code - The extended ASCII table

ASCII Code - The extended ASCII table

以下包含十六进制、八进制、HTML、二进制和十进制图表转换的ASCII表,既包含了ASCII控制字符、ASCII可打印字符,也包含了扩展的ASCII字符集Windows-1252。

……ASCII码应该是196,但上面的代码返回了195,也就是Ã?

https://play.golang.org/p/6qC7x7bI2pg

这是我第一次接触符文,所以我可能误解了一些基本的东西。为什么它不返回196?


更多关于Golang中如何处理无效的字符:Ä的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

petrus:

The Go Blog: Strings, bytes, runes and characters in Go

这个链接解释了我之前困惑的大部分内容,谢谢……

更多关于Golang中如何处理无效的字符:Ä的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


好的,如果像这样做,它就能工作:

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

看来我误解了一些基本的东西。

Hultan:

这是我第一次接触符文(rune),所以我可能在这里误解了一些基本概念。

是的,你似乎仍然遗漏了一些基本的东西。

Go 博客:Go 语言中的字符串、字节、符文和字符

关于 Unicode 标准

ASCII 只有 7 位。Windows-1252 不是 ASCII,它是众多 ASCII 兼容的 8 位字符编码之一。

然而,Go 使用完整的 Unicode 字符集,其中“带分音符的拉丁文大写字母 A”(Ä)的序号是 196(U+00C4)。

Go 运行时在内部将这些字符编码为 UTF-8。因此,这个字形实际上会占用 2 个字节(0xC3 0x84)。

还有其他方法可以构建通常表示为 Ä 的字符。你已经了解了 U+00C4,但它也可以由 A(U+0041)和 ◌̈(U+0308)组合而成。这在 UTF-8 编码中最终需要 3 个字节(A 占 1 个字节,◌̈ 占 2 个字节)。

另外请记住,Ä 不仅用于瑞典语字母表,也用于丹麦语和德语。

通常,小写变体在许多字母表中都有使用,因为字母上方的分音符(◌̈)通常表示某种元音停顿。但在德语中并非如此,因为变音符号是从连字(如 Æ)演变而来的,其发音与 A 后跟 E 的发音不同。

如果你想处理任何非 UTF-8 编码的输入(原始的 7 位 ASCII 是 UTF-8 的子集),你需要在编码之间进行转换。Unicode 序号通常被用作各种字符重新编码的通用中间映射。

func main() {
    fmt.Println("hello world")
}

在Go中处理字符“Ä”时,你遇到的问题是字符编码不一致导致的。ASCII表只包含128个字符(0-127),而“Ä”属于扩展字符集。Go使用UTF-8编码,其中“Ä”的Unicode码点是U+00C4,但在UTF-8编码中它由两个字节表示:0xC3 0x84

你的代码返回195是因为你错误地将UTF-8编码的字节序列当作单个字节处理。以下是正确的处理方式:

package main

import (
    "fmt"
)

func main() {
    // 正确获取Unicode码点
    r := 'Ä'
    fmt.Printf("Unicode码点: %U\n", r)  // 输出: U+00C4
    fmt.Printf("十进制值: %d\n", r)     // 输出: 196
    
    // 查看UTF-8编码
    s := "Ä"
    fmt.Printf("UTF-8字节: % x\n", s)  // 输出: c3 84
    fmt.Printf("字节长度: %d\n", len(s)) // 输出: 2
    
    // 遍历字符串中的符文
    for i, r := range s {
        fmt.Printf("位置 %d: %U (十进制: %d)\n", i, r, r)
    }
}

如果你需要将字符串转换为特定编码(如Windows-1252),可以使用golang.org/x/text/encoding/charmap包:

package main

import (
    "fmt"
    "golang.org/x/text/encoding/charmap"
)

func main() {
    // UTF-8转Windows-1252
    encoder := charmap.Windows1252.NewEncoder()
    encoded, _ := encoder.String("Ä")
    
    fmt.Printf("Windows-1252编码: % x\n", encoded)  // 输出: c4
    fmt.Printf("十进制值: %d\n", encoded[0])        // 输出: 196
}

运行前需要安装编码包:

go get golang.org/x/text/encoding/charmap

关键点:

  1. Go默认使用UTF-8编码,每个符文可能对应1-4个字节
  2. ASCII码196对应的是Windows-1252编码中的“Ä”
  3. 在UTF-8中,“Ä”的Unicode码点是U+00C4(十进制196),但编码为两个字节0xC3 0x84

你的代码返回195是因为你读取了UTF-8编码的第一个字节0xC3(十进制195),而不是完整的Unicode码点。

回到顶部