自学Go我正在构建一个简单的服务器,它接受一些输入,进行一些处理,并将输出发送回客户端(包括原始输入)。
输入的长度可以从大约5到13个字符+终止线以及客户端发送的任何其他guff。
将输入读入字节数组,然后转换为字符串以进行某些处理。另一个字符串被附加到此字符串,整个事物被转换回字节数组以发送回客户端。
问题是输入是用一堆NUL字符填充的,我不知道如何摆脱它们。
所以我可以循环遍历数组,当我找到一个空字符时,记下长度(n),创建一个新长度的字节数组,并将前n个字符复制到新的字节数组并使用它。这是最好的方式,还是有什么东西让我更容易?
一些精简代码:
data := make([]byte, 16)
c.Read(data)
s := strings.Replace(string(data[:]), "an", "", -1)
s = strings.Replace(s, "\r", "", -1)
s += "some other string"
response := []byte(s)
c.Write(response)
c.close()
此外,如果我在这里做任何其他明显愚蠢的事情,那将很高兴知道。
答案 0 :(得分:40)
在“字节”包中,func Trim(s []byte, cutset string) []byte
是你的朋友:
Trim通过切掉cutset中包含的所有前导和尾随UTF-8编码的Unicode代码点来返回s的子切片。
// Remove any NULL characters from 'b'
b = bytes.Trim(b, "\x00")
答案 1 :(得分:1)
你的方法听起来基本正确。一些评论:
当您在data
中找到第一个空字节的索引时,您不需要复制,只需截断切片:data[:idx]
。
bytes.Index应该能够为您找到该索引。
还有bytes.Replace
,因此您无需转换为字符串。
答案 2 :(得分:0)
您可以利用 Read
的返回值:
package main
import "strings"
func main() {
r, b := strings.NewReader("north east south west"), make([]byte, 16)
n, e := r.Read(b)
if e != nil {
panic(e)
}
b = b[:n]
println(string(b) == "north east south")
}
答案 3 :(得分:0)
io.Reader 文档说:
<块引用>Read 将最多 len(p) 个字节读入 p。它返回读取的字节数 (0 <= n <= len(p)) 和遇到的任何错误。
如果应用程序中对 Read 的调用未读取 16 个字节,则 data
将具有尾随零字节。使用读取的字节数从缓冲区中修剪零字节。
data := make([]byte, 16)
n, err := c.Read(data)
if err != nil {
// handle error
}
data = data[:n]
还有一个问题。无法保证 Read 会吸收对等方发送的所有“消息”。应用程序可能需要多次调用 Read 来获取完整的消息。
您在问题中提到了结尾。如果来自客户端的消息终止但换行,则使用 bufio.Scanner 从连接中读取行:
s := bufio.NewScanner(c)
if s.Scan() {
data = s.Bytes() // data is next line, not including end lines, etc.
}
if s.Err() != nil {
// handle error
}