string(int)、string(int32) 和 string([]int32) 都有效,但 string([]int) 无效——这里的原理是什么?

string(int), string(int32) and string([]int32) are all valid but string([]int) is invalid - what's the rationale here?

(我使用的是 Go 1.14.6。)

以下语句都会输出字符 a

Println(string(int(97) ) )
Println(string(int32(97) ) )
Println(string([]int32{97} ) )

但是

Println(string([]int{97} ) )

会导致编译错误

cannot convert []int literal (type []int) to type string

这种行为让我感到困惑。如果它处理 string(int)string(int32) 相同,为什么它处理 string([]int) 不同于 string([]int32)

rune表示一个unicode代码点,是int32的别名。因此 string([]int32{})string([]rune{}) 相同,后者将一段符文(类似于 string 的字符)转换为 string。这很有用。

int 不是 int32 也不是 rune,所以把 []int 转换成 string 应该是不合逻辑的,它是模棱两可的,所以它不是语言规范允许。

将整数转换为 string 会生成具有单个 rune 的字符串值。 Spec: Conversions:

Conversions to and from a string type

  1. Converting a signed or unsigned integer value to a string type yields a string containing the UTF-8 representation of the integer. Values outside the range of valid Unicode code points are converted to "\uFFFD".

这让很多人感到困惑,因为许多人希望转换结果是字符串的(十进制)表示形式。 Go 的作者已经认识到这一点,并已采取措施在未来将其从语言中移除。在 Go 1.15 中,go vet 已经警告此类转换。 Go 1.15 release notes: Vet:

New warning for string(x)

The vet tool now warns about conversions of the form string(x) where x has an integer type other than rune or byte. Experience with Go has shown that many conversions of this form erroneously assume that string(x) evaluates to the string representation of the integer x. It actually evaluates to a string containing the UTF-8 encoding of the value of x. For example, string(9786) does not evaluate to the string "9786"; it evaluates to the string "\xe2\x98\xba", or "☺".

Code that is using string(x) correctly can be rewritten to string(rune(x)). Or, in some cases, calling utf8.EncodeRune(buf, x) with a suitable byte slice buf may be the right solution. Other code should most likely use strconv.Itoa or fmt.Sprint.

This new vet check is enabled by default when using go test.

We are considering prohibiting the conversion in a future release of Go. That is, the language would change to only permit string(x) for integer x when the type of x is rune or byte. Such a language change would not be backward compatible. We are using this vet check as a first trial step toward changing the language.