为了账号安全,请及时绑定邮箱和手机立即绑定

初始化周期错误

初始化周期错误

Go
慕婉清6462132 2022-03-03 19:52:24
我有自动生成的代码。简化版:package main// begin of Afunc main(){    ParseReader("x")}func parseInclude(fileName string) (interface{}, error) {    got, _ := ParseReader(fileName)    return got, nil}// end of Atype 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 }// Bfunc (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 中的代码。我怎样才能打破初始化周期?
查看完整描述

1 回答

?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

这是包初始化的结果,其中:


依赖分析不依赖于变量的实际值,只依赖于源中对它们的词汇引用,并进行传递分析。


例如,如果一个变量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 g

Go 中有一些用于松散耦合的技术,例如接口。


作为一个例子(不是最优的,但至少打破了初始化周期),你可以//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 grammar


func 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)

}


查看完整回答
反对 回复 2022-03-03
  • 1 回答
  • 0 关注
  • 130 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信