我正在编写一个带有TCP套接字的小通信协议。我能够读写基本数据类型,如整数,但我不知道如何从字节片读取UTF-8编码的字符串。
协议客户端是用Java编写的,服务器是Go。
据我所读: GO符文有32位长,UTF-8字符有1到4个字节长,这使得不可能简单地将一个字节切片转换成一个字符串。
我想知道我怎么读和写这条UTF-8流。
Note I有字节缓冲区长度,可以按时读取字符串。
发布于 2013-11-25 22:06:38
一些理论首先:
rune表示Unicode代码点--一个分配给Unicode中特定字符的数字。它是uint32的别名。如何映射Go数据类型:
[]byte和string都存储一系列字节( Go中的byte是uint8的别名)。
最主要的区别是字符串是不可变的,所以您可以
B := make([]字节,2) b=字节(‘a’) b1 =字节(‘z’)
你不能
变量的字符串s=字节(‘a’)
后一个事实甚至由于无法显式设置字符串长度(如假想的s := make(string, 10)中的字符串长度)而得到强调。- A type conversion between `string` and `[]rune` parses the string as a sequence of UTF-8-encoded code points and produces a slice of them. The reverse type conversion takes the Unicode code points from the slice of runes and produces an UTF-8-encoded string.
- A `range` loop over a string loops through Unicode code points comprising the string, _not_ just bytes.Go还提供了string和[]byte以及back之间的类型转换。现在回想一下,字符串是只读的,而字节片则不是.这意味着一个类似于
b := make([]byte, 1000)
io.ReadFull(r, b)
s := string(b)始终复制数据,无论您是将一个片段转换为字符串还是返回。这浪费了空间,但类型安全,并强制语义。
现在回到手头的任务。
如果您处理的字符串相当小,并且不受内存压力,只需将由io.Read()填充的字节片(或其他任何东西)转换为字符串即可。一定要重用用于读取数据的切片,以减轻垃圾收集器的压力--也就是说,不要为每次新读取的数据分配一个新的片段,因为您要将读取代码发送给它的数据复制到一个字符串中。
最后,如果您绝对不需要复制数据(比方说,您正在处理多兆字节的字符串,并且内存需求很紧),您可以尝试通过不安全地使用内存来玩肮脏的把戏-- 这里是将内存从字节片移植到字符串的一个例子。请注意,如果您恢复到这样的情况,您必须非常清楚,它可以自由地与Go的任何新版本断绝关系,而且它甚至不一定能够正常工作。
https://stackoverflow.com/questions/20195145
复制相似问题