【问题标题】:How to detect when bytes can't be converted to string in Go?如何检测何时无法在 Go 中将字节转换为字符串?
【发布时间】:2016-04-24 00:32:31
【问题描述】:

invalid byte sequences 无法转换为 Unicode 字符串。在 Go 中将 []byte 转换为 string 时如何检测到这一点?

【问题讨论】:

  • 如果您的编码是 UTF-8:unicode/utf8.Valid
  • 阅读blog.golang.org/strings -- string 转换只是一个字节对字节的复制,当你range 在代码点上时你会遇到无效的 UTF-8 (或转换为 []rune) 并获得 0xFFFD,即 Unicode 替换字符(规范为 here)。这些都不会崩溃,因此您只需要检查有效性是否对您的应用程序独立重要(或者如果您计划做其他事情在错误的 utf8 上崩溃)。
  • 这是一个无效 UTF-8 的示例:play.golang.org/p/6yHonH0Mae

标签: string unicode encoding go utf-8


【解决方案1】:

正如 Tim Cooper 所说,您可以使用 utf8.Valid 测试 UTF-8 的有效性。

但是!您可能认为将非 UTF-8 字节转换为 Go string 是不可能的。其实"In Go, a string is in effect a read-only slice of bytes";它可以包含无效的 UTF-8 字节,您可以打印、通过索引访问、传递给 WriteString 方法,甚至往返返回到 []byte(比如,到 Write)。

Go 语言中有两个地方会为您对strings 进行 UTF-8 解码。

  • 当您执行for i, r := range s 时,r 是一个Unicode 代码点,作为rune 类型的值
  • 当您进行[]rune(s) 的转换时,Go 会将整个字符串解码为符文。

(注意runeint32 的别名,不是完全不同的类型。)

在这两种情况下,无效的 UTF-8 被替换为 U+FFFDreplacement character 保留用于此类用途。更多内容在 for statementsconversions between strings and other types 的规范部分中。 这些转换永远不会崩溃,因此您只需要主动检查与您的应用程序相关的 UTF-8 有效性,例如如果您不能接受 U+FFFD 替换并且需要在错误编码的输入上抛出错误.

由于该行为已融入语言,您也可以从库中获得它。 U+FFFDutf8.RuneError 并由 utf8 中的函数返回。

这是一个示例程序,展示了 Go 如何处理带有无效 UTF-8 的 []byte

package main

import "fmt"

func main() {
    a := []byte{0xff}
    s := string(a)
    fmt.Println(s)
    for _, r := range s {
        fmt.Println(r)
    }
    rs := []rune(s)
    fmt.Println(rs)
}

输出在不同环境中看起来会有所不同,但在 Playground 中看起来像

�
65533
[65533]

【讨论】:

    猜你喜欢
    • 2017-02-14
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-07
    • 1970-01-01
    • 1970-01-01
    • 2023-02-26
    相关资源
    最近更新 更多