通过TCP链接传输结构体的Golang实现方法
通过TCP链接传输结构体的Golang实现方法 你好! 我想了解,在实现效率和简洁性方面,传输特定类型的消息的最佳方式是什么?
我想解决的问题是,我希望每条消息都具有 {标题, 正文, 时间戳} 这样的形式,但到目前为止,我使用的是缓冲区,并且只发送字节消息。
在我的使用场景中,效率对我很重要。我听说过 protobuf。它对我来说是最佳解决方案吗?
关于这个主题的第二个问题是,如果我在 Windows 机器上进行开发,但使用 WSL 与 Ubuntu 终端交互,我应该安装 Windows 版本还是 Linux 版本的 protoc(protobuf 编译器)?
更多关于通过TCP链接传输结构体的Golang实现方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
对于通过TCP传输结构体,Go语言中有几种高效且简洁的实现方式。以下是针对你需求的具体实现:
1. 使用encoding/gob(Go原生方案)
这是Go语言内置的二进制序列化方案,特别适合Go-to-Go通信:
package main
import (
"encoding/gob"
"fmt"
"net"
"time"
)
// 定义消息结构体
type Message struct {
Title string
Body string
Timestamp time.Time
}
// 发送消息
func sendMessage(conn net.Conn, msg Message) error {
encoder := gob.NewEncoder(conn)
return encoder.Encode(msg)
}
// 接收消息
func receiveMessage(conn net.Conn) (Message, error) {
var msg Message
decoder := gob.NewDecoder(conn)
err := decoder.Decode(&msg)
return msg, err
}
// 服务器端示例
func server() {
ln, _ := net.Listen("tcp", ":8080")
conn, _ := ln.Accept()
msg := Message{
Title: "测试消息",
Body: "这是消息正文",
Timestamp: time.Now(),
}
sendMessage(conn, msg)
}
// 客户端示例
func client() {
conn, _ := net.Dial("tcp", "localhost:8080")
msg, _ := receiveMessage(conn)
fmt.Printf("收到消息: %+v\n", msg)
}
2. 使用Protocol Buffers(跨语言方案)
这是Google的高效二进制序列化格式,适合跨语言通信:
首先定义proto文件(message.proto):
syntax = "proto3";
package main;
option go_package = "./";
message Message {
string title = 1;
string body = 2;
int64 timestamp = 3;
}
生成Go代码:
# 在WSL中安装Linux版本的protoc
sudo apt-get install protobuf-compiler
protoc --go_out=. message.proto
Go实现代码:
package main
import (
"fmt"
"net"
"time"
)
// 发送protobuf消息
func sendProtobufMessage(conn net.Conn, msg *Message) error {
data, err := proto.Marshal(msg)
if err != nil {
return err
}
// 先发送消息长度
length := uint32(len(data))
err = binary.Write(conn, binary.BigEndian, length)
if err != nil {
return err
}
// 发送消息体
_, err = conn.Write(data)
return err
}
// 接收protobuf消息
func receiveProtobufMessage(conn net.Conn) (*Message, error) {
// 读取消息长度
var length uint32
err := binary.Read(conn, binary.BigEndian, &length)
if err != nil {
return nil, err
}
// 读取消息体
data := make([]byte, length)
_, err = io.ReadFull(conn, data)
if err != nil {
return nil, err
}
msg := &Message{}
err = proto.Unmarshal(data, msg)
return msg, err
}
// 使用示例
func example() {
msg := &Message{
Title: "Protobuf消息",
Body: "这是protobuf格式的消息",
Timestamp: time.Now().Unix(),
}
// 在TCP连接上发送
conn, _ := net.Dial("tcp", "localhost:8080")
sendProtobufMessage(conn, msg)
}
3. 使用JSON(可读性方案)
如果需要可读性或与其他系统集成,可以使用JSON:
package main
import (
"encoding/json"
"fmt"
"net"
"time"
)
// JSON消息传输
func sendJSONMessage(conn net.Conn, msg Message) error {
encoder := json.NewEncoder(conn)
return encoder.Encode(msg)
}
func receiveJSONMessage(conn net.Conn) (Message, error) {
var msg Message
decoder := json.NewDecoder(conn)
err := decoder.Decode(&msg)
return msg, err
}
性能对比
-
encoding/gob:
- 优点:Go原生支持,无需额外依赖,序列化/反序列化速度快
- 缺点:仅适用于Go语言间通信
-
Protocol Buffers:
- 优点:跨语言支持,二进制格式高效,向后兼容性好
- 缺点:需要.proto文件定义和protoc编译
-
JSON:
- 优点:可读性好,广泛支持
- 缺点:性能较低,数据体积较大
关于protoc安装
在WSL开发环境中,应该安装Linux版本的protoc,因为:
- WSL运行的是Linux二进制文件
- 你的Go代码将在Linux环境中编译和执行
- 保持开发环境的一致性
安装命令:
# 在WSL的Ubuntu中
sudo apt-get update
sudo apt-get install protobuf-compiler
protoc --version # 验证安装
对于你的使用场景,如果主要是Go语言间通信且追求最高效率,推荐使用encoding/gob。如果需要跨语言支持或与其他系统集成,Protocol Buffers是最佳选择。

