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

19

我有一个经过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

我在这个问题上找到了解决方案。

pass = string(b[:])

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

pass = string(b)
1个回答

32
简短的回答是,因为Go语言规范不允许这样做。
引用自Go语言规范:类型转换
非常量值x可以在以下任何情况下转换为类型T: - x可分配给T。 - x的类型和T具有相同的基础类型。 - x的类型和T是未命名指针类型,并且它们的指针基类型具有相同的基础类型。 - x的类型和T都是整数或浮点类型。 - x的类型和T都是复合类型。 - x是整数或字节片或符文片,而T是字符串类型。 - x是一个字符串,T是一个字节片或符文片。
规范仅允许将字节片或符文片转换为字符串,但不允许将字节数组转换为字符串。

长答案

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

切片比数组更加通用,将一个数组转换为表示相同值序列的切片非常容易:arr[:](并且成本很低,结果切片将共享数组作为其后备数组,不会进行重新分配或复制)。

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

想象一下,您想创建一个简单的函数,该函数接受一个int数字的切片(具有任意长度),并返回数字的总和。像这样:

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()函数来使用它。

注意:

还要注意,将“随机”字节片转换为string很可能不是您想要的,因为“随机”字节片可能不是有效的UTF-8字节序列。

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接