func (field *goStructField) marshaler() (qualifiedName string, needsImport bool, needsMarshaler bool) {
	switch typ := field.GoType.Unwrap().(type) {
	case *goOpaqueType:
		if typ.Marshaler != "" {
			return typ.Marshaler, true, true
		}
	case *goInterfaceType:
		return "__marshal" + typ.Reference(), false, true
	}
	return "encoding/json.Marshal", true, field.IsEmbedded()
}
marshaler returns:
- the fully-qualified name of the function to use to marshal this field
- true if we need to generate an marshaler at all, false if the default
behavior will suffice
package generate
import (
	"fmt"
	"io"
	"strings"
	"github.com/vektah/gqlparser/v2/ast"
)
type goType interface {
	WriteDefinition(io.Writer, *generator) error
	Reference() string
	GraphQLTypeName() string
	SelectionSet() ast.SelectionSet
	Unwrap() goType
	SliceDepth() int
	IsPointer() bool
}
var (
	_ goType = (*goOpaqueType)(nil)
	_ goType = (*goSliceType)(nil)
	_ goType = (*goPointerType)(nil)
	_ goType = (*goEnumType)(nil)
	_ goType = (*goStructType)(nil)
	_ goType = (*goInterfaceType)(nil)
)
type (
	goOpaqueType struct {
		GoRef                  string
		GraphQLName            string
		Marshaler, Unmarshaler string
	}
	goTypenameForBuiltinType struct {
		GoTypeName    string
		GoBuiltinName string
		GraphQLName   string
	}
	goSliceType struct{ Elem goType }
	goPointerType struct{ Elem goType }
)
func (typ *goOpaqueType) WriteDefinition(io.Writer, *generator) error { return nil }
func (typ *goTypenameForBuiltinType) WriteDefinition(w io.Writer, g *generator) error {
	fmt.Fprintf(w, "type %s %s", typ.GoTypeName, typ.GoBuiltinName)
	return nil
}
func (typ *goSliceType) WriteDefinition(io.Writer, *generator) error   { return nil }
func (typ *goPointerType) WriteDefinition(io.Writer, *generator) error { return nil }
func (typ *goOpaqueType) Reference() string             { return typ.GoRef }
func (typ *goTypenameForBuiltinType) Reference() string { return typ.GoTypeName }
func (typ *goSliceType) Reference() string              { return "[]" + typ.Elem.Reference() }
func (typ *goPointerType) Reference() string            { return "*" + typ.Elem.Reference() }
func (typ *goOpaqueType) SelectionSet() ast.SelectionSet             { return nil }
func (typ *goTypenameForBuiltinType) SelectionSet() ast.SelectionSet { return nil }
func (typ *goSliceType) SelectionSet() ast.SelectionSet              { return typ.Elem.SelectionSet() }
func (typ *goPointerType) SelectionSet() ast.SelectionSet            { return typ.Elem.SelectionSet() }
func (typ *goOpaqueType) GraphQLTypeName() string             { return typ.GraphQLName }
func (typ *goTypenameForBuiltinType) GraphQLTypeName() string { return typ.GraphQLName }
func (typ *goSliceType) GraphQLTypeName() string              { return typ.Elem.GraphQLTypeName() }
func (typ *goPointerType) GraphQLTypeName() string            { return typ.Elem.GraphQLTypeName() }
type goEnumType struct {
	GoName      string
	GraphQLName string
	Description string
	Values      []goEnumValue
}
type goEnumValue struct {
	Name        string
	Description string
}
func (typ *goEnumType) WriteDefinition(w io.Writer, g *generator) error {
	writeDescription(w, typ.Description)
	fmt.Fprintf(w, "type %s string\n", typ.GoName)
	fmt.Fprintf(w, "const (\n")
	for _, val := range typ.Values {
		writeDescription(w, val.Description)
		fmt.Fprintf(w, "%s %s = \"%s\"\n",
			typ.GoName+goConstName(val.Name),
			typ.GoName, val.Name)
	}
	fmt.Fprintf(w, ")\n")
	return nil
}
func (typ *goEnumType) Reference() string              { return typ.GoName }
func (typ *goEnumType) SelectionSet() ast.SelectionSet { return nil }
func (typ *goEnumType) GraphQLTypeName() string        { return typ.GraphQLName }
type goStructType struct {
	GoName    string
	Fields    []*goStructField
	IsInput   bool
	Selection ast.SelectionSet
	descriptionInfo
	Generator *generator  
}
type goStructField struct {
	GoName      string
	GoType      goType
	JSONName    string  
	GraphQLName string  
	Omitempty   bool    
	Description string
}
func (field *goStructField) IsAbstract() bool {
	_, ok := field.GoType.Unwrap().(*goInterfaceType)
	return ok
}
func (field *goStructField) IsEmbedded() bool {
	return field.GoName == ""
}
func (field *goStructField) Selector() string {
	if field.GoName != "" {
		return field.GoName
	}
	return field.GoType.Unwrap().Reference()
}
func (field *goStructField) unmarshaler() (qualifiedName string, needsImport bool, needsUnmarshaler bool) {
	switch typ := field.GoType.Unwrap().(type) {
	case *goOpaqueType:
		if typ.Unmarshaler != "" {
			return typ.Unmarshaler, true, true
		}
	case *goInterfaceType:
		return "__unmarshal" + typ.Reference(), false, true
	}
	return "encoding/json.Unmarshal", true, field.IsEmbedded()
}
func (field *goStructField) Unmarshaler(g *generator) (string, error) {
	name, needsImport, _ := field.unmarshaler()
	if needsImport {
		return g.ref(name)
	}
	return name, nil
}