如何将[] int8转换为字符串

Kok*_*zzu 5 string type-conversion go slice

转换[]int8为字符串的最佳方式(最快的性能)是什么?

对于[]byte我们可以做string(byteslice),但[]int8它给出了一个错误:

cannot convert ba (type []int8) to type string
Run Code Online (Sandbox Code Playgroud)

我得到了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)
}
Run Code Online (Sandbox Code Playgroud)

编辑我的坏,它uint8不是int8..所以我可以string(ba)直接做.

icz*_*cza 13

事先注意:提问者首先说输入切片是[]int8这样的答案.后来他意识到输入[]uint8可以直接转换为,string因为byte它是别名uint8(并且语言规范支持[]byte=> string转换).


您不能转换不同类型的切片,您必须手动完成.

问题是我们应该转换为什么类型的切片?我们有2名候选人:[]byte[]rune.字符串在内部([]byte)存储为UTF-8编码的字节序列,并且a string也可以转换为符文切片.该语言支持将这两种类型([]byte[]rune)转换为string.

A rune是unicode代码点.如果我们尝试以一对一的方式将a 转换int8为a rune,如果输入包含编码为多个字节的字符(使用UTF-8),它将失败(意味着输出错误),因为在这种情况下int8应该有多个值最终合而为一rune.

让我们从"??"字节为的字符串开始:

fmt.Println([]byte("??"))
// Output: [228 184 150 231 149 140]
Run Code Online (Sandbox Code Playgroud)

它的符文:

fmt.Println([]rune("??"))
// [19990 30028]
Run Code Online (Sandbox Code Playgroud)

它只有2个符文和6个字节.所以很明显1对1 int8- > rune映射不起作用,我们必须使用1-1 int8- > byte映射.

byte是否uint8具有范围的别名0..255,要将其转换为[]int8(具有范围-128..127),-256+bytevalue如果字节值> 127则必须使用,因此"??" stringin []int8看起来像这样:

[-28 -72 -106 -25 -107 -116]
Run Code Online (Sandbox Code Playgroud)

我们想要的向后转换是:bytevalue = 256 + int8value如果int8是负数,但我们不能这样做int8(范围-128..127),也不能作为byte(范围0..255),所以我们也必须将它转换为int第一个(并且返回到byte最后).这看起来像这样:

if v < 0 {
    b[i] = byte(256 + int(v))
} else {
    b[i] = byte(v)
}
Run Code Online (Sandbox Code Playgroud)

但实际上由于有符号整数用2的补码表示,如果我们只使用byte(v)转换(在负数的情况下,这相当于256 + v),我们得到相同的结果.

注意:由于我们知道切片的长度,因此分配具有此长度的切片并使用索引设置其元素[]而不调用内置append函数要快得多.

所以这是最后的转换:

func B2S(bs []int8) string {
    b := make([]byte, len(bs))
    for i, v := range bs {
        b[i] = byte(v)
    }
    return string(b)
}
Run Code Online (Sandbox Code Playgroud)

Go Playground尝试一下.