当init()函数之间存在依赖关系时,如何将包拆分为多个文件?

时间:2016-01-28 05:03:11

标签: go packages

我有一个go文件,这个包变得笨重,所以我想将它拆分成多个逻辑文件。

我目前正在分割(和删节)文件:

// node.go
package schema

import (
    "github.com/graphql-go/graphql"
    "github.com/graphql-go/relay"
)

var nodeDefinitions *relay.NodeDefinitions

func init() {
    nodeDefinitions = relay.NewNodeDefinitions(relay.NodeDefinitionsConfig{
        IDFetcher: func(id string, info graphql.ResolveInfo) interface{} {
            ...
        },
        TypeResolve: func(value interface{}, info graphql.ResolveInfo) *graphql.Object {
            // based on the type of the value, return GraphQLObjectType
            switch value.(type) {
            default:
                return testType //Depends on the test.go
            }
        },
    })
}


//root.go
package schema

import (
    "github.com/graphql-go/graphql"
)

var Schema graphql.Schema

func init() {
    queryType := graphql.NewObject(graphql.ObjectConfig{
        Name: "Query",
        Fields: graphql.Fields{
            "version": &graphql.Field{
                 Type: versionType, //Depends on testtype.go
                 ...
            },
            "node": nodeDefinitions.NodeField, //Depends on node.go
        },
    })

    Schema, _ = graphql.NewSchema(graphql.SchemaConfig{
        Query: queryType,
    })
}

//testtype.go
package schema

import (
    "github.com/graphql-go/graphql"
    "github.com/graphql-go/relay"
)

var testType *graphql.Object

func init() {
    testType = graphql.NewObject(graphql.ObjectConfig{
        ...
        Interfaces: []*graphql.Interface{
            nodeDefinitions.NodeInterface, //Depends on node.go
        },
    })
}

然后我在main.go中使用该包:

result := graphql.Do(graphql.Params{
        Schema:        schema.Schema,
        RequestString: r.URL.Query()["query"][0],
    })

虽然程序包正确构建,但在运行它时会出现错误:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x0 pc=0x48e4b6]

goroutine 1 [running]:
test/testproject/vendor/github.com/graphql-go/graphql.(*Object).Error(0x0, 0xc082003380, 0x3c)
        C:/go/src/test/testproject/vendor/github.com/graphql-go/graphql/definition.go:440 +0x26
test/testproject/vendor/github.com/graphql-go/graphql.defineFieldMap(0xda48b0, 0xc08206c780, 0xc0820550e0, 0xda
        C:/go/src/test/testproject/vendor/github.com/graphql-go/graphql/definition.go:498 +0x532
test/testproject/vendor/github.com/graphql-go/graphql.(*Object).Fields(0xc08206c780, 0xc08206c780)
        C:/go/src/test/testproject/vendor/github.com/graphql-go/graphql/definition.go:416 +0x106
test/testproject/vendor/github.com/graphql-go/graphql.typeMapReducer(0xc082055110, 0xda4560, 0xc08206c780, 0x0,
        C:/go/src/test/testproject/vendor/github.com/graphql-go/graphql/schema.go:208 +0x79a
test/testproject/vendor/github.com/graphql-go/graphql.NewSchema(0xc08206c780, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
        C:/go/src/test/testproject/vendor/github.com/graphql-go/graphql/schema.go:67 +0x809
test/testproject/schema.init.2()
        C:/go/src/test/testproject/schema/root.go:37 +0x244
test/testproject/schema.init()
        C:/go/src/test/testproject/schema/version.go:37 +0x5b
main.init()
        C:/go/src/test/testproject/main.go:37 +0x42

这是因为:

node.go depends on testtype.go
testtype.go depends on node.go
root.go depends on node.go and testtype.go

go build通过按字母顺序对文件名进行排序来构建页面中的文件:node.go然后root.go然后testtype.go

如果我将root.go重命名为z.go,则会构建并正确运行。除了将root.go重命名为z.go这不太理想之外,还有其他方法可以让我以可扩展的方式工作吗?

1 个答案:

答案 0 :(得分:2)

您只能使用一个init()函数并将所有内容都放在其中。

或者如果你想在多个init()文件中坚持使用多个.go函数,那么创建一个" master"将被称为init()的init函数,并重命名其他init函数,例如initA()initB(),并按正确顺序从主init调用这些:

func init() {
    initA()
    initB()
}

参见相关问题+回答:What does lexical file name order mean?