初始化周期错误

我有自动生成的代码。简化版:


package main


// begin of A

func main(){

    ParseReader("x")

}

func parseInclude(fileName string) (interface{}, error) {

    got, _ := ParseReader(fileName)

    return got, nil

}

// end of A

type grammar struct {

    pos   int

    run  func(*parser) (interface{}, error)

}

var g = &grammar{

    pos:  1,

    run: (*parser).callonIncludeOp1,

}


type parser struct {

    filename string

    cur      current

}

func (p *parser) callonIncludeOp1() (interface{}, error) {

    return p.cur.onIncludeOp1("x")

}

func (p *parser) parse(g *grammar) (val interface{}, err error) {

    return g.pos, nil

}


type current struct {

    pos  int 

}

// B

func (c *current) onIncludeOp1(qfilename interface{}) (interface{}, error) {

    got, _ := parseInclude("x")

    return got, nil

}


func ParseReader(filename string) (interface{}, error) {

    p := &parser{ filename: filename }

    return p.parse(g)

}

编译后出现错误


./prog.go:19: initialization loop:

    /home/gCDfp4/prog.go:19 g refers to

    /home/gCDfp4/prog.go:25 (*parser).callonIncludeOp1 refers to

    /home/gCDfp4/prog.go:36 (*current).onIncludeOp1 refers to

    /home/gCDfp4/prog.go:7 parseInclude refers to

    /home/gCDfp4/prog.go:41 ParseReader refers to

    /home/gCDfp4/prog.go:19 g

我需要在语法上进行递归调用,因为我有预处理器运算符“#include”来解析其他文件。


因为它是自动生成的代码,所以我只能修改块 A 或函数 B 中的代码。


我怎样才能打破初始化周期?


慕婉清6462132
浏览 157回答 1
1回答

一只斗牛犬

这是包初始化的结果,其中:依赖分析不依赖于变量的实际值,只依赖于源中对它们的词汇引用,并进行传递分析。例如,如果一个变量x的初始化表达式引用了一个函数,该函数的主体引用了变量,y那么x依赖于y.如:“对变量或函数的引用是表示该变量或函数的标识符。”您在操场上的示例返回更直接的内容:tmp/sandbox395359317/main.go:21: initialization loop:    prog.go:21 g refers to    prog.go:28 (*parser).callonIncludeOp1 refers to    prog.go:21 gGo 中有一些用于松散耦合的技术,例如接口。作为一个例子(不是最优的,但至少打破了初始化周期),你可以//A添加:type parseIncluder interface {    parseInclude(fileName string) (interface{}, error)}func (c *current) parseInclude(fileName string) (interface{}, error) {    return parseInclude(fileName)}在 中//B,调用parseInclude()变为:got, _ := c.cParseIncluder().parseInclude("x")请参阅Go plaground并单击Run:不再initialization loop。OP Red Skotina使用了一种不同的方法来封装init()函数:var gProxy grammarfunc init() { gProxy = g }func parseInclude(fileName string) (interface{}, error) {    got, _ := ParseReaderProxy(fileName)    return got, nil}func ParseReaderProxy(filename string) (interface{}, error) {    p := &parser{filename: filename}    return p.parse(gProxy)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go