рдЧреНрд░рд╛рдлрдХреЙрд▓ рдФрд░ рдЧреЛрд▓рдВрдЧ

рдкрд┐рдЫрд▓реЗ рдХреБрдЫ рд╡рд░реНрд╖реЛрдВ рдореЗрдВ рдЧреНрд░рд╛рдлрдХреЙрд▓ рддрдХрдиреАрдХ, рдХрдВрдкрдиреА рджреНрд╡рд╛рд░рд╛ рдлреЗрд╕рдмреБрдХ рдХреЛ рдУрдкрди-рд╕реЛрд░реНрд╕ рдХреА рд╢реНрд░реЗрдгреА рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдпрд╣ рдмрд╣реБрдд рд▓реЛрдХрдкреНрд░рд┐рдп рд╣реЛ рдЧрдпрд╛ рд╣реИред рд╕рд╛рдордЧреНрд░реА рдХрд╛ рд▓реЗрдЦрдХ, рдЬрд┐рд╕рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдЖрдЬ рд╣рдо рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдХрд╛ рдХрд╣рдирд╛ рд╣реИ рдХрд┐ рдЙрдиреНрд╣реЛрдВрдиреЗ Node.js рдореЗрдВ рдЧреНрд░рд╛рдлрдХреЙрдХ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдФрд░ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдЕрдиреБрднрд╡ рд╕реЗ, рдЖрд╢реНрд╡рд╕реНрдд рдереЗ рдХрд┐ рдпрд╣ рддрдХрдиреАрдХ, рдЗрд╕рдХреА рдЙрд▓реНрд▓реЗрдЦрдиреАрдп рдХреНрд╖рдорддрд╛рдУрдВ рдФрд░ рд╕рд╛рджрдЧреА рдХреЗ рдХрд╛рд░рдг, рдЧрд▓рддреА рд╕реЗ рдЗрддрдирд╛ рдзреНрдпрд╛рди рдирд╣реАрдВ рджреЗрддреА рд╣реИред рд╣рд╛рд▓ рд╣реА рдореЗрдВ, рдПрдХ рдирдП рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рд▓рдЧреЗ рд░рд╣рдиреЗ рдХреЗ рджреМрд░рд╛рди, рдЙрдиреНрд╣реЛрдВрдиреЗ Node.js рд╕реЗ рдЧреЛрд▓рдВрдЧ рдореЗрдВ рд╕реНрд╡рд┐рдЪ рдХрд┐рдпрд╛ред рддрдм рдЙрдиреНрд╣реЛрдВрдиреЗ рдЧреЛрд▓рдВрдЧ рдФрд░ рдЧреНрд░рд╛рдлрдХреЙрдХ рдХреЗ рд╕рд╣рдпреЛрдЧ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред



рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА


рдЖрдк рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдЧреНрд░рд╛рдлрд╝рдХреЙрд▓ рдкрд░рд┐рднрд╛рд╖рд╛ рд╕реЗ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреНрд╡реЗрд░реА рднрд╛рд╖рд╛ рд╣реИ рдФрд░ рдореМрдЬреВрджрд╛ рдбреЗрдЯрд╛ рдкрд░ рдРрд╕реЗ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд░рдирдЯрд╛рдЗрдо рд╣реИред рдЧреНрд░рд╛рдлрдХреЙрд▓ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдПрдкреАрдЖрдИ рдореЗрдВ рдбреЗрдЯрд╛ рдХрд╛ рдПрдХ рдкреВрд░реНрдг рдФрд░ рд╕рдордЭрдиреЗ рдпреЛрдЧреНрдп рд╡рд┐рд╡рд░рдг рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЛ рдареАрдХ рдЙрд╕реА рдЬрд╛рдирдХрд╛рд░реА рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдЕрдзрд┐рдХ рдХреБрдЫ рдирд╣реАрдВ, рд╕рдордп рдХреЗ рд╕рд╛рде рдПрдкреАрдЖрдИ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЛ рд╕рд░рд▓ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЛ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдЙрдкрдХрд░рдг рджреЗрддрд╛ рд╣реИред

рдЧреЛрд▓рдВрдЧ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕реЗ рдЧреНрд░рд╛рдлрд╝рд┐рдХрд▓ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдирд╣реАрдВ рд╣реИрдВред рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рдореИрдВрдиреЗ рдердВрдбрд░ , рдЧреНрд░реЗрдлреНрд▓ , рдЧреНрд░реЗрдлреНрд▓-рдЧреЛ рдФрд░ рдЧрдХреНрдХреНрдЬреЗрди рдЬреИрд╕реЗ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреА рдХреЛрд╢рд┐рд╢ рдХреАред рдореБрдЭреЗ рдзреНрдпрд╛рди рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдореИрдВрдиреЗ рдЬреЛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд┐рдпрд╛, рд╡рд╣ рдерд╛ рдЧрдХреНрд▓реЗрдЬреЗрди рдкреБрд╕реНрддрдХрд╛рд▓рдпред

Gqlgen рдкреБрд╕реНрддрдХрд╛рд▓рдп рдЕрднреА рднреА рдмреАрдЯрд╛ рдореЗрдВ рд╣реИ, рдЗрд╕ рд╕рд╛рдордЧреНрд░реА рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреЗ рд╕рдордп рдпрд╣ рд╕рдВрд╕реНрдХрд░рдг 0.7.2 рдерд╛ред рдкреБрд╕реНрддрдХрд╛рд▓рдп рддреЗрдЬреА рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛ рд░рд╣рд╛ рд╣реИред рдпрд╣рд╛рдВ рдЖрдк рдЗрд╕рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреА рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВред рдЕрдм gqlgen рдХрд╛ рдЖрдзрд┐рдХрд╛рд░рд┐рдХ рдкреНрд░рд╛рдпреЛрдЬрдХ 99designs рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдпрд╣ рдкреБрд╕реНрддрдХрд╛рд▓рдп, рд╕рдВрднрд╡рддрдГ, рдкрд╣рд▓реЗ рд╕реЗ рднреА рддреЗрдЬреА рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрдЧрд╛ред рдЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рдореБрдЦреНрдп рд╡рд┐рдХрд╛рд╕рдХрд░реНрддрд╛ рд╡реАрдЯрд╛рд╣ рдФрд░ рдиреАрд▓реЗрдВрд╕ рд╣реИрдВ , рдЬрдмрдХрд┐ рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдиреАрд▓реЗрдВрд╕, рдЧреНрд░рд╛рдлрд╝рд┐рдХрд▓-рдЧреЛ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдкрд░ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред

рдЖрдЗрдП рдЗрд╕ рдзрд╛рд░рдгрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ gqlgen рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░реЗрдВ рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЧреНрд░рд╛рдлрд╝рд┐рдХрд▓ рдХрд╛ рдмреБрдирд┐рдпрд╛рджреА рдЬреНрдЮрд╛рди рд╣реИред

Gqlgen рд╕реБрд╡рд┐рдзрд╛рдПрдБ


