为什么不能在 Go 中将 [Size]byte 转换为字符串?

Why can not convert [Size]byte to string in Go?

我有一个大小的字节数组,是我在 md5.Sum().

之后得到的
data := []byte("testing")
var pass string 
var b [16]byte
b = md5.Sum(data)
pass = string(b)

错误:

cannot convert b (type [16]byte) to type string

我在这里找到了解决方案 problem

更改为:

pass = string(b[:])

但是为什么不能这样用呢?

pass = string(b)

简短的回答是因为 Go 语言规范不允许。

引自Go Language Specification: Conversions

A non-constant value x can be converted to type T in any of these cases:

  • x is assignable to T.
  • x's type and T have identical underlying types.
  • x's type and T are unnamed pointer types and their pointer base types have identical underlying types.
  • x's type and T are both integer or floating point types.
  • x's type and T are both complex types.
  • x is an integer or a slice of bytes or runes and T is a string type.
  • x is a string and T is a slice of bytes or runes.

规范只允许将一段字节或符文转换为 string,而不是字节数组。

长答案

在 Go 中,数组和切片是不同的类型。数组的大小是类型的一部分。

切片比数组更通用,将数组转换为表示相同系列值的切片非常容易:arr[:](而且也很便宜,结果切片将共享数组作为它的后备数组,不会进行重新分配或复制。

因此,所有函数和支持都是为切片而不是数组提供的。

只是想创建一个简单的函数,它接受 int 个数字的切片(任意长度)和 returns 个数字的总和。像这样:

func sum(s []int) (sum int) {
    for _, v := range s {
        sum += v
    }
    return
}

如果您决定使用数组作为输入,由于长度是类型的一部分,您将限制函数的可用性,它只能采用相同长度的数组:

func sum2(s [2]int) (sum int) {
    for _, v := range s {
        sum += v
    }
    return
}

您只能使用 [2]int 类型的值调用 sum2(),但如果您有 [3]int 类型的数组,则 不能 因为这两种类型是不同的!如果你只有 int 的一片,你也不能调用 sum2()(你不能访问一个片的后备数组)。同时,您可以使用所有 []int 切片调用 sum() 函数,如果您有一个数组,您仍然可以通过将 arr[:] 传递给 sum() 函数来使用它。

注:

另请注意,将 "random" 字节片转换为 string 很可能不是您想要的,因为 "random" 字节片可能不是有效的 UTF-8字节序列。

而是使用 encoding/hex 包将结果转换为十六进制字符串,如下所示:

fmt.Println(hex.EncodeToString(b[:]))