英文:
Why can not convert [Size]byte to string in Go?
问题
我有一个经过md5.Sum()
处理后得到的大小为16字节的字节数组。
data := []byte("testing")
var pass string
var b [16]byte
b = md5.Sum(data)
pass = string(b)
错误信息为:
无法将b(类型为[16]byte)转换为string类型
我在这个问题上找到了解决方案。
将代码修改为:
pass = string(b[:])
但为什么不能像这样使用呢?
pass = string(b)
英文:
I have a sized byte array that I got after doing md5.Sum()
.
data := []byte("testing")
var pass string
var b [16]byte
b = md5.Sum(data)
pass = string(b)
The error:
cannot convert b (type [16]byte) to type string
I find the solution at this problem
Change to:
pass = string(b[:])
But why can not use it like this?
pass = string(b)
答案1
得分: 32
简短回答是因为Go语言规范不允许这样做。
引用自Go语言规范:类型转换:
- 在以下情况下,非常量值
x
可以转换为类型T
: x
可以赋值给T
。x
的类型和T
具有相同的基础类型。x
的类型和T
是未命名指针类型,并且它们的指针基础类型具有相同的基础类型。x
的类型和T
都是整数或浮点数类型。x
的类型和T
都是复数类型。x
是整数或字节切片或符文切片,而T
是字符串类型。x
是字符串,而T
是字节切片或符文切片。
规范只允许将字节切片或符文切片转换为string
,而不允许将字节数组转换为string
。
长答案
在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
的数组,你就不能调用sum2()
,因为这两种类型是不同的!如果你只有一个int
切片,你也不能调用sum2()
(你无法访问切片的后备数组)。与此同时,你可以使用arr[:]
将数组传递给sum()
函数。
注意:
还要注意,将“随机”的字节切片转换为string
可能不是你想要的,因为“随机”的字节切片可能不是有效的UTF-8字节序列。
相反,使用encoding/hex
包将结果转换为十六进制字符串,如下所示:
fmt.Println(hex.EncodeToString(b[:]))
英文:
Short answer is because the Go Language Specification does not permit it.
Quoting from the 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.
The specification only allows converting a slice of bytes or runes to string
, but not an array of bytes.
Long answer
In Go arrays and slices are distinct types. The size of an array is part of the type.
Slices are much more general than arrays, and converting an array to a slice which represents the same series of values is very easy: arr[:]
(and is also cheap, the result slice will share the array as its backing array, no reallocation or copying will be done).
Because of this, all functions and support are provided for slices and not for arrays.
Just image you want to create a simple function which takes a slice (with any length) of int
numbers and returns the sum of the numbers. Something like this:
func sum(s []int) (sum int) {
for _, v := range s {
sum += v
}
return
}
If you would decide to use an array as the input, since the length is part of the type, you would limit the usability of your function, it could only take arrays of the same length:
func sum2(s [2]int) (sum int) {
for _, v := range s {
sum += v
}
return
}
You can call sum2()
only with values of type [2]int
but if you have an array of type [3]int
, you can't because those 2 types are distinct! You also cannot call sum2()
if you only have a slice of int
's (you can't access the backing array of a slice). Meanwhile you can call your sum()
function with all []int
slices, and if you have an array, you can still use it by passing arr[:]
to your sum()
function.
Note:
Also note that converting a "random" slice of bytes to a string
is most likely not what you want because a "random" slice of bytes may not be a valid UTF-8 byte sequence.
Instead use the encoding/hex
package to convert the result to a hex string like this:
fmt.Println(hex.EncodeToString(b[:]))
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论