graph-gophers/graphql-go

To achieve the interface is strange.

gunsluo opened this issue · 0 comments

GraphQL Schema for example

# A character from the Star Wars universe
	interface Character {
		# The ID of the character
		id: ID!
		# The name of the character
		name: String!
		# The friends of the character, or an empty list if they have none
		friends: [Character]
		# The friends of the character exposed as a connection with edges
		friendsConnection(first: Int, after: ID): FriendsConnection!
		# The movies this character appears in
		appearsIn: [Episode!]!
	}
type Human implements Character {
		# The ID of the human
		id: ID!
		# What this human calls themselves
		name: String!
		# Height in the preferred unit, default is meters
		height(unit: LengthUnit = METER): Float!
		# Mass in kilograms, or null if unknown
		mass: Float
		# This human's friends, or an empty list if they have none
		friends: [Character]
		# The friends of the human exposed as a connection with edges
		friendsConnection(first: Int, after: ID): FriendsConnection!
		# The movies this human appears in
		appearsIn: [Episode!]!
		# A list of starships this person has piloted, or an empty list if none
		starships: [Starship]
	}

it's golang code

func (r *Resolver) Hero(args struct{ Episode string }) *characterResolver {
	if args.Episode == "EMPIRE" {
		return &characterResolver{&humanResolver{humanData["1000"]}}
	}
	return &characterResolver{&droidResolver{droidData["2001"]}}
}


type character interface {
	ID() graphql.ID
	Name() string
	Friends() *[]*characterResolver
	FriendsConnection(friendsConnectionArgs) (*friendsConnectionResolver, error)
	AppearsIn() []string
}

type characterResolver struct {
	character
}

func (r *characterResolver) ToHuman() (*humanResolver, bool) {
	c, ok := r.character.(*humanResolver)
	return c, ok
}

type humanResolver struct {
	h *human
}

func (r *humanResolver) ID() graphql.ID {
	return r.h.ID
}

func (r *humanResolver) Name() string {
	return r.h.Name
}

func (r *humanResolver) Height(args struct{ Unit string }) float64 {
	return convertLength(r.h.Height, args.Unit)
}

func (r *humanResolver) Mass() *float64 {
	if r.h.Mass == 0 {
		return nil
	}
	f := float64(r.h.Mass)
	return &f
}

func (r *humanResolver) Friends() *[]*characterResolver {
	return resolveCharacters(r.h.Friends)
}

func (r *humanResolver) FriendsConnection(args friendsConnectionArgs) (*friendsConnectionResolver, error) {
	return newFriendsConnectionResolver(r.h.Friends, args)
}

func (r *humanResolver) AppearsIn() []string {
	return r.h.AppearsIn
}

func (r *humanResolver) Starships() *[]*starshipResolver {
	l := make([]*starshipResolver, len(r.h.Starships))
	for i, id := range r.h.Starships {
		l[i] = &starshipResolver{starshipData[id]}
	}
	return &l
}
  1. define character interface
  2. define characterResolver
  3. define humanResolver & Implement interface(character)
  4. achieve characterResolver.ToHuman
  5. call func need Conversion: return &characterResolver{&droidResolver{droidData["2001"]}}

use graphql interface requires more than 5 steps,a bit cumbersome.

  1. define characterResolver interface (replace define character interface)
  2. define humanResolver & Implement interface(character)
  3. call func need Conversion: return &droidResolver{droidData["2001"]},but &characterResolver{&droidResolver{droidData["2001"]}}

E.g

func (r *Resolver) Hero(args struct{ Episode string }) characterResolver {
	if args.Episode == "EMPIRE" {
		return &humanResolver{humanData["1000"]}
	}
	return &droidResolver{droidData["2001"]}
}

type characterResolver interface {
	ID() graphql.ID
	Name() string
	Friends() *[]*characterResolver
	FriendsConnection(friendsConnectionArgs) (*friendsConnectionResolver, error)
	AppearsIn() []string
}

type humanResolver struct {
	h *human
}

func (r *humanResolver) ID() graphql.ID {
	return r.h.ID
}

func (r *humanResolver) Name() string {
	return r.h.Name
}

func (r *humanResolver) Height(args struct{ Unit string }) float64 {
	return convertLength(r.h.Height, args.Unit)
}

func (r *humanResolver) Mass() *float64 {
	if r.h.Mass == 0 {
		return nil
	}
	f := float64(r.h.Mass)
	return &f
}

func (r *humanResolver) Friends() *[]*characterResolver {
	return resolveCharacters(r.h.Friends)
}

func (r *humanResolver) FriendsConnection(args friendsConnectionArgs) (*friendsConnectionResolver, error) {
	return newFriendsConnectionResolver(r.h.Friends, args)
}

func (r *humanResolver) AppearsIn() []string {
	return r.h.AppearsIn
}

func (r *humanResolver) Starships() *[]*starshipResolver {
	l := make([]*starshipResolver, len(r.h.Starships))
	for i, id := range r.h.Starships {
		l[i] = &starshipResolver{starshipData[id]}
	}
	return &l
}

This be easier.

@neelance