Gqlgen рд╡рд┐рд╡рд░рдг рдореЗрдВ, рдЖрдк рдпрд╣ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдЧреЛрд▓рдВрдЧ рдореЗрдВ рдХрдбрд╝рд╛рдИ рд╕реЗ рдЯрд╛рдЗрдк рдХрд┐рдП рдЧрдП рдЧреНрд░рд╛рдлрд╝рдХреНрдпреВрдПрд▓ рд╕рд░реНрд╡рд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреНрдпрд╛ рд╣реИред рдпрд╣ рд╡рд╛рдХреНрдпрд╛рдВрд╢ рдореБрдЭреЗ рдмрд╣реБрдд рдЖрд╢рд╛рдЬрдирдХ рд▓рдЧрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдХрд╛ рдорддрд▓рдм рд╣реИ рдХрд┐ рдЗрд╕ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рдореИрдВ map[string]interface{} рдЬреИрд╕реА рдХрд┐рд╕реА рдЪреАрдЬ рдХреЗ рд╕рд╛рде рдирд╣реАрдВ map[string]interface{} , рдХреНрдпреЛрдВрдХрд┐ рд╕рдЦреНрдд рдЯрд╛рдЗрдкрд┐рдВрдЧ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рдПрдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдпрд╣рд╛рдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдбреЗрдЯрд╛ рд╕реНрдХреАрдорд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИред рдЗрд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдПрдкреАрдЖрдИ рдХрд╛ рд╡рд░реНрдгрди рдЧреНрд░рд╛рдлрдХреЙрд▓ рд╕реНрдХреАрдорд╛ рдбреЗрдлрд┐рдирд┐рд╢рди рд▓реИрдВрдЧреНрд╡реЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЗрд╕ рднрд╛рд╖рд╛ рдХреЗ рдЕрдкрдиреЗ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдХреЛрдб рдЬрдирд░реЗрд╢рди рдЯреВрд▓ рд╣реИрдВ рдЬреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ GraphQL рдХреЛрдб рдмрдирд╛рддреЗ рд╣реИрдВред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЗрд╡рд▓ рд╕рдВрдмрдВрдзрд┐рдд рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЗ рдореВрд▓ рддрд░реНрдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддрд╛ рд╣реИред

рдпрд╣ рд▓реЗрдЦ рджреЛ рднрд╛рдЧреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рд╣реИред рдкрд╣рд▓рд╛ рдХрд╛рдо рдХреЗ рдмреБрдирд┐рдпрд╛рджреА рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдкрд┐рдд рд╣реИ, рдФрд░ рджреВрд╕рд░рд╛ рдЙрдиреНрдирдд рд▓реЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдПред

рдХрд╛рдо рдХреЗ рдореБрдЦреНрдп рддрд░реАрдХреЗ: рдбреЗрдЯрд╛ рдХреА рд╕реНрдерд╛рдкрдирд╛, рд╕рджрд╕реНрдпрддрд╛ рдФрд░ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдХрд░рдирд╛


рд╣рдо, рдПрдХ рдкреНрд░рдпреЛрдЧрд╛рддреНрдордХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдХреЗ рд░реВрдк рдореЗрдВ, рдПрдХ рд╕рд╛рдЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ рдЬрд╣рд╛рдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╡реАрдбрд┐рдпреЛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ рдФрд░ рд╕рдореАрдХреНрд╖рд╛рдПрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ, рд╡реАрдбрд┐рдпреЛ рдЦреЛрдЬ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЕрдиреНрдп рд░рд┐рдХреЙрд░реНрдб рд╕реЗ рдЬреБрдбрд╝реЗ рд░рд┐рдХреЙрд░реНрдб рдХреА рд╕реВрдЪреА рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдЗрдП рдЗрд╕ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкрд░ рдХрд╛рдо рд╢реБрд░реВ рдХрд░реЗрдВ:

 mkdir -p $GOPATH/src/github.com/ridhamtarpara/go-graphql-demo/ 

рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдХреЗ рд░реВрдЯ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдореЗрдВ рдирд┐рдореНрди рдбреЗрдЯрд╛ рд╕реНрдХреАрдорд╛ рдлрд╝рд╛рдЗрд▓ ( schema.graphql ) рдмрдирд╛рдПрдБ:

 type User {   id: ID!   name: String!   email: String! } type Video {   id: ID!   name: String!   description: String!   user: User!   url: String!   createdAt: Timestamp!   screenshots: [Screenshot]   related(limit: Int = 25, offset: Int = 0): [Video!]! } type Screenshot {   id: ID!   videoId: ID!   url: String! } input NewVideo {   name: String!   description: String!   userId: ID!   url: String! } type Mutation {   createVideo(input: NewVideo!): Video! } type Query {   Videos(limit: Int = 25, offset: Int = 0): [Video!]! } scalar Timestamp 

рдпрд╣рд╛рдВ рдореВрд▓ рдбреЗрдЯрд╛ рдореЙрдбрд▓, рдПрдХ рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрди ( Mutation , рдбреЗрдЯрд╛ рдкрд░рд┐рд╡рд░реНрддрди рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдХрд╛ рд╡рд░реНрдгрди) рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рд╛рдЗрдЯ рдкрд░ рдирдИ рд╡реАрдбрд┐рдпреЛ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдкреНрд░рдХрд╛рд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рд╕рднреА рд╡реАрдбрд┐рдпреЛ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреА рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреНрд╡реЗрд░реА ( Query )ред рдпрд╣рд╛рдВ рдЧреНрд░рд╛рдлрд╝рд┐рдХрд▓ рд╕реНрдХреАрдорд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдФрд░ рдкрдврд╝реЗрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣рд╛рдВ рд╣рдордиреЗ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд╕реНрдХреЗрд▓рд░ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ред рд╣рдо 5 рдорд╛рдирдХ рд╕реНрдХреЗрд▓рд░ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░реЛрдВ ( Int , Float , String , Boolean рдФрд░ ID ) рд╕реЗ рд╕рдВрддреБрд╖реНрдЯ рдирд╣реАрдВ рд╣реИрдВ, рдЬреЛ рдЧреНрд░рд╛рдлрдХреЙрдЗрди рдореЗрдВ рд╣реИрдВред

рдпрджрд┐ рдЖрдкрдХреЛ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЖрдк рдЙрдиреНрд╣реЗрдВ schema.graphql (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдкреНрд░рдХрд╛рд░ Timestamp ) рдореЗрдВ рдШреЛрд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдХреЛрдб рдореЗрдВ рдЕрдкрдиреА рдкрд░рд┐рднрд╛рд╖рд╛ рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред Gqlgen рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдЖрдкрдХреЛ рдЕрдкрдиреЗ рд╕рднреА рд╕реНрдХреЗрд▓рд░ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдорд╛рд░реНрд╢рд▓рд┐рдВрдЧ рдФрд░ рдЕрдирдорд░реНрд╢рд┐рдВрдЧ рдХреЗ рддрд░реАрдХреЗ рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдФрд░ gqlgen.yml рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдореИрдкрд┐рдВрдЧ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рдиреЗ рдХреА gqlgen.yml ред

рдпрд╣ рдзреНрдпрд╛рди рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рдПрдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдкрд░рд┐рд╡рд░реНрддрди рдерд╛ред рдЕрд░реНрдерд╛рддреН, рд╕рдВрдХрд▓рд┐рдд рдмрд╛рдЗрдирд░реА рдлрд╝рд╛рдЗрд▓реЛрдВ рдкрд░ рдирд┐рд░реНрднрд░рддрд╛ рдХреЛ рдЗрд╕рд╕реЗ рд╣рдЯрд╛ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЗрд╕рд▓рд┐рдП, scripts/gqlgen.go рдлрд╝рд╛рдЗрд▓ рдХреЛ рдирд┐рдореНрди рд╕рд╛рдордЧреНрд░реА рдХреЗ scripts/gqlgen.go рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдЬреЛрдбрд╝рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП:

 // +build ignore package main import "github.com/99designs/gqlgen/cmd" func main() { cmd.Execute() } 

