首页 > 解决方案 > golang, £ char 导致奇怪的字符

问题描述

我有一个从一串有效字符生成随机字符串的函数。当它选择一个£时,我偶尔会得到奇怪的结果

我已将其复制到以下最小示例:

func foo() string {
    validChars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~@:!£$%^&*"
    var result strings.Builder

    for i := 0; i < len(validChars); i++ {

        currChar := validChars[i]
        result.WriteString(string(currChar))
    }
    return result.String()
}

我希望这会回来

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~@:!£$%^&*

但它没有,它产生

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~@:!£$%^&*
                                                                  ^
                                             where did you come from ?

如果我从原始的 validChars 字符串中取出 £ 符号,那个奇怪的 A 就会消失。

func foo() string {
    validChars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~@:!$%^&*"
    var result strings.Builder

    for i := 0; i < len(validChars); i++ {

        currChar := validChars[i]
        result.WriteString(string(currChar))
    }
    return result.String()
}

这产生 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~@:!$%^&*

标签: go

解决方案


Astring是 的类型别名[]byte。你对 a 的心智模型string可能是它由一片字符组成——或者,正如我们在 Go 中所说的那样:一片rune.

对于validChars字符串中的许多符文,这很好,因为它们是 ASCII 字符的一部分,因此可以在 UTF-8 中以单个字节表示。但是,£符文表示为 2 个字节。

现在,如果我们考虑一个字符串£,它由 1 个符文但 2 个字节组成。正如我所提到的,字符串实际上只是一个[]byte. 如果我们像您在示例中有效地做的那样抓取第一个元素,我们将只获得表示£. 当你将它转换回字符串时,它会给你一个意想不到的符文。


解决您的问题的方法是首先将字符串转换validChars[]rune. 然后,您可以按索引访问其各个符文(而不是字节),foo并将按预期工作。您可以在这个操场上看到它的实际效果。

另请注意,这len(validChars)将为您提供字符串中的字节数。要获得符文的数量,请utf8.RuneCountInString改用。

最后,是 Rob Pike 发表的一篇博文,您可能会觉得有趣。


推荐阅读