如何将[] int8转换为字符串
从[]int8
转换为字符串的最佳方法(最快的性能)是什么?
What's the best way (fastest performance) to convert from []int8
to string?
对于[]byte
,我们可以做string(byteslice)
,但是对于[]int8
,它会给出错误:
For []byte
we could do string(byteslice)
, but for []int8
it gives an error:
cannot convert ba (type []int8) to type string
我从 *sqlx.Rows
的SliceScan()
方法中获得了ba
,它生成了[]int8
而不是string
I got the ba
from SliceScan()
method of *sqlx.Rows
that produces []int8
instead of string
此解决方案最快吗?
func B2S(bs []int8) string {
ba := []byte{}
for _, b := range bs {
ba = append(ba, byte(b))
}
return string(ba)
}
编辑,我不好,它是uint8
而不是int8
..所以我可以直接执行string(ba)
.
EDIT my bad, it's uint8
instead of int8
.. so I can do string(ba)
directly.
事前注意:询问者首先指出输入分片为[]int8
,这就是答案.后来他意识到输入是[]uint8
,可以直接转换为string
,因为byte
是uint8
的别名(并且[]byte
=> string
转换受
Note beforehand: The asker first stated that input slice is []int8
so that is what the answer is for. Later he realized the input is []uint8
which can be directly converted to string
because byte
is an alias for uint8
(and []byte
=> string
conversion is supported by the language spec).
您无法转换不同类型的切片,必须手动进行.
You can't convert slices of different types, you have to do it manually.
问题是我们应该转换为哪种类型的切片?我们有2个候选:[]byte
和[]rune
.字符串在内部以UTF-8编码的字节序列([]byte
)的形式存储,并且string
也可以转换为一片符文.该语言支持将这两种类型([]byte
和[]rune
)都转换为string
.
Question is what type of slice should we convert to? We have 2 candidates: []byte
and []rune
. Strings are stored as UTF-8 encoded byte sequences internally ([]byte
), and a string
can also be converted to a slice of runes. The language supports converting both of these types ([]byte
and []rune
) to string
.
A rune
是Unicode代码点.而且,如果我们尝试以一对一的方式将int8
转换为rune
,如果输入包含编码为多个字节的字符(使用UTF-8),它将失败(表示错误的输出),因为在这种情况下,多个int8
值应以一个rune
结尾.
A rune
is a unicode codepoint. And if we try to convert an int8
to a rune
in a one-to-one fashion, it will fail (meaning wrong output) if the input contains characters which are encoded to multiple bytes (using UTF-8) because in this case multiple int8
values should end up in one rune
.
让我们从字符串"世界"
开始,其字节为:
Let's start from the string "世界"
whose bytes are:
fmt.Println([]byte("世界"))
// Output: [228 184 150 231 149 140]
及其符文:
fmt.Println([]rune("世界"))
// [19990 30028]
只有2个符文和6个字节.因此很明显,一对一int8
-> rune
映射将不起作用,我们必须使用1-1 int8
-> byte
映射.
It's only 2 runes and 6 bytes. So obviously 1-to-1 int8
->rune
mapping won't work, we have to go with 1-1 int8
->byte
mapping.
byte
是具有范围0..255
的uint8
的别名,要将其转换为[]int8
(具有范围-128..127
),如果字节值> 127,则必须使用-256+bytevalue
. []int8
中的"世界"
string
看起来像这样:
byte
is alias for uint8
having range 0..255
, to convert it to []int8
(having range -128..127
) we have to use -256+bytevalue
if the byte value is > 127 so the "世界"
string
in []int8
looks like this:
[-28 -72 -106 -25 -107 -116]
我们想要的向后转换是:bytevalue = 256 + int8value
如果int8
为负,但我们不能将其作为int8
(范围-128..127),也不能将其作为byte
(范围0..255),因此我们还必须先将其转换为int
(最后转换回byte
).可能看起来像这样:
The backward conversion what we want is: bytevalue = 256 + int8value
if the int8
is negative but we can't do this as int8
(range -128..127) and neither as byte
(range 0..255) so we also have to convert it to int
first (and back to byte
at the end). This could look something like this:
if v < 0 {
b[i] = byte(256 + int(v))
} else {
b[i] = byte(v)
}
但是实际上由于有符号整数是使用 2的补码表示的如果我们仅使用byte(v)
转换(在负数的情况下,它等效于256 + v
),则结果相同.
But actually since signed integers are represented using 2's complement, we get the same result if we simply use a byte(v)
conversion (which in case of negative numbers this is equivalent to 256 + v
).
注意:由于我们知道切片的长度,因此分配具有该长度的切片并仅使用索引[]
而不调用内置append
函数.
Note: Since we know the length of the slice, it is much faster to allocate a slice with this length and just set its elements using indexing []
and not calling the built-in append
function.
这是最终的转换:
func B2S(bs []int8) string {
b := make([]byte, len(bs))
for i, v := range bs {
b[i] = byte(v)
}
return string(b)
}
在去游乐场上尝试.