猿问

有没有办法用编码/gob 序列化循环数据结构?

我正在将神经网络库移植到 Go。我希望能够保存和恢复经过训练的网络,因此我尝试直接对其进行序列化。问题是,网络结构在其字段中包含循环(神经元 A 与神经元 B 有连接,而神经元 B 与神经元 A 有连接)。每当我尝试使用编码/gob 序列化整个网络时,它都会因堆栈溢出而失败。


这是一个以相同方式中断的非常简单的代码示例:


package main


import (

    "bytes"

    "encoding/gob"

    "fmt"

    "log"

)


type P struct {

    Name    string

    Q *Q

}


type Q struct {

    Name string

    P *P

}


func main() {

    var network bytes.Buffer        // Stand-in for a network connection

    enc := gob.NewEncoder(&network) // Will write to network.

    dec := gob.NewDecoder(&network) // Will read from network.


    p := &P{ "P", nil }

    q := &Q{ "Q", p }

    p.Q = q


    err := enc.Encode(p)

    if err != nil {

        log.Fatal("encode error:", err)

    }

    // Decode (receive) the value.

    var p2 *P

    err = dec.Decode(&p2)

    if err != nil {

        log.Fatal("decode error:", err)

    }

    fmt.Printf("%#v", p2)

}

http://play.golang.org/p/LrO0VlLnX4


除非重写库的整个结构以避免循环,否则有没有直接的方法来解决这个问题?


喵喔喔
浏览 224回答 1
1回答

慕田峪4524236

你不能直接使用gob,但不要害怕勇敢的世界公民!您可以在您的类型上实现BinaryMarshaler/BinaryUnmarshaler接口作为解决方法,gob 在编码/解码您的类型时会很乐意使用它们。func (p *P) MarshalBinary() (_ []byte, err error) {    var buf bytes.Buffer    enc := gob.NewEncoder(&buf)    enc.Encode(p.Name)    if p.Q == nil {        return buf.Bytes(), nil    }    isCyclic := p.Q != nil && p.Q.P == p    enc.Encode(isCyclic)    if isCyclic {        p.Q.P = nil        err = enc.Encode(p.Q)        p.Q.P = p    } else {        err = enc.Encode(p.Q)    }    //buf.Encode    return buf.Bytes(), err}func (p *P) UnmarshalBinary(data []byte) (err error) {    dec := gob.NewDecoder(bytes.NewReader(data))    if err = dec.Decode(&p.Name); err != nil {        return    }    var isCyclic bool    if err = dec.Decode(&isCyclic); err != nil {        return    }    err = dec.Decode(&p.Q)    if isCyclic {        p.Q.P = p    }    return}playground警告每次创建新的解码器/编码器效率极低,您可能需要考虑使用binary.*.
随时随地看视频慕课网APP

相关分类

Go
我要回答