英文:
Reading and writing on net.Conn
问题
我正在尝试从net.Conn读取和写入数据,但由于我只有Read([]byte)和Write([]byte)函数,所以我发现很难找到辅助函数来完成这个任务。
我需要读取和写入以下类型的数据:
- uint64
- byte
- uint32
- UTF-8编码的字符串(首先是一个uint32长度,然后是字符串数据)
简而言之,Go语言的包中是否有类似Java的DataInputStream和DataOutputStream的功能?
谢谢和问候。
英文:
I am trying to read and write data from a net.Conn but since I have only Read([]byte) and Write([]byte) functions, I am finding quite hard to find helper functions to do this job.
I need to read and write the following types:
- uint64
- byte
- uint32
- UTF-8 encoded string ( first a uint32 length and the string data after)
In Short
Is there anything like Java's DataInputStream and DataOutputStream in Go's packages ?
Thanks and regards
答案1
得分: 4
你需要决定一个用于编组和解组的格式。你可以选择自己创建一个格式,或者使用已经存在的格式。我强烈推荐使用后者。
我之前在这里发布过关于go标准库支持的许多格式的帖子:https://stackoverflow.com/a/13575325/727643
如果你决定自己创建格式,那么可以使用encoding/binary
将无符号整数编码和解码为[]byte。它提供了小端和大端的选项。字符串可以直接转换为[]byte,使用[]byte(str)
。最后,字节可以直接作为字节发送。不需要任何魔法。
我要强调的是,自己创建格式通常是一个坏主意。我通常默认使用JSON,并且只在可以获得显著性能提升并且我认为值得花时间去做的情况下使用其他格式。
英文:
You need to decide on a format to marshal to and from. Your choices are to either roll your own format or to use one that was already made. I highly recommend the latter.
I have previously posted about many of the formats supported in the go standard library here: https://stackoverflow.com/a/13575325/727643
If you decide to roll your own, then uints can be encoded and decoded from []byte using encoding/binary
. It gives you the option of both little and big endian. Strings can be converted directly to []byte using []byte(str)
. Finally, bytes can just be sent as bytes. No magic needed.
I will stress that making up your own format is normally a bad idea. I tend to use JSON by default and use others only when I can get a significant performance increase and I believe it worth the time to do it.
答案2
得分: 1
二进制编码的一个小秘密是你可以编写和读取整个数据结构:
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, &MyMessage{
First: 100,
Second: 0,
Third: 100,
Message: MyString{0, [10]byte{'H', 'e', 'l', 'l', 'o', '\n'}},
})
if err != nil {
fmt.Printf("binary.Write failed:", err)
return
}
// <<--- CONN --->>
msg := new(MyMessage)
err2 := binary.Read(buf, binary.LittleEndian, msg)
if err2 != nil {
fmt.Printf("binary.Read failed:", err2)
return
}
注意你可以使用的类型的种类:
来自binary/encoding文档:
固定大小的值可以是固定大小的算术类型(int8、uint8、int16、float32、complex64,...)或仅包含固定大小值的数组或结构体。
请注意,你必须使用[10]byte
而不能使用[]byte
。
英文:
One little secret of binary encoding is that you can write and read entire data structures:
From the Playground
buf := new(bytes.Buffer)
err := binary.Write(buf, binary.LittleEndian, &MyMessage{
First: 100,
Second: 0,
Third: 100,
Message: MyString{0, [10]byte{'H', 'e', 'l', 'l', 'o', '\n'}},
})
if err != nil {
fmt.Printf("binary.Read failed:", err)
return
}
// <<--- CONN -->>
msg := new(MyMessage)
err2 := binary.Read(buf, binary.LittleEndian, msg)
if err2 != nil {
fmt.Printf("binary.Read failed:", err2)
return
}
Pay attention at the kind of types that you can use:
from binary/encoding docs:
> A fixed-size value is either a fixed-size arithmetic type (int8, uint8, int16, float32, complex64, ...) or an array or struct containing only fixed-size values.
notice then that you have to use [10] byte
and can't use []byte
答案3
得分: 0
Fabrizio的回答很好,我想补充一点,你应该使用bufio包中的缓冲读写器来包装你的socket:
英文:
Fabrizio's answer is good and I would like to add that you should probably wrap your socket with a buffered reader and buffered writer from the bufio package:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论