一尘不染

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

go

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

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

cannot convert ba (type []int8) to type string

ba从那产生的from
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)直接做。


阅读 340

收藏
2020-07-02

共1个答案

一尘不染

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


您无法转换不同类型的切片,必须手动进行。

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

A rune是一个Unicode代码点。如果我们尝试以一对一的方式将a 转换int8为a
rune,那么如果输入包含编码为多个字节(使用UTF-8)的字符,则它将失败(表示错误的输出),因为在这种情况下,int8应使用多个值最终合而为一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映射。

byteuint8具有range的别名,如果字节值> 127 0..255,则必须将其转换为[]int8(具有range
-128..127),-256+bytevalue因此"世界" stringin []int8如下所示:

[-28 -72 -106 -25 -107 -116]

向后转换我们想要的是:bytevalue = 256 + int8value如果a int8为负,但我们不能将其转换为int8(range
-128..127),也不byte能将其转换为(range 0..255),因此我们还必须将其转换为intfirst(and
back)到byte最后)。可能看起来像这样:

if v < 0 {
    b[i] = byte(256 + int(v))
} else {
    b[i] = byte(v)
}

但是实际上,由于有符号整数是使用
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)
}

Go Playground上尝试一下。

2020-07-02