从[]int8字符串转换为字符串的最佳方法(最快的性能)是什么?
[]int8
对于[]byte我们可以做string(byteslice),但[]int8它给出了一个错误:
[]byte
string(byteslice)
cannot convert ba (type []int8) to type string
我ba从那产生的from SliceScan()方法而不是*sqlx.Rows[]int8``string
ba
SliceScan()
*sqlx.Rows
[]int8``string
这个解决方案最快吗?
func B2S(bs []int8) string { ba := []byte{} for _, b := range bs { ba = append(ba, byte(b)) } return string(ba) }
编辑 我的坏东西,uint8而不是int8..,所以我可以string(ba)直接做。
uint8
int8
string(ba)
事先注意: 询问者首先指出输入分片就是[]int8答案。后来他意识到输入是[]uint8可以直接转换为的,string因为byte它是别名uint8(并且语言规范支持[]byte=> string转换)。
[]uint8
string
byte
您无法转换不同类型的切片,必须手动进行。
问题是我们应该转换为哪种类型的切片?我们有2个候选人:[]byte和[]rune。字符串在内部([]byte)作为UTF-8编码的字节序列存储,string也可以将a转换为一段符文。该语言支持将这两种类型([]byte和[]rune)都转换为string。
[]rune
A rune是一个Unicode代码点。如果我们尝试以一对一的方式将a 转换int8为a rune,那么如果输入包含编码为多个字节(使用UTF-8)的字符,则它将失败(表示错误的输出),因为在这种情况下,int8应使用多个值最终合而为一rune。
rune
让我们从"世界"字节为以下的字符串开始:
"世界"
fmt.Println([]byte("世界")) // Output: [228 184 150 231 149 140]
及其符文:
fmt.Println([]rune("世界")) // [19990 30028]
它只有2个符文和6个字节。因此,显然1对1- int8> rune映射将不起作用,我们必须使用1-1- int8> byte映射。
byte是uint8具有range的别名,如果字节值> 127 0..255,则必须将其转换为[]int8(具有range -128..127),-256+bytevalue因此"世界" stringin []int8如下所示:
0..255
-128..127
-256+bytevalue
[-28 -72 -106 -25 -107 -116]
向后转换我们想要的是:bytevalue = 256 + int8value如果a int8为负,但我们不能将其转换为int8(range -128..127),也不byte能将其转换为(range 0..255),因此我们还必须将其转换为intfirst(and back)到byte最后)。可能看起来像这样:
bytevalue = 256 + int8value
int
if v < 0 { b[i] = byte(256 + int(v)) } else { b[i] = byte(v) }
但是实际上,由于有符号整数是使用 2的补码表示的,因此,如果我们仅使用byte(v)转换(如果是负数,则等于256 + v),我们将得到相同的结果。
byte(v)
256 + v
注意: 由于我们知道切片的长度,因此分配具有该长度的切片并仅使用索引设置其元素[]而不调用内置append函数要快得多。
[]
append
所以这是最终的转换:
func B2S(bs []int8) string { b := make([]byte, len(bs)) for i, v := range bs { b[i] = byte(v) } return string(b) }
在Go Playground上尝试一下。