Interface implementation question
Hello. I created a simple example according to testutil/testutil.go. But when running my example, I get constant error. Stuck for many hours trying to find out what's wrong with my piece of code.
main.go:
package main
import (
"encoding/json"
"fmt"
"net/http"
"github.com/graphql-go/graphql"
)
var (
Schema graphql.Schema
sectionType *graphql.Object
)
type CbrNode struct {
ID string
TreeID string
RcpaCode string
Name string
}
func init() {
myInterface := graphql.NewInterface(graphql.InterfaceConfig{
Name: "CbrNode",
Description: "A character in the Star Wars Trilogy",
Fields: graphql.Fields{
"id": &graphql.Field{
Type: graphql.NewNonNull(graphql.String),
Description: "The id of the character.",
},
"tree_id": &graphql.Field{
Type: graphql.NewNonNull(graphql.String),
Description: "-",
},
"rcpa_code": &graphql.Field{
Type: graphql.NewNonNull(graphql.String),
Description: "-",
},
},
ResolveType: func(p graphql.ResolveTypeParams) *graphql.Object {
return sectionType
},
})
sectionType = graphql.NewObject(graphql.ObjectConfig{
Name: "CbrSection",
Description: "A humanoid creature in the Star Wars universe.",
Fields: graphql.Fields{
"id": &graphql.Field{
Type: graphql.NewNonNull(graphql.String),
Description: "The id of the character.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if human, ok := p.Source.(CbrNode); ok {
return human.ID, nil
}
return nil, nil
},
},
"tree_id": &graphql.Field{
Type: graphql.NewNonNull(graphql.String),
Description: "The id of the human.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if human, ok := p.Source.(CbrNode); ok {
return human.TreeID, nil
}
return nil, nil
},
},
"rcpa_code": &graphql.Field{
Type: graphql.NewNonNull(graphql.String),
Description: "The name of the human.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if human, ok := p.Source.(CbrNode); ok {
return human.RcpaCode, nil
}
return nil, nil
},
},
"name": &graphql.Field{
Type: graphql.NewNonNull(graphql.String),
Description: "The name of the human.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
if human, ok := p.Source.(CbrNode); ok {
return human.Name, nil
}
return nil, nil
},
},
},
Interfaces: []*graphql.Interface{
myInterface,
},
})
queryType := graphql.NewObject(graphql.ObjectConfig{
Name: "Query",
Fields: graphql.Fields{
"cbr_node": &graphql.Field{
Type: myInterface,
Args: graphql.FieldConfigArgument{
"rcpa_code": &graphql.ArgumentConfig{
Description: "If omitted, returns the hero of the whole saga. If " +
"provided, returns the hero of that particular episode.",
Type: graphql.String,
},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return CbrNode{ID: "1", TreeID: "2", RcpaCode: "3", Name: "4"}, nil
},
},
},
})
var err error
Schema, err = graphql.NewSchema(graphql.SchemaConfig{
Query: queryType,
})
if err != nil {
fmt.Println(err)
}
}
func main() {
http.HandleFunc("/graphql", func(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query().Get("query")
result := graphql.Do(graphql.Params{
Schema: Schema,
RequestString: query,
})
if len(result.Errors) > 0 {
fmt.Printf("errors: %v\n", result.Errors)
}
json.NewEncoder(w).Encode(result)
})
fmt.Println("Now server is running on port 8080")
fmt.Println("Test with Get : curl -g 'http://localhost:8080/graphql?query={cbr_node(rcpa_code:\"1\"){rcpa_code}}'")
http.ListenAndServe(":8080", nil)
}
query:
http://localhost:8080/graphql?query={cbr_node(rcpa_code:"1"){rcpa_code}}
error:
{
"data": {
"cbr_node": null
},
"errors": [
{
"message": "Runtime Object type \"CbrSection\" is not a possible type for \"CbrNode\".",
"locations": [
{
"line": 1,
"column": 2
}
],
"path": [
"cbr_node"
]
}
]
}
Any tips appreciated!
This was not obvious at all, and I too just spent several hours searching for a solution. Turns out, if you want to use your type with an Interface, you need to tell the schema about it in the SchemaConfig.Types. So in your case, I think you'd need to change your schema definition to:
Schema, err = graphql.NewSchema(graphql.SchemaConfig{
Query: queryType,
Types: []graphql.Type[sectionType],
})
I don't know why, but that solved my problem perfectly.
Have same problem here, dont know how to solve. Had try @ki4jnq solution, but dont work on me.