在 golang 中持久化嵌套结构

我想添加持久性并从 json 初始化。我正在尝试保存/加载嵌套结构并收到“致命错误:堆栈溢出”。


据我了解,原因是父结构和子结构都有指向彼此的指针,并且 json 库正在进入循环。我需要指向 Parent 的指针,因为需要从孩子那里访问它。


我知道这是一个常见问题,解决它的最佳方法是什么?


type Mcloud struct {

    Projects map[string]*Project `json:"Projects"`

    Workdir  string

}


type Project struct {

    Name     string

    Networks map[string]Network

    Parent   *Mcloud

    TFC      TFConf

}


func newMcloud() *Mcloud {

    mc := &Mcloud{

        Projects: make(map[string]*Project),

        Workdir:  defaultWorkDir,

    }

    mc.load(statefile)


    return mc

}



func (mc *Mcloud) addProject(n string) {

    mc.Projects[n] = &Project{

        Name:     n,

        Networks: make(map[string]Network),

        Parent:   mc,

    }

    mc.Projects[n].addTFConf()

}


//save saves state to statefile

func (mc *Mcloud) save(f string) (err error) {

    if jsonState, err := json.Marshal(mc); err != nil {

        fmt.Println("Was not able to marshal")

        log.Fatal(err)

    } else {

        if err := ioutil.WriteFile(f, jsonState, 0666); err != nil {

            fmt.Println("Was not able to write state to", f, "!")

            log.Fatal(err)

        }

        fmt.Println("Save function saves: \n", mc, "to file ", f)

    }


    return err

}


func (mc *Mcloud) load(f string) (err error) {

    var bytestate []byte


    if bytestate, err = ioutil.ReadFile(f); err == nil {

        err = json.Unmarshal(bytestate, &mc)

    }


    return err

}

获得

运行时:goroutine 堆栈超过 1000000000 字节限制致命错误:堆栈溢出


运行时堆栈:runtime.throw(0x149cdfe, 0xe) /usr/local/Cellar/go/1.11.1/libexec/src/runtime/panic.go:608 +0x72 runtime.newstack() /usr/local/Cellar/go /1.11.1/libexec/src/runtime/stack.go:1008 +0x729 runtime.morestack() /usr/local/Cellar/go/1.11.1/libexec/src/runtime/asm_amd64.s:429 +0x8f



至尊宝的传说
浏览 88回答 1
1回答

炎炎设计

首先你需要告诉encoding/json跳过父字段,你可以用json:"-"标签来做到这一点。然后在解组过程中,在加载父项的所有子项后,循环遍历子项并设置它们的父项,您可以通过实现接口将此作为解组过程的一部分json.Unmarshaler。type Mcloud struct {    Projects map[string]*Project `json:"Projects"`    Workdir  string}type Project struct {    Name     string    Networks map[string]Network    Parent   *Mcloud `json:"-"` // ignore on un/marshal    TFC      TFConf}func (m *Mcloud) UnmarshalJSON(data []byte) error {    type tmp Mcloud    if err := json.Unmarshal(data, (*tmp)(m)); err != nil {        return err    }    // set Parent of all projects    for _, p := range m.Projects {        p.Parent = m    }    return nil}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go