我正在从文件中读取json数据并使用gob编码将其发送到远程服务器, 但我对我的代码不满意,我尝试了几种方法来获得更通用的功能,但我失败了,我的代码工作的唯一方法就是为每种类型提供相同的功能。
我尝试使用switch作为类型,但是以同样的方式需要重复代码才能解组和编码gob数据
拜托,有人可以帮我理解如何改进吗?
两种类型:
type Data1 struct{
ID int
Message string
}
type Data2 struct{
Serial int
Height float64
Loss float64
Temp float64
Oil float64
}
Data1类型的函数
func SenderData1(address string, buff *filebuffer.Buffer) {
var conn net.Conn
var err error
var line string
var obj Data1
for {
line, err = buff.Pop()
if err != nil {
log.Critical("Error Poping:", err.Error())
continue
}
if len(line) == 0 {
time.Sleep(1 * time.Second)
continue
}
if err := json.Unmarshal([]byte(line), &obj); err != nil {
log.Critical("Error Unmarshaling:", err.Error())
continue
}
for {
log.Info("Trying to connect with Server...")
conn, err = net.Dial(PROTO, address)
// If err try to connect again
if err != nil {
log.Error("Error connecting:", err.Error())
time.Sleep(1 * time.Second)
continue
}
// If connected break the loop
break
}
log.Debug("Sending ", obj, " to:", address)
encoder := gob.NewEncoder(conn)
err := encoder.Encode(obj)
if err != nil {
log.Critical("Error Encoding Gob:", err.Error())
}
// Timer between every sending, ie. Reading from buffer
time.Sleep(300 * time.Millisecond)
conn.Close()
}
}
相同的功能,但对于Data2类型
func SenderData2(address string, buff *filebuffer.Buffer) {
var conn net.Conn
var err error
var line string
var obj Data2
for {
line, err = buff.Pop()
if err != nil {
log.Critical("Error Poping:", err.Error())
continue
}
if len(line) == 0 {
time.Sleep(1 * time.Second)
continue
}
if err := json.Unmarshal([]byte(line), &obj); err != nil {
log.Critical("Error Unmarshaling:", err.Error())
continue
}
for {
log.Info("Trying to connect with Server...")
conn, err = net.Dial(PROTO, address)
// If err try to connect again
if err != nil {
log.Error("Error connecting:", err.Error())
time.Sleep(1 * time.Second)
continue
}
// If connected break the loop
break
}
log.Debug("Sending ", obj, " to:", address)
encoder := gob.NewEncoder(conn)
err := encoder.Encode(obj)
if err != nil {
log.Critical("Error Encoding Gob:", err.Error())
}
// Timer between every sending, ie. Reading from buffer
time.Sleep(300 * time.Millisecond)
conn.Close()
}
答案 0 :(得分:2)
添加一个参数,该参数分配要接收和发送的类型的新值:
func SenderData1(address string, buff *filebuffer.Buffer) {
SenderData(address, buff, func() interface{} { return new(Data1) })
}
func SenderData2(address string, buff *filebuffer.Buffer) {
SenderData(address, buff, func() interface{} { return new(Data2) })
}
func SenderData(address string, buff *filebuffer.Buffer, newfn func() interface{}) {
var conn net.Conn
var err error
var line string
for {
line, err = buff.Pop()
if err != nil {
log.Critical("Error Poping:", err.Error())
continue
}
if len(line) == 0 {
time.Sleep(1 * time.Second)
continue
}
obj := newfn()
if err := json.Unmarshal([]byte(line), obj); err != nil {
log.Critical("Error Unmarshaling:", err.Error())
continue
}
for {
log.Info("Trying to connect with Server...")
conn, err = net.Dial(PROTO, address)
// If err try to connect again
if err != nil {
log.Error("Error connecting:", err.Error())
time.Sleep(1 * time.Second)
continue
}
// If connected break the loop
break
}
log.Debug("Sending ", obj, " to:", address)
encoder := gob.NewEncoder(conn)
err := encoder.Encode(obj)
if err != nil {
log.Critical("Error Encoding Gob:", err.Error())
}
// Timer between every sending, ie. Reading from buffer
time.Sleep(300 * time.Millisecond)
conn.Close()
}
}
此答案中的代码每次循环时都会分配一个新值,而问题中的代码会分配对象一次。每次通过循环分配可以防止收到的JSON对象之间的串扰。