Golang将[] int8转换为字符串 [英] Golang convert []int8 to string
问题描述
将 [] int8
转换为字符串的最佳方法(最快性能)是什么?
code> [] byte 我们可以做 string(byteslice)
,但是对于 [] int8
它给出一个错误:
不能将ba(type [] int8)转换为字符串
我从 SliceScan获得了
方法 ba
) * sqlx.Rows
生成 [] int8
而不是 string
func B2S(bs [] int8)string {
ba:= [] byte {}
for _,b:=范围bs {
ba = append(ba,byte(b))
}
返回字符串(ba)
}
编辑我的不好,它是 uint8
而不是 int8
..所以我可以直接执行 string(ba)
p>
[] int8
,这就是答案的意思。后来他意识到输入是 [] uint8
,它可以直接转换为 string
,因为字节
是 uint8
的别名。 您不能转换不同类型的切片,您必须手动完成。
问题是我们应该转换为哪种类型的切片?我们有两个候选人: [] byte
和 [] rune
。字符串在内部存储为UTF-8编码的字节序列( [] byte
),还可以转换字符串
到一小块符文。该语言支持将这两种类型( [] byte
和 [] rune
)转换为字符串
。
符文
是一个unicode代码点。如果我们尝试以一对一的方式将 int8
转换为符文
,它将失败(意味着错误的输出),如果输入包含被编码为多个字节的字符(使用UTF-8),因为在这种情况下,多个 int8
值应该以一个<$ c $结尾c> rune 。 我们从字符串世界
:
fmt.Println([] byte(世界))
//输出:[228 184 150 231 149 140]
其符号:
fmt.Println([] rune(世界))
// [19990 30028]
只有2个符文和6个字节。所以很明显,1对1 int8
- > rune
映射将不起作用,我们必须使用1- 1 int8
- > byte
mapping。
byte
是 uint8
的别名,其范围 0..255
,将它转换为 [] int8
(有范围 -128..127
),我们必须使用 -256 + bytevalue
如果字节值> 127,所以世界
string
in [] int8
看起来像这样:
[ - 28 -72 -106 -25 -107 -116]
向后转换我们想要的是: bytevalue = 256 + int8value
如果 int8
是负数,但我们不能这样做作为 int8
(范围-128..127),既不是字节
(范围0..255),所以我们也必须先将它转换为 int
(并在最后回到 byte
)。这可能看起来像这样:
if v< 0 {
b [i] = byte(256 + int(v))
} else {
b [i] = byte(v)
}
但实际上由于有符号整数是用 2的补码,如果我们简单地使用字节(v)
转换(在的负数,这相当于 256 + v
)。
注意:由于我们知道切片的长度,分配具有此长度的切片的速度要快得多,并且只需使用索引 []
设置其元素,而不是调用构建的-in append
函数。
所以这里是最终转换:
func B2S(bs [] int8)字符串{
b:= make([] byte,len(bs))
for i,v: =范围bs {
b [i] =字节(v)
}
返回字符串(b)
}
在<上尝试它a href =https://play.golang.org/p/pCymfKl_Hp =nofollow noreferrer> Go Playground 。
What's the best way (fastest performance) to convert from []int8
to string?
For []byte
we could do string(byteslice)
, but for []int8
it gives an error:
cannot convert ba (type []int8) to type string
I got the ba
from SliceScan()
method of *sqlx.Rows
that produces []int8
instead of string
Is this solution the fastest?
func B2S(bs []int8) string {
ba := []byte{}
for _, b := range bs {
ba = append(ba, byte(b))
}
return string(ba)
}
EDIT my bad, it's uint8
instead of int8
.. so I can do string(ba)
directly.
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
.
You can't convert slices of different types, you have to do it manually.
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
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]
And its runes:
fmt.Println([]rune("世界"))
// [19990 30028]
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
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]
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)
}
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
).
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.
So here is the final conversion:
func B2S(bs []int8) string {
b := make([]byte, len(bs))
for i, v := range bs {
b[i] = byte(v)
}
return string(b)
}
Try it on the Go Playground.
这篇关于Golang将[] int8转换为字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!