dozr13344 2014-10-20 20:57
浏览 7
已采纳

按类型的功能? 如何重构呢?

I'm reading json data from a file and sending it to a remote server using gob encoding, but I'm not happy with my code, I tried several ways to get a more generic function, but I'm failed, the only way that my code works is having identical functions for every type.

I tried using switch for types, but in the same way is needed repeat code in order to unmarshall and encode gob data

Please, could somebody help me to understand how improve that?

Two types:

type Data1 struct{
ID int
Message string
}

type Data2 struct{
 Serial int
 Height float64
 Loss   float64
 Temp   float64
 Oil    float64
}

Function for Data1 type

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()
    }
}

The same function but for Data2 type

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()
    }
  • 写回答

1条回答 默认 最新

  • douchilian1009 2014-10-20 21:10
    关注

    Add a parameter that allocates a new value of the type to receive and send:

    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()
        }
    }
    

    The code in this answer allocates a new value every time through the loop while the code in the question allocates the object once. Allocating each time through the loop prevents crosstalk between received JSON objects.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 delta降尺度方法,未来数据怎么降尺度
  • ¥15 c# 使用NPOI快速将datatable数据导入excel中指定sheet,要求快速高效
  • ¥15 再不同版本的系统上,TCP传输速度不一致
  • ¥15 高德地图点聚合中Marker的位置无法实时更新
  • ¥15 DIFY API Endpoint 问题。
  • ¥20 sub地址DHCP问题
  • ¥15 delta降尺度计算的一些细节,有偿
  • ¥15 Arduino红外遥控代码有问题
  • ¥15 数值计算离散正交多项式
  • ¥30 数值计算均差系数编程