рдЙрд╕рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ dep рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

 dep init 

рдЕрдм рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреА рдХреЛрдб рдЬрдирд░реЗрд╢рди рдХреНрд╖рдорддрд╛рдУрдВ рдХрд╛ рд▓рд╛рдн рдЙрдард╛рдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИред рд╡реЗ рдЖрдкрдХреЛ рд╕рднреА рдЙрдмрд╛рдК рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдХреЛрдб рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ, рдЬреЛ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдирд┐рд░реНрдмрд╛рдз рдирд╣реАрдВ рдХрд╣рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХреЛрдб рдкреАрдврд╝реА рддрдВрддреНрд░ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:

 go run scripts/gqlgen.go init 

рдЗрд╕рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд╛рдЗрд▓реЗрдВ рдмрдирд╛рдИ рдЬрд╛рдПрдВрдЧреА:

  • gqlgen.yml : рдХреЛрдб рдкреАрдврд╝реА рдХреЗ рдкреНрд░рдмрдВрдзрди рдХреЗ рд▓рд┐рдП рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдлрд╝рд╛рдЗрд▓ред
  • generated.go : рдЙрддреНрдкрдиреНрди рдХреЛрдбред
  • models_gen.go : рдЙрдкрд▓рдмреНрдз рд╕реНрдХреАрдорд╛ рдХреЗ рд╕рднреА рдореЙрдбрд▓ рдФрд░ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ред
  • resolver.go : рдпрд╣рд╛рдВ рд╡рд╣ рдХреЛрдб рд╣реЛрдЧрд╛ рдЬреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдмрдирд╛рддрд╛ рд╣реИред
  • server/server.go : http.Handler рдкреЙрдЗрдВрдЯ рд╕рд░реНрд╡рд░ рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП http.Handler рдХреЗ рд╕рд╛рде рдПрдВрдЯреНрд░реА рдкреЙрдЗрдВрдЯред

Video рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдЬрдирд░реЗрдЯ рдХрд┐рдП рдЧрдП рдореЙрдбрд▓ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ (рдлрд╝рд╛рдЗрд▓ generated_video.go ):

 type Video struct { ID          string  `json:"id"` Name        string  `json:"name"` User        User  `json:"user"` URL         string  `json:"url"` CreatedAt   string  `json:"createdAt"` Screenshots []*Screenshot `json:"screenshots"` Related     []Video  `json:"related"` } 

рдпрд╣рд╛рдВ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ ID рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИ, CreatedAt рднреА рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИред рдЕрдиреНрдп рд╕рдВрдмрдВрдзрд┐рдд рдореЙрдбрд▓ рддрджрдиреБрд╕рд╛рд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдП рдЧрдП рд╣реИрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИред рдпрджрд┐ рдЖрдк рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ рдПрд╕рдХреНрдпреВрдПрд▓ рдбреЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, ID рдлрд╝реАрд▓реНрдб рд╣реЛрдЧрд╛, рдЬреЛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЧрдП рдбреЗрдЯрд╛рдмреЗрд╕, рдПрдХ int рдпрд╛ int int64 рдЖрдзрд╛рд░ рдкрд░ рд╣реЛрдЧрд╛ред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдореИрдВ рдЗрд╕ рдбреЗрдореЛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ PostgreSQL рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реВрдВ, рдЗрд╕рд▓рд┐рдП рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдореБрдЭреЗ ID рдлрд╝реАрд▓реНрдб рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдкреНрд░рдХрд╛рд░ рдХреА int рдФрд░ CreatedAt рдкреНрд░рдХрд╛рд░ CreatedAt ред рдпрд╣ рдЗрд╕ рддрдереНрдп рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рд╣рдореЗрдВ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдореЙрдбрд▓ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ gqlgen рдХреЛ рдмрддрд╛рдПрдВ рдХрд┐ рд╣рдореЗрдВ рдПрдХ рдирдпрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдЕрдкрдиреЗ рдореЙрдбрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣рд╛рдБ models.go рдлрд╝рд╛рдЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рд╣реИ:

 type Video struct { ID          int `json:"id"` Name        string `json:"name"` Description string    `json:"description"` User        User `json:"user"` URL         string `json:"url"` CreatedAt   time.Time `json:"createdAt"` Related     []Video } //    int  ID func MarshalID(id int) graphql.Marshaler { return graphql.WriterFunc(func(w io.Writer) {   io.WriteString(w, strconv.Quote(fmt.Sprintf("%d", id))) }) } //        func UnmarshalID(v interface{}) (int, error) { id, ok := v.(string) if !ok {   return 0, fmt.Errorf("ids must be strings") } i, e := strconv.Atoi(id) return int(i), e } func MarshalTimestamp(t time.Time) graphql.Marshaler { timestamp := t.Unix() * 1000 return graphql.WriterFunc(func(w io.Writer) {   io.WriteString(w, strconv.FormatInt(timestamp, 10)) }) } func UnmarshalTimestamp(v interface{}) (time.Time, error) { if tmpStr, ok := v.(int); ok {   return time.Unix(int64(tmpStr), 0), nil } return time.Time{}, errors.TimeStampError } 

рд╣рдо рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЛ рдмрддрд╛рддреЗ рд╣реИрдВ рдХрд┐ рдЙрд╕реЗ рдЗрди рдореЙрдбрд▓реЛрдВ ( gqlgen.yml рдлрд╝рд╛рдЗрд▓) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:

 schema: - schema.graphql exec: filename: generated.go model: filename: models_gen.go resolver: filename: resolver.go type: Resolver models: Video:   model: github.com/ridhamtarpara/go-graphql-demo/api.Video ID:   model: github.com/ridhamtarpara/go-graphql-demo/api.ID Timestamp:   model: github.com/ridhamtarpara/go-graphql-demo/api.Timestamp 

рдЗрди рд╕рдмрдХреЗ рдмреАрдЪ рдпрд╣ рд╣реИ рдХрд┐ рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ ID рдФрд░ Timestamp рдХреЗ рд▓рд┐рдП рдорд╛рд░реНрд╢рд▓рд┐рдВрдЧ рдФрд░ gqlgen.yml рддрд░реАрдХреЛрдВ рдХреА рдЕрдкрдиреА рдкрд░рд┐рднрд╛рд╖рд╛рдПрдБ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ gqlgen.yml рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдореИрдк рдХрд░рдирд╛ рд╣реИред рдЕрдм рдЬрдм рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдПрдХ ID рд░реВрдк рдореЗрдВ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рддреЛ UnmarshalID() рд╡рд┐рдзрд┐ рдЙрд╕ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЛ рдкреВрд░реНрдгрд╛рдВрдХ рдореЗрдВ рдмрджрд▓ рджреЗрддреА рд╣реИред рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рднреЗрдЬрддреЗ рд╕рдордп, MarshalID() рд╡рд┐рдзрд┐ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреА рд╣реИред рдРрд╕рд╛ рд╣реА рдХреБрдЫ Timestamp рд╕рд╛рде рдпрд╛ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рджреНрд╡рд╛рд░рд╛ рдШреЛрд╖рд┐рдд рдХрд┐рд╕реА рдЕрдиреНрдп рд╕реНрдХреЗрд▓рд░ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╣реЛрддрд╛ рд╣реИред

