Golang将[] int8转换为字符串 [英] Golang convert []int8 to string

查看:426
本文介绍了Golang将[] int8转换为字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[] 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