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

时间:2015-03-04 06:47:41

标签: string go type-conversion slice

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

对于[]byte,我们可以执行string(byteslice),但对于[]int8,它会出错:

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

我从[{3}}的ba方法获得SliceScan()生成[]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)

4 个答案:

答案 0 :(得分:12)

事先注意:提问者首先声明输入切片为[]int8,这就是答案所针对的。后来他意识到输入是[]uint8,可以直接转换为string,因为byteuint8的别名([]byte => {{1 language spec)支持转换。


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

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

string是一个unicode代码点。如果我们尝试以一对一的方式将rune转换为int8,如果输入包含编码为多个字节的字符,则会失败(意味着输出错误)(使用UTF -8)因为在这种情况下,多个rune值应该以{{1​​}}结尾。

让我们从字符串int8开始,其字节为:

rune

它的符文:

"世界"

它只有2个符文和6个字节。因此,显然1对1 fmt.Println([]byte("世界")) // Output: [228 184 150 231 149 140] - &gt; fmt.Println([]rune("世界")) // [19990 30028] 映射不起作用,我们必须使用1-1 int8 - &gt; rune映射。< / p>

int8是范围为byte的{​​{1}}的别名,要将其转换为byte(范围为uint8)我们必须使用{ {1}}如果字节值为&gt; 127所以0..255中的[]int8 -128..127如下所示:

-256+bytevalue

向后转换我们想要的是:"世界"如果string为负数,但我们不能将此作为[]int8(范围-128..127)和既不是[-28 -72 -106 -25 -107 -116] (范围0..255),所以我们还必须先将其转换为bytevalue = 256 + int8value(最后再转换为int8)。这看起来像这样:

int8

但实际上由于有符号整数使用2's complement表示,如果我们只使用byte转换,我们会得到相同的结果(如果是负数,则相当于{{1} }})。

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

所以这是最后的转换:

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

Go Playground上尝试。

答案 1 :(得分:2)

不完全确定它是最快的,但我还没有找到更好的东西。 更改ba := []byte{}的{​​{1}},以便最后:

ba := make([]byte,0, len(bs)

这样,append函数永远不会尝试插入更多可以放在切片底层数组中的数据,并且可以避免不必要的复制到更大的数组。

答案 2 :(得分:1)

Convert between slices of different types”的确定是您必须从原始int8[]构建正确的切片。

我最终使用runeint32别名)(playground),假设uint8都是简单的ascii字符。这显然是一种过度简化,icza answer SliceScan()对此有更多的了解 另外,{{3}}方法最终还是返回uint8[]

package main

import (
    "fmt"
)

func main() {
    s := []int8{'a', 'b', 'c'}
    b := make([]rune, len(s))
    for i, v := range s {
        b[i] = rune(v)
    }
    fmt.Println(string(b))
}

但我没有使用[]byte对其进行基准测试。

答案 3 :(得分:0)

使用不安全的包裹。

func B2S(bs []int8) string {
  return strings.TrimRight(string(*(*[]byte)unsafe.Pointer(&bs)), "\x00")
}

再次发送^^