рдЕрдм рдЖрд╡реЗрджрди рддрд░реНрдХ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИред resolver.go рдлрд╝рд╛рдЗрд▓ рдЦреЛрд▓реЗрдВ рдФрд░ рдЙрд╕рдореЗрдВ рдореНрдпреВрдЯреЗрд╢рди рдФрд░ рдХреНрд╡реЗрд░реАрдЬрд╝ рдХрд╛ рд╡рд┐рд╡рд░рдг рдЬреЛрдбрд╝реЗрдВред рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рдмреЙрдпрд▓рд░рдкреНрд▓реЗрдЯ рдХреЛрдб рд╣реИ рдЬрд┐рд╕реЗ рд╣рдореЗрдВ рдЕрд░реНрде рдХреЗ рд╕рд╛рде рднрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕ рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдХреЛрдб рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:

 func (r *mutationResolver) CreateVideo(ctx context.Context, input NewVideo) (api.Video, error) { newVideo := api.Video{   URL:         input.URL,   Name:        input.Name,   CreatedAt:   time.Now().UTC(), } rows, err := dal.LogAndQuery(r.db, "INSERT INTO videos (name, url, user_id, created_at) VALUES($1, $2, $3, $4) RETURNING id",   input.Name, input.URL, input.UserID, newVideo.CreatedAt) defer rows.Close() if err != nil || !rows.Next() {   return api.Video{}, err } if err := rows.Scan(&newVideo.ID); err != nil {   errors.DebugPrintf(err)   if errors.IsForeignKeyError(err) {     return api.Video{}, errors.UserNotExist   }   return api.Video{}, errors.InternalServerError } return newVideo, nil } func (r *queryResolver) Videos(ctx context.Context, limit *int, offset *int) ([]api.Video, error) { var video api.Video var videos []api.Video rows, err := dal.LogAndQuery(r.db, "SELECT id, name, url, created_at, user_id FROM videos ORDER BY created_at desc limit $1 offset $2", limit, offset) defer rows.Close();   if err != nil {   errors.DebugPrintf(err)   return nil, errors.InternalServerError } for rows.Next() {   if err := rows.Scan(&video.ID, &video.Name, &video.URL, &video.CreatedAt, &video.UserID); err != nil {     errors.DebugPrintf(err)     return nil, errors.InternalServerError   }   videos = append(videos, video) } return videos, nil } 

рдЕрдм рдореНрдпреВрдЯреЗрд╢рди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╣реИрдВред

рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрди createVideo

рдпрд╣ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ! рд▓реЗрдХрд┐рди рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЬрд╛рдирдХрд╛рд░реА ( user рд╡рд╕реНрддреБ) рдореЗрдВ рдХреБрдЫ рднреА рдХреНрдпреЛрдВ рдирд╣реАрдВ рд╣реИ? рдЧреНрд░рд╛рдлрдХрд▓рд╛рдЗрди рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп, "рдЖрд▓рд╕реА" (рдЖрд▓рд╕реА) рдФрд░ "рд▓рд╛рд▓рдЪреА" (рдЙрддреНрд╕реБрдХ) рд▓реЛрдбрд┐рдВрдЧ рдХреЗ рд╕рдорд╛рди рдЕрд╡рдзрд╛рд░рдгрд╛рдПрдВ рд▓рд╛рдЧреВ рд╣реЛрддреА рд╣реИрдВред рдЪреВрдВрдХрд┐ рдпрд╣ рдкреНрд░рдгрд╛рд▓реА рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд▓ рд╣реИ, рдЖрдкрдХреЛ рдпрд╣ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХрд┐рди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ "рд▓рд╛рд▓рдЪ" рд╕реЗ рднрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ рдЬреЛ "рдЖрд▓рд╕реА" рд╣реИрдВред

рдореИрдВрдиреЗ рдЙрд╕ рд╕рдВрдЧрдарди рдореЗрдВ рдЯреАрдо рдХреЛ рд╕реБрдЭрд╛рд╡ рджрд┐рдпрд╛, рдЬрд╣рд╛рдВ рдореИрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд "рд╕реБрдирд╣рд░рд╛ рдирд┐рдпрдо" рдХрд╛рдо рдХрд░рддрд╛ рд╣реВрдВ, рдЬреЛ gqlgen рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИ: "рдореЙрдбрд▓ рдореЗрдВ рдЙрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рд╢рд╛рдорд┐рд▓ рди рдХрд░реЗрдВ рдЬрд┐рдиреНрд╣реЗрдВ рдХреЗрд╡рд▓ рдХреНрд▓рд╛рдЗрдВрдЯ рджреНрд╡рд╛рд░рд╛ рдЕрдиреБрд░реЛрдз рдХрд┐рдП рдЬрд╛рдиреЗ рдкрд░ рд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред"

рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдореБрдЭреЗ рд╕рдВрдмрдВрдзрд┐рдд рд╡реАрдбрд┐рдпреЛ рдХреНрд▓рд┐рдк (рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЬрд╛рдирдХрд╛рд░реА) рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдбреЗрдЯрд╛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХреЗрд╡рд▓ рдЕрдЧрд░ рдЧреНрд░рд╛рд╣рдХ рдЗрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЬрдм рд╕реЗ рд╣рдордиреЗ рдЗрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдореЙрдбрд▓ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛, gqlgen рдорд╛рдирддрд╛ рд╣реИ рдХрд┐ рд╣рдо рд╡реАрдбрд┐рдпреЛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдХреЗ рдпрд╣ рдбреЗрдЯрд╛ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рдирддреАрдЬрддрди, рдЕрдм рд╣рдореЗрдВ рдЦрд╛рд▓реА рд╕рдВрд░рдЪрдирд╛рдПрдВ рдорд┐рд▓рддреА рд╣реИрдВред

рдХрднреА-рдХрднреА рдРрд╕рд╛ рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рд╣рд░ рдмрд╛рд░ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдбреЗрдЯрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рдЕрдиреБрд░реЛрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдирд╛ рдЕрд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП, рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк SQL рдЬреЙрдЗрди рдЬреИрд╕реЗ рдХреБрдЫ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдПрдХ рдмрд╛рд░ (рдпрд╣, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣рд╛рдВ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдкрд░ рд▓рд╛рдЧреВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ), рдореБрдЭреЗ рд╡реАрдбрд┐рдпреЛ рдХреЗ рд╕рд╛рде рдЗрд╕рдХреЗ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреЛ рдЕрдкрд▓реЛрдб рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрди рд╕рдВрд╕реНрдерд╛рдУрдВ рдХреЛ рд╡рд┐рднрд┐рдиреНрди рд╕реНрдерд╛рдиреЛрдВ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдЕрдЧрд░ рдореЗрд░реЗ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рд╡реАрдбрд┐рдпреЛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХрд╛ рдЕрдиреБрд░реЛрдз рдорд┐рд▓рд╛, рддреЛ рдореБрдЭреЗ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдЕрдиреБрд░реЛрдз рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд▓реЗрдХрд┐рди, рдЬрдм рд╕реЗ рдореБрдЭреЗ рдЗрд╕ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрддрд╛ рдерд╛ (рдЕрд░реНрдерд╛рдд, рдореБрдЭреЗ рдкрддрд╛ рдерд╛ рдХрд┐ рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╡реАрдбрд┐рдпреЛ рдФрд░ рдЙрд╕рдХреЗ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдХреА рд╣рдореЗрд╢рд╛ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреА рддрд░рдл рдЬрд░реВрд░рдд рд╣реЛрддреА рд╣реИ), рдореИрдВрдиреЗ рдкреНрд░рджрд░реНрд╢рди рдХреЛ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд╛рд▓рдЪреА рд▓реЛрдбрд┐рдВрдЧ рддрдХрдиреАрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд┐рдпрд╛ред

