I have a go file for a package that is becoming unwieldy, so I want to split it into multiple logical files.
I have the files currently split (and abridged) like so:
// 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
},
})
}
I then use the package in main.go
:
result := graphql.Do(graphql.Params{
Schema: schema.Schema,
RequestString: r.URL.Query()["query"][0],
})
While the package builds correctly, it complains with an error when I run it:
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
This is because:
node.go depends on testtype.go
testtype.go depends on node.go
root.go depends on node.go and testtype.go
go build
builds the files in the page by sorting the filenames alphabetically: node.go
then root.go
then testtype.go
.
If I rename root.go
to z.go
, it builds and runs correctly. Besides renaming root.go
to z.go
which is less than ideal, is there any other way I can get this working in a scalable way?
You could use just one init()
function and put everything in that.
Or if you want to stick with multiple init()
functions in multiple .go
files, then create one "master" init function that will be called init()
, and rename other init functions, e.g. initA()
, initB()
, and call these from the master init in proper order:
func init() {
initA()
initB()
}
See related question+answer: What does lexical file name order mean?