按类型划分的功能?怎么重构呢?

时间:2014-10-20 20:57:45

标签: go refactoring

我正在从文件中读取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()
    }

1 个答案:

答案 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对象之间的串扰。