рдЖрдЗрдП рдореЙрдбрд▓ рдХреЛ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦреЗрдВ рдФрд░ рдлрд┐рд░ рд╕реЗ gqlgen рдХреЛрдб рдЬрдирд░реЗрдЯ рдХрд░реЗрдВред рдХрд╣рд╛рдиреА рдХреЛ рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдХреЗрд╡рд▓ user рдлрд╝реАрд▓реНрдб рдХреЗ рд▓рд┐рдП рддрд░реАрдХреЗ рд▓рд┐рдЦрддреЗ рд╣реИрдВ (рдлрд╝рд╛рдЗрд▓ models.go ):

 type Video struct { ID          int `json:"id"` Name        string `json:"name"` Description string    `json:"description"` UserID      int `json:"-"` URL         string `json:"url"` CreatedAt   time.Time `json:"createdAt"` } 

рд╣рдордиреЗ рдПрдХ User рдЬреЛрдбрд╝рд╛ рдФрд░ User рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд╣рдЯрд╛ рджрд┐рдпрд╛ред рдЕрдм рдХреЛрдб рдкреБрди: рдмрдирд╛рдПрдБ:

 go run scripts/gqlgen.go -v 

рдЗрд╕ рдЖрджреЗрд╢ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж, рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╡рд┐рдзрд┐рдпреЛрдВ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдкрдХреЛ рд░рд┐рдЬрд╝реЙрд▓реНрд╡рд░ ( generated.go рдлрд╝рд╛рдЗрд▓) рдореЗрдВ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

 type VideoResolver interface { User(ctx context.Context, obj *api.Video) (api.User, error) Screenshots(ctx context.Context, obj *api.Video) ([]*api.Screenshot, error) Related(ctx context.Context, obj *api.Video, limit *int, offset *int) ([]api.Video, error) } 

рдпрд╣рд╛рдБ рдкрд░рд┐рднрд╛рд╖рд╛ ( resolver.go рдлрд╝рд╛рдЗрд▓) рд╣реИ:

 func (r *videoResolver) User(ctx context.Context, obj *api.Video) (api.User, error) { rows, _ := dal.LogAndQuery(r.db,"SELECT id, name, email FROM users where id = $1", obj.UserID) defer rows.Close() if !rows.Next() {   return api.User{}, nil } var user api.User if err := rows.Scan(&user.ID, &user.Name, &user.Email); err != nil {   errors.DebugPrintf(err)   return api.User{}, errors.InternalServerError } return user, nil } 

рдЕрдм, рдореНрдпреВрдЯреЗрд╢рди рдЯреЗрд╕реНрдЯ рдХреЗ рдкрд░рд┐рдгрд╛рдо рдиреАрдЪреЗ рджрд┐рдЦрд╛рдП рдЧрдП рдЕрдиреБрд╕рд╛рд░ рд╣реЛрдВрдЧреЗред


рдЙрддреНрдкрд░рд┐рд╡рд░реНрддрди createVideo

рдЬрд┐рд╕ рдЪреАрдЬ рдкрд░ рд╣рдордиреЗ рдЪрд░реНрдЪрд╛ рдХреА рд╣реИ, рд╡рд╣ рдЧреНрд░рд╛рдлрдХреНрдпреВрдПрд▓ рдХреА рдмреБрдирд┐рдпрд╛рджреА рдмрд╛рддреЛрдВ рдореЗрдВ рдорд╣рд╛рд░рдд рд╣рд╛рд╕рд┐рд▓ рд╣реИ, рдЬрд┐рд╕реЗ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдкрдирд╛ рдХреБрдЫ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рдЖрдк рдЧреНрд░рд╛рдлрдХреЙрд▓ рдФрд░ рдЧреЛрд▓рдВрдЧ рдХреЗ рдкреНрд░рдпреЛрдЧреЛрдВ рдореЗрдВ рдЙрддрд░реЗрдВ, рд╕рджрд╕реНрдпрддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛, рдЬреЛ рд╕реАрдзреЗ рддреМрд░ рдкрд░ рд╣рдо рдпрд╣рд╛рдВ рдХреНрдпрд╛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╕реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИрдВред

тЦН рд╕рджрд╕реНрдпрддрд╛


GraphQL рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдореЗрдВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдбреЗрдЯрд╛ рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреА рд╕рджрд╕реНрдпрддрд╛ рд▓реЗрдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред Gqlgen рдкреБрд╕реНрддрдХрд╛рд▓рдп, рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдореЗрдВ, рд╡реЗрдм рд╕реЙрдХреЗрдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рд╕рдмреНрд╕рдХреНрд░рд┐рдкреНрд╢рди рдШрдЯрдирд╛рдУрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рд╕рджрд╕реНрдпрддрд╛ рдХреЛ schema.graphql рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрд╣рд╛рдБ рд╡реАрдбрд┐рдпреЛ рдкреНрд░рдХрд╛рд╢рди рдШрдЯрдирд╛ рдХреЗ рд▓рд┐рдП рд╕рджрд╕реНрдпрддрд╛ рдХрд╛ рд╡рд░реНрдгрди рд╣реИ:

 type Subscription {   videoPublished: Video! } 

рдЕрдм, рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХреЛрдб рдкреАрдврд╝реА рдлрд┐рд░ рд╕реЗ рдЪрд▓рд╛рдПрдБ:

 go run scripts/gqlgen.go -v 

рдЬреИрд╕рд╛ рдХрд┐ рдкрд╣рд▓реЗ рд╣реА рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, generated.go рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдХреЛрдб рдХреЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдирд┐рд░реНрдорд╛рдг рдХреЗ рджреМрд░рд╛рди, рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕реЗ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ ( resolver.go file):

 var videoPublishedChannel map[string]chan api.Video func init() { videoPublishedChannel = map[string]chan api.Video{} } type subscriptionResolver struct{ *Resolver } func (r *subscriptionResolver) VideoPublished(ctx context.Context) (<-chan api.Video, error) { id := randx.String(8) videoEvent := make(chan api.Video, 1) go func() {   <-ctx.Done() }() videoPublishedChannel[id] = videoEvent return videoEvent, nil } func (r *mutationResolver) CreateVideo(ctx context.Context, input NewVideo) (api.Video, error) { //   ... for _, observer := range videoPublishedChannel {   observer <- newVideo } return newVideo, nil } 

рдЕрдм, рдПрдХ рдирдпрд╛ рд╡реАрдбрд┐рдпреЛ рдмрдирд╛рддреЗ рд╕рдордп, рдЖрдкрдХреЛ рдПрдХ рдИрд╡реЗрдВрдЯ рдЯреНрд░рд┐рдЧрд░ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдпрд╣ for _, observer := range videoPublishedChannel рд▓рд╛рдЗрди рдореЗрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдЕрдм рдЖрдкрдХреА рд╕рджрд╕реНрдпрддрд╛ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИред


рд╕рджрд╕реНрдпрддрд╛ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░реЗрдВ

рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдЧреНрд░рд╛рдлрд╝рд┐рдХрд▓ рдореЗрдВ рдХреБрдЫ рдореВрд▓реНрдпрд╡рд╛рди рдХреНрд╖рдорддрд╛рдПрдВ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЬреИрд╕рд╛ рдХрд┐ рд╡реЗ рдХрд╣рддреЗ рд╣реИрдВ, рдпрд╣ рд╕рдм рдирд╣реАрдВ рд╣реИ рдХрд┐ рдЧреНрд▓рд┐рдЯрд░ рд╕реЛрдирд╛ рд╣реИред рдЕрд░реНрдерд╛рддреН, рд╣рдо рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХрд┐ рдХреЛрдИ рд╡реНрдпрдХреНрддрд┐ рдЬреЛ рдЧреНрд░рд╛рдлрд╝рд┐рдХрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдЙрд╕реЗ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдХреА рджреЗрдЦрднрд╛рд▓, рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рдЬрдЯрд┐рд▓рддрд╛, рдХреИрд╢рд┐рдВрдЧ, рдПрди + 1 рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдорд╕реНрдпрд╛, рдХреНрд╡реЗрд░реА рдирд┐рд╖реНрдкрд╛рджрди рдХреА рдЧрддрд┐ рдХреА рд╕реАрдорд╛ рдФрд░ рдХреБрдЫ рдЕрдиреНрдп рдЪреАрдЬреЛрдВ рдХрд╛ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЕрдиреНрдпрдерд╛, GraphQL рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рдПрдХ рдкреНрд░рдгрд╛рд▓реА рдХреЛ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рдПрдХ рдЧрдВрднреАрд░ рдЧрд┐рд░рд╛рд╡рдЯ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рдирд╛ рдкрдбрд╝ рд╕рдХрддрд╛ рд╣реИред

рдЙрдиреНрдирдд рддрдХрдиреАрдХ: рдкреНрд░рдорд╛рдгреАрдХрд░рдг, рдбреЗрдЯрд╛ рд▓реЛрдбрд░, рдХреНрд╡реЗрд░реА рдЬрдЯрд┐рд▓рддрд╛


рдЬрдм рднреА рдореИрдВ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдореИрдиреБрдЕрд▓ рдкрдврд╝рддрд╛ рд╣реВрдВ, рдореБрдЭреЗ рдпрд╣ рдПрд╣рд╕рд╛рд╕ рд╣реЛрддрд╛ рд╣реИ рдХрд┐, рдЙрдиреНрд╣реЗрдВ рдорд╣рд╛рд░рдд рд╣рд╛рд╕рд┐рд▓ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдореИрдВ рд╡рд╣ рд╕рдм рдХреБрдЫ рд╕реАрдЦрддрд╛ рд╣реВрдВ, рдЬреЛ рдореБрдЭреЗ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рддрдХрдиреАрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ рдФрд░ рдХрд┐рд╕реА рднреА рдЬрдЯрд┐рд▓рддрд╛ рдХреА рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рд╣реИред

рд▓реЗрдХрд┐рди рдЬрдм рдореИрдВ рдЕрдкрдиреА рдЦреБрдж рдХреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдкрд░ рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реВрдВ, рддреЛ рдореИрдВ рдЖрдорддреМрд░ рдкрд░ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдореЗрдВ рдЖ рдЬрд╛рддрд╛ рд╣реВрдВ рдЬреЛ рд╕рд░реНрд╡рд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдпрд╛ рдЙрди рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рддрд░рд╣ рджрд┐рдЦрддреА рд╣реИрдВ рдЬреЛ рдЙрдореНрд░ рдХреЗ рд▓рд┐рдП рдЪрд▓ рд░рд╣реЗ рд╣реИрдВ, рдпрд╛ рдХреБрдЫ рдЕрдиреНрдп рдЧрддрд┐рд░реЛрдз рд╕реНрдерд┐рддрд┐рдпреЛрдВ рдХреА рддрд░рд╣ рд╣реИрдВред рдирддреАрдЬрддрди, рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореБрдЭреЗ рдмреЗрд╣рддрд░ рддрд░реАрдХреЗ рд╕реЗ рд╕рдордЭрд╛рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рд╕рдордЭ рдореЗрдВ рдЖрдпрд╛ рдерд╛ред рдЗрд╕реА рдирд┐рдпрдорд╛рд╡рд▓реА рдореЗрдВ, рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдЗрд╕рд╕реЗ рдмрдЪрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдЗрд╕ рдЦрдВрдб рдореЗрдВ рд╣рдо рдЧреНрд░рд╛рдлрдХреЙрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдЙрдиреНрдирдд рддрдХрдиреАрдХреЛрдВ рдХреЛ рджреЗрдЦреЗрдВрдЧреЗред

Ication рдкреНрд░рдорд╛рдгреАрдХрд░рдг


REST API рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдкреНрд░рдгрд╛рд▓реА рдФрд░ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп рдорд╛рдирдХ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдЙрдкрдХрд░рдг рд╣реЛрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рдЧреНрд░рд╛рдлрдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп, рдХреЗрд╡рд▓ рдПрдХ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП, рд╕реНрдХреАрдорд╛ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред schema.graphql рд╕рдВрдкрд╛рджрд┐рдд рдХрд░реЗрдВред

 type Mutation {   createVideo(input: NewVideo!): Video! @isAuthenticated } directive @isAuthenticated on FIELD_DEFINITION 

рд╣рдордиреЗ isAuthenticated рдирд┐рд░реНрджреЗрд╢ рдмрдирд╛рдпрд╛ рдФрд░ рдЗрд╕реЗ createVideo рд╕рджрд╕реНрдпрддрд╛ рдкрд░ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ред рдЕрдЧрд▓реЗ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХреЛрдб рдкреАрдврд╝реА рд╕рддреНрд░ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдЗрд╕ рдирд┐рд░реНрджреЗрд╢ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рднрд╛рд╖рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЕрдм рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдирд╣реАрдВ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдЙрдирдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдореИрдВрдиреЗ server.go рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕реНрдерд┐рдд рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдЙрддреНрдкрдиреНрди рдХреЛрдб рдХреЛ server.go рдФрд░ рдПрдХ рдРрд╕реА рд╡рд┐рдзрд┐ рдмрдирд╛рдИ, рдЬреЛ server.go рдлрд╝рд╛рдЗрд▓ рдХреЗ рд▓рд┐рдП рдЧреНрд░рд╛рдлрдХреЙрд▓ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЛ server.go рд╣реИред рдпрд╣рд╛рдБ resolver.go рдлрд╝рд╛рдЗрд▓ рд╣реИ:

 func NewRootResolvers(db *sql.DB) Config { c := Config{   Resolvers: &Resolver{     db: db,   }, } //   c.Directives.IsAuthenticated = func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) {   ctxUserID := ctx.Value(UserIDCtxKey)   if ctxUserID != nil {     return next(ctx)   } else {     return nil, errors.UnauthorisedError   } } return c } 

рдпрд╣рд╛рдБ server.go рдлрд╝рд╛рдЗрд▓ рд╣реИ:

 rootHandler:= dataloaders.DataloaderMiddleware(   db,   handler.GraphQL(     go_graphql_demo.NewExecutableSchema(go_graphql_demo.NewRootResolvers(db)   ) ) http.Handle("/query", auth.AuthMiddleware(rootHandler)) 

рд╣рдо рд╕рдВрджрд░реНрдн рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ ID рдкрдврд╝рддреЗ рд╣реИрдВред рдХреНрдпрд╛ рдЖрдкрдХреЛ рдпрд╣ рдЕрдЬреАрдм рдирд╣реАрдВ рд▓рдЧрддрд╛? рдпрд╣ рдЕрд░реНрде рд╕рдВрджрд░реНрдн рдореЗрдВ рдХреИрд╕реЗ рдЖрдпрд╛ рдФрд░ рдпрд╣ рд╕рдВрджрд░реНрдн рдореЗрдВ рднреА рдХреНрдпреЛрдВ рдкреНрд░рдХрдЯ рд╣реБрдЖ? рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ gqlgen рдХреЗрд╡рд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕реНрддрд░ рдкрд░ рдЕрдиреБрд░реЛрдз рд╕рдВрджрд░реНрдн рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХрд┐рд╕реА рднреА HTTP рдЕрдиреБрд░реЛрдз рдбреЗрдЯрд╛, рдЬреИрд╕реЗ рд╣реЗрдбрд░ рдпрд╛ рдХреБрдХреАрдЬрд╝, рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдпрд╛ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдореЗрдВ рдкрдврд╝рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИред рдирддреАрдЬрддрди, рдЖрдкрдХреЛ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдордзреНрдпрд╡рд░реНрддреА рддрдВрддреНрд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЬрд░реВрд░рдд рд╣реИ, рдЗрд╕ рдбреЗрдЯрд╛ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдбрд╛рд▓реЗрдВред

рдЕрдм рд╣рдореЗрдВ рдЕрдиреБрд░реЛрдз рд╕реЗ рдкреНрд░рдорд╛рдгреАрдХрд░рдг рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рдЗрд╕реЗ рд╕рддреНрдпрд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдордзреНрдпрд╡рд░реНрддреА рдкреНрд░рдорд╛рдгреАрдХрд░рдг рддрдВрддреНрд░ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред

рдХреЛрдИ рддрд░реНрдХ рдпрд╣рд╛рдБ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдирд╣реАрдВ рд╣реИред рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рдкреНрд░рджрд░реНрд╢рди рдЙрджреНрджреЗрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ ID рдмрд╕ рдпрд╣рд╛рдВ рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ рддрдВрддреНрд░ рдлрд┐рд░ рдПрдХ рдирдпрд╛ рд╡рд┐рдиреНрдпрд╛рд╕ рд▓реЛрдб рдХрд░рдиреЗ рдХреА рд╡рд┐рдзрд┐ рдХреЗ рд╕рд╛рде server.go рдореЗрдВ рд╕рдВрдпреБрдХреНрдд рд╣реИред

рдЕрдм рдирд┐рд░реНрджреЗрд╢ рдХрд╛ рд╡рд░реНрдгрди рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИред рд╣рдо рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛрдб рдореЗрдВ рдЕрдирдзрд┐рдХреГрдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдРрд╕реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдирд┐рд░реНрджреЗрд╢ рджреНрд╡рд╛рд░рд╛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрд╣рд╛рдБ рд╣реИ рдХрд┐ рдпрд╣ рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИред


рдПрдХ рдЕрдирдзрд┐рдХреГрдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВ


рдЕрдзрд┐рдХреГрдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВ

рд╕реНрдХреАрдорд╛ рдирд┐рд░реНрджреЗрд╢реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп, рдЖрдк рддрд░реНрдХ рднреА рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

 directive @hasRole(role: Role!) on FIELD_DEFINITION enum Role { ADMIN USER } 

тЦНрджрддреНрддрд╛ рд▓реЛрдбрд░


рдпрд╣ рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдм рдмрд╣реБрдд рджрд┐рд▓рдЪрд╕реНрдк рд▓рдЧ рд░рд╣рд╛ рд╣реИред рдЬрд░реВрд░рдд рдкрдбрд╝рдиреЗ рдкрд░ рдЖрдк рдбреЗрдЯрд╛ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рддреЗ рд╣реИрдВред рдЧреНрд░рд╛рд╣рдХреЛрдВ рдХреЗ рдкрд╛рд╕ рдбреЗрдЯрд╛ рдХреЛ рдкреНрд░рдмрдВрдзрд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реЛрддреА рд╣реИ; рд▓реЗрдХрд┐рди рд╣рд░ рдЪреАрдЬ рдХреА рдПрдХ рдХреАрдордд рд╣реЛрддреА рд╣реИред

рдЗрди рдЕрд╡рд╕рд░реЛрдВ рдХреЗ рд▓рд┐рдП рднреБрдЧрддрд╛рди рдХрд░рдиреЗ рдХреА рдХреАрдордд рдХреНрдпрд╛ рд╣реИ? рд╕рднреА рд╡реАрдбрд┐рдпреЛ рдХреЗ рдбрд╛рдЙрдирд▓реЛрдб рд▓реЙрдЧ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред рдЕрд░реНрдерд╛рддреН, рд╣рдо рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ 8 рд╡реАрдбрд┐рдпреЛ рдФрд░ 5 рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╣реИрдВред

 query{ Videos(limit: 10){   name   user{     name   } } } 


рд╡реАрдбрд┐рдпреЛ рдбрд╛рдЙрдирд▓реЛрдб рд╡рд┐рд╡рд░рдг

 Query: Videos : SELECT id, name, description, url, created_at, user_id FROM videos ORDER BY created_at desc limit $1 offset $2 Resolver: User : SELECT id, name, email FROM users where id = $1 Resolver: User : SELECT id, name, email FROM users where id = $1 Resolver: User : SELECT id, name, email FROM users where id = $1 Resolver: User : SELECT id, name, email FROM users where id = $1 Resolver: User : SELECT id, name, email FROM users where id = $1 Resolver: User : SELECT id, name, email FROM users where id = $1 Resolver: User : SELECT id, name, email FROM users where id = $1 Resolver: User : SELECT id, name, email FROM users where id = $1 

рдпрд╣рд╛рдБ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ? 9 рдЕрдиреБрд░реЛрдз рдХреНрдпреЛрдВ рд╣реИрдВ (1 рдЕрдиреБрд░реЛрдз рд╡реАрдбрд┐рдпреЛ рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рд╕рд╛рде рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИ рдФрд░ 8 - рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рддрд╛рд▓рд┐рдХрд╛ рдХреЗ рд╕рд╛рде)? рдпрд╣ рднрдпрд╛рдирдХ рд▓рдЧ рд░рд╣рд╛ рд╣реИред рдореЗрд░рд╛ рджрд┐рд▓ рд▓рдЧрднрдЧ рд░реБрдХ рдЧрдпрд╛ рдЬрдм рдореИрдВрдиреЗ рд╕реЛрдЪрд╛ рдХрд┐ рд╣рдорд╛рд░реЗ рдореМрдЬреВрджрд╛ рдПрдкреАрдЖрдИ рдХреЛ рдЗрд╕реЗ рдмрджрд▓рдирд╛ рд╣реЛрдЧрд╛ ... рд╕рдЪ рд╣реИ, рдбреЗрдЯрд╛ рд▓реЛрдбрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЗрд╕реЗ N + 1 рд╕рдорд╕реНрдпрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдЬрд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рд╣рдо рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдХрд┐ рд╕рднреА рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХреНрд╡реЗрд░реА рд╣реИ рдФрд░ рдбреЗрдЯрд╛ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдЯреБрдХрдбрд╝реЗ (рдПрди) рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдХреНрд╡реЗрд░реА рд╣реЛрдЧреАред

рдЬрдм рдпрд╣ рдкреНрд░рджрд░реНрд╢рди рдФрд░ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреА рдмрд╛рдд рдЖрддреА рд╣реИ, рддреЛ рдпрд╣ рдПрдХ рдмрд╣реБрдд рд╣реА рдЧрдВрднреАрд░ рд╕рдорд╕реНрдпрд╛ рд╣реИ: рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпреЗ рдЕрдиреБрд░реЛрдз рд╕рдорд╛рдирд╛рдВрддрд░ рд╣реИрдВ, рдпреЗ рд╕рд┐рд╕реНрдЯрдо рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреЛ рд╕реВрдЦрд╛ рджреЗрддреЗ рд╣реИрдВред

рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо gqlgen рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓реЗрдЦрдХ рд╕реЗ dataloaden рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдпрд╣ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЖрдкрдХреЛ рдЧреЛ рдХреЛрдб рдЬрдирд░реЗрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, User рдЗрдХрд╛рдИ рдХреЗ рд▓рд┐рдП рдПрдХ рдбреЗрдЯрд╛ рд▓реЛрдбрд░ рдмрдирд╛рдПрдБ:

 go get github.com/vektah/dataloaden dataloaden github.com/ridhamtarpara/go-graphql-demo/api.User 

рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдлрд╝рд╛рдЗрд▓ userloader_gen.go , рдЬрд┐рд╕рдореЗрдВ Fetch , LoadAll рдФрд░ Prime рдЬреИрд╕реА рд╡рд┐рдзрд┐рдпрд╛рдБ рд╣реИрдВред

рдЕрдм, рд╕рд╛рдорд╛рдиреНрдп рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ Fetch рд╡рд┐рдзрд┐ ( dataloader.go рдлрд╝рд╛рдЗрд▓) рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

 func DataloaderMiddleware(db *sql.DB, next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {   userloader := UserLoader{     wait : 1 * time.Millisecond,     maxBatch: 100,     fetch: func(ids []int) ([]*api.User, []error) {       var sqlQuery string       if len(ids) == 1 {         sqlQuery = "SELECT id, name, email from users WHERE id = ?"       } else {         sqlQuery = "SELECT id, name, email from users WHERE id IN (?)"       }       sqlQuery, arguments, err := sqlx.In(sqlQuery, ids)       if err != nil {         log.Println(err)       }       sqlQuery = sqlx.Rebind(sqlx.DOLLAR, sqlQuery)       rows, err := dal.LogAndQuery(db, sqlQuery, arguments...)       defer rows.Close();       if err != nil {         log.Println(err)       }       userById := map[int]*api.User{}       for rows.Next() {         user:= api.User{}         if err := rows.Scan(&user.ID, &user.Name, &user.Email); err != nil {           errors.DebugPrintf(err)           return nil, []error{errors.InternalServerError}         }         userById[user.ID] = &user       }       users := make([]*api.User, len(ids))       for i, id := range ids {         users[i] = userById[id]         i++       }       return users, nil     },   }   ctx := context.WithValue(r.Context(), CtxKey, &userloader)   r = r.WithContext(ctx)   next.ServeHTTP(w, r) }) } 

рдпрд╣рд╛рдВ рд╣рдо 1 рдПрдордПрд╕ рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░рддреЗ рд╣реИрдВред рдЕрдиреБрд░реЛрдз рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдФрд░ 100 рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдкреИрдХреЗрдЬ рдореЗрдВ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдЗрдХрдЯреНрдард╛ рдХрд░реЗрдВред рдЕрдм, рдкреНрд░рддреНрдпреЗрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЗ рд▓рд┐рдП рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдПрдХ рдЕрдиреБрд░реЛрдз рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп, рд▓реЛрдбрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕рдордп рдХреА рдкреНрд░рддреАрдХреНрд╖рд╛ рдХрд░реЗрдЧрд╛ред рдЗрд╕рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдбреЗрдЯрд╛ рд▓реЛрдбрд░ ( resolver.go рдлрд╝рд╛рдЗрд▓) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдЕрдиреБрд░реЛрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рдкрд╣рдЪрд╛рдирдиреЗ рд╡рд╛рд▓реЗ рддрд░реНрдХ рдХреЛ рдмрджрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:

 func (r *videoResolver) User(ctx context.Context, obj *api.Video) (api.User, error) { user, err := ctx.Value(dataloaders.CtxKey).(*dataloaders.UserLoader).Load(obj.UserID) return *user, err } 

рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдКрдкрд░ рд╡рд░реНрдгрд┐рдд рд╕реНрдерд┐рддрд┐ рдХреЗ рд╕рдорд╛рди рд╣реА рд▓реЙрдЧ рдХреИрд╕реЗ рджрд┐рдЦрддрд╛ рд╣реИ:

 Query: Videos : SELECT id, name, description, url, created_at, user_id FROM videos ORDER BY created_at desc limit $1 offset $2 Dataloader: User : SELECT id, name, email from users WHERE id IN ($1, $2, $3, $4, $5) 

рдХреЗрд╡рд▓ рджреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рдпрд╣рд╛рдВ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рд╣рд░ рдХреЛрдИ рдЕрдм рдЦреБрд╢ рд╣реИред рдпрд╣ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ рдХрд┐ рдХреЗрд╡рд▓ 5 рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдХреЛ рдЕрдиреБрд░реЛрдз рднреЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ 8 рд╡реАрдбрд┐рдпреЛ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рдбреЗрдЯрд╛ рд▓реЛрдбрд░ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рд░рд┐рдХреЙрд░реНрдб рдХреЛ рд╣рдЯрд╛ рджреЗрддрд╛ рд╣реИред

тЦН


GraphQL API , . , API DOS-.

, .

Video , . GraphQL Video . . тАФ .

, тАФ :

 { Videos(limit: 10, offset: 0){   name   url   related(limit: 10, offset: 0){     name     url     related(limit: 10, offset: 0){       name       url       related(limit: 100, offset: 0){         name         url       }     }   } } } 

100, . (, , ) , .

gqlgen , . , ( handler.ComplexityLimit(300) ) GraphQL (300 ). , ( server.go ):

 rootHandler:= dataloaders.DataloaderMiddleware( db, handler.GraphQL(   go_graphql_demo.NewExecutableSchema(go_graphql_demo.NewRootResolvers(db)),   handler.ComplexityLimit(300) ), ) 

, , . 12. , , , ( , , , , ). resolver.go :

 func NewRootResolvers(db *sql.DB) Config { c := Config{   Resolvers: &Resolver{     db: db,   }, } //  countComplexity := func(childComplexity int, limit *int, offset *int) int {   return *limit * childComplexity } c.Complexity.Query.Videos = countComplexity c.Complexity.Video.Related = countComplexity //   c.Directives.IsAuthenticated = func(ctx context.Context, obj interface{}, next graphql.Resolver) (res interface{}, err error) {   ctxUserID := ctx.Value(UserIDCtxKey)   if ctxUserID != nil {     return next(ctx)   } else {     return nil, errors.UnauthorisedError   } } return c } 

, , .







, , related . , , , , .

рдкрд░рд┐рдгрд╛рдо


, , GitHub . . , , .

рдкреНрд░рд┐рдп рдкрд╛рдардХреЛрдВ! GraphQL , Go?

Source: https://habr.com/ru/post/hi444346/


All Articles