рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕реЗрд╕ рдореЗрдВ рдЬреЗрдВрдЯрд▓ рдПрд░рд░ рд╣реИрдВрдбрд▓рд┐рдВрдЧ

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


рдпрд╣ рд▓реЗрдЦ рдХрдЬрд╝рд╛рди рдореЗрдВ рд╣рд╛рд▓рд┐рдпрд╛ рдЧреЛ рдмреИрдардХ рдХреА рдПрдХ рд░рд┐рдкреЛрд░реНрдЯ рдХрд╛ рдПрдХ рд╡рд┐рд╕реНрддреГрдд рд╕рдВрд╕реНрдХрд░рдг рд╣реИред рдпрджрд┐ рдЖрдк рдЧреЛ рдореЗрдВ рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ рдФрд░ рдЖрдк рдХрдЬрд╝рд╛рди, рдЗрдиреНрдиреЛрдкреЛрд▓рд┐рд╕, рд╕реБрдВрджрд░ рдпреЛрд╢реНрдХрд░-рдУрд▓рд╛ рдпрд╛ рдЖрд╕рдкрд╛рд╕ рдХреЗ рдХрд┐рд╕реА рдЕрдиреНрдп рд╢рд╣рд░ рдореЗрдВ рд░рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рд╕рдореБрджрд╛рдп рдкреГрд╖реНрда рдкрд░ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП: golangkazan.imtqy.com ред


рдмреИрдардХ рдореЗрдВ, рд╣рдорд╛рд░реА рдЯреАрдо рдиреЗ рджреЛ рд░рд┐рдкреЛрд░реНрдЯреЛрдВ рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдХрд┐ рд╣рдо рдЧреЛ рдкрд░ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕реЗрд╕ рдХреИрд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╣реИрдВ - рд╣рдо рдХрд┐рди рд╕рд┐рджреНрдзрд╛рдВрддреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╣рдо рдЕрдкрдиреЗ рдЬреАрд╡рди рдХреЛ рдХреИрд╕реЗ рд╕рд░рд▓ рдмрдирд╛рддреЗ рд╣реИрдВред рдпрд╣ рд▓реЗрдЦ рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреА рд╣рдорд╛рд░реА рдЕрд╡рдзрд╛рд░рдгрд╛ рдкрд░ рдзреНрдпрд╛рди рдХреЗрдВрджреНрд░рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдЕрдм рд╣рдо рдЕрдкрдиреЗ рд╕рднреА рдирдП рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕реЗрдЬ рддрдХ рдмрдврд╝рд╛рддреЗ рд╣реИрдВред


рдорд╛рдЗрдХреНрд░реЛрд╕рд┐рд╕реНрдЯрд╡рд░реНрдХ рд╕рдВрд░рдЪрдирд╛ рд╕рдордЭреМрддреЗ


рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рдирд┐рдпрдореЛрдВ рдХреЛ рдЫреВрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдпрд╣ рддрдп рдХрд░рдиреЗ рдХреЗ рд▓рд╛рдпрдХ рд╣реИ рдХрд┐ рд╣рдо рдбрд┐рдЬрд╛рдЗрди рдФрд░ рдХреЛрдбрд┐рдВрдЧ рдХрд░рддреЗ рд╕рдордп рдХрд┐рди рдкреНрд░рддрд┐рдмрдВрдзреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рддреЗ рд╣реИрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рдмрддрд╛рдиреЗ рд▓рд╛рдпрдХ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рдорд╛рдЗрдХреНрд░реЛрд╕реЗрд╡рд░реНрд╕ рдХрд┐рд╕ рддрд░рд╣ рдХреЗ рджрд┐рдЦрддреЗ рд╣реИрдВред


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


рдЗрд╕ рддрд░рд╣ рд╣рдорд╛рд░рд╛ рд╕реНрддрд░ рджрд┐рдЦрддрд╛ рд╣реИ:


  1. рдбреЛрдореЗрди рд╕реНрддрд░ рдореЗрдВ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдирд┐рдпрдо рд╣реЛрддреЗ рд╣реИрдВ рдЬреЛ рд╡рд┐рд╖рдп рдХреНрд╖реЗрддреНрд░ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╣реЛрддреЗ рд╣реИрдВред
    • рдпрджрд┐ рдХрд╛рд░реНрдп рд╕рд░рд▓ рд╣реИ рддреЛ рдХрднреА-рдХрднреА рд╣рдо рдмрд┐рдирд╛ рдбреЛрдореЗрди рдХреЗ рдХрд░рддреЗ рд╣реИрдВ
    • рдирд┐рдпрдо: рдбреЛрдореЗрди рд╕реНрддрд░ рдкрд░ рдХреЛрдб рдХреЗрд╡рд▓ рдЧреЛ рдХреА рдХреНрд╖рдорддрд╛рдУрдВ, рдорд╛рдирдХ рдЧреЛ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдФрд░ рдЪрдпрдирд┐рдд рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдкрд░ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЧреЛ рднрд╛рд╖рд╛ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ
  2. рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкрд░рдд рдореЗрдВ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдирд┐рдпрдо рд╣реИрдВред
    • рдирд┐рдпрдо: рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реНрддрд░ рдкрд░ рдХреЛрдб рдбреЛрдореЗрди рдкрд░ рдирд┐рд░реНрднрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ
  3. рдЕрд╡рд╕рдВрд░рдЪрдирд╛ рд╕реНрддрд░ рдореЗрдВ рдЕрд╡рд╕рдВрд░рдЪрдирд╛ рдХреЛрдб рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рднрдВрдбрд╛рд░рдг (MySQL, Redis), рдкрд░рд┐рд╡рд╣рди (рдЬреАрдЖрд░рдкреАрд╕реА, рдПрдЪрдЯреАрдЯреАрдкреА), рдмрд╛рд╣рд░реА рд╡рд╛рддрд╛рд╡рд░рдг рдФрд░ рдЕрдиреНрдп рд╕реЗрд╡рд╛рдУрдВ рдХреЗ рд╕рд╛рде рд╕рдВрдкрд░реНрдХ рдХреЗ рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рддрдХрдиреАрдХреЛрдВ рд╕реЗ рдЬреЛрдбрд╝рддрд╛ рд╣реИред
    • рдирд┐рдпрдо: рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреЗ рд╕реНрддрд░ рдкрд░ рдХреЛрдб рдбреЛрдореЗрди рдФрд░ рдРрдк рдкрд░ рдирд┐рд░реНрднрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ
    • рдирд┐рдпрдо: рдкреНрд░рддрд┐ рдкреИрдХреЗрдЬ рдХреЗрд╡рд▓ рдПрдХ рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХреА
  4. рдореБрдЦреНрдп рдкреИрдХреЗрдЬ рд╕рднреА рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдмрдирд╛рддрд╛ рд╣реИ - "рдЖрдЬреАрд╡рди рд╕рд┐рдВрдЧрд▓рдЯрди", рдЙрдиреНрд╣реЗрдВ рдПрдХ рд╕рд╛рде рдЬреЛрдбрд╝рддрд╛ рд╣реИ рдФрд░ рд▓рдВрдмреЗ рд╕рдордп рддрдХ рд░рд╣рдиреЗ рд╡рд╛рд▓реЗ рдХреЛрд░рдЖрдЙрдЯ рдХрд░рддрд╛ рд╣реИ - рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рдкреЛрд░реНрдЯ 8081 рд╕реЗ HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ

рдпрд╣ рд╣реИ рдХрд┐ microservice рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдЯреНрд░реА рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ (рд╡рд╣ рднрд╛рдЧ рдЬрд╣рд╛рдВ Go рдХреЛрдб рд╣реИ):


рдЪрд┐рддреНрд░: рдЧреЙ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдЙрдбрд╝реАрд╕рд╛


рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╕рдВрджрд░реНрдн (рдореЙрдбреНрдпреВрд▓) рдХреЗ рд▓рд┐рдП, рдкреИрдХреЗрдЬ рд╕рдВрд░рдЪрдирд╛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреА рд╣реИ:


  • рдРрдк рдкреИрдХреЗрдЬ рдПрдХ рд╕реЗрд╡рд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдХрд┐рд╕реА рджрд┐рдП рдЧрдП рд╕реНрддрд░ рдкрд░ рд╕рднреА рдХреНрд░рд┐рдпрд╛рдПрдВ рд╕рдВрднрд╡ рд╣реЛрддреА рд╣реИрдВ рдЬреЛ рд╕реЗрд╡рд╛ рд╕рдВрд░рдЪрдирд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдФрд░ func NewService(...) Service рдлрд╝рдВрдХреНрд╢рди func NewService(...) Service
  • рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд╛ рдЕрд▓рдЧрд╛рд╡ рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдкреНрд░рд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдбреЛрдореЗрди рдпрд╛ рдРрдк рдкреИрдХреЗрдЬ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдкреИрдХреЗрдЬ рдореЗрдВ рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреЗ рд╕реНрддрд░ рдкрд░ рджреГрд╢реНрдп рдирд╛рдо "mysql" рдХреЗ рд╕рд╛рде рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ
  • рдкрд░рд┐рд╡рд╣рди рдХреЛрдб infrastructure/transport рдкреИрдХреЗрдЬ рдореЗрдВ рд╕реНрдерд┐рдд рд╣реИ
    • рд╣рдо GRPC рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╕рд░реНрд╡рд░ рд╕реНрдЯрдмреНрд╕ рдкреНрд░реЛрдЯреЛ рдлрд╛рдЗрд▓ (рдпрд╛рдиреА рд╕рд░реНрд╡рд░ рдЗрдВрдЯрд░рдлреЗрд╕, рд░рд┐рд╕реНрдкрд╛рдВрд╕ / рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдФрд░ рд╕рднреА рдХреНрд▓рд╛рдЗрдВрдЯ рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХреЛрдб) рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрддреЗ рд╣реИрдВред

рдпрд╣ рд╕рдм рдЪрд┐рддреНрд░ рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:


рдЪрд┐рддреНрд░: рд╕рд░рдХрд╛рд░ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкреИрдХреЗрдЬ


рд╕рд┐рджреНрдзрд╛рдВрддреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдореЗрдВ рддреНрд░реБрдЯрд┐


рдпрд╣рд╛рдБ рд╕рдм рдХреБрдЫ рд╕рд░рд▓ рд╣реИ:


  1. рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдПрдкреАрдЖрдИ рдореЗрдВ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддреЗ рд╕рдордп рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдФрд░ рдШрдмрд░рд╛рд╣рдЯ рд╣реЛрддреА рд╣реИ - рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рддреНрд░реБрдЯрд┐ рдпрд╛ рдЖрддрдВрдХ рдХреЗрд╡рд▓ рдПрдХ рдЕрдиреБрд░реЛрдз рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП
  2. рд╣рдорд╛рд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рд▓реЙрдЧ рдХреЗрд╡рд▓ рдШрдЯрдирд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИрдВ (рдФрд░ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рдбреАрдмрдЧрд░ рд╣реИ), рдЗрд╕рд▓рд┐рдП, рд▓реЙрдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХреА рдЬрд╛рддреА рд╣реИ, рдФрд░ рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдЬрдм рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдЕрдиреБрд░реЛрдз рд╣реЛрддреЗ рд╣реИрдВ
  3. рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рд▓реЙрдЧ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдкреВрд░реНрдг рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪрд╛ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдИрдПрд▓рдХреЗ рдкрд░ рдЖрдзрд╛рд░рд┐рдд) - рдФрд░ рдорд╛рдЗрдХреНрд░реЛрд╕реЗрд╡рд░ рдЗрд╕рдореЗрдВ рдПрдХ рдирд┐рд╖реНрдХреНрд░рд┐рдп рднреВрдорд┐рдХрд╛ рдирд┐рднрд╛рддрд╛ рд╣реИ, рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП stderr

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


рдореБрд╣рд╛рд╡рд░рд╛ рдкреНрд░рд╣рд░реА рддреНрд░реБрдЯрд┐рдпрд╛рдБ


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


 package app import "errors" var ErrNoCake = errors.New("no cake found") 

рдПрдХ рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдпрд╣рд╛рдВ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЬреЛ рд╣рдорд╛рд░реЗ рд╕рдЬреНрдЬрди рд╕рдордЭреМрддреЗ рд╕реЗ, рд╣рдореЗрдВ рдХрд╣реАрдВ рднреА рдирд╣реАрдВ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рдЖрдк рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдХреА рддрд░рд╣ рдирд╣реАрдВ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдХреБрдЫ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдбреЗрд╡ рдЪреЗрдиреА рд▓рдЧрд╛рддрд╛рд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдмрд╛рдж рд╕реБрдЭрд╛рд╡ рджреЗрддреЗ рд╣реИрдВ :


 package app type Error string func (e Error) Error() string { return string(e) } const ErrNoCake = Error("no cake found") 

рдпрджрд┐ рдЖрдк рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЕрдкрдиреЗ рдХреЙрд░рдкреЛрд░реЗрдЯ рдЧреЛ рднрд╛рд╖рд╛ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ ConstError рдкреНрд░рдХрд╛рд░ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣ рд╕рдХрддреЗ рд╣реИрдВред

рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рд╕рдВрд░рдЪрдирд╛


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


  • рдПрдХреНрд╕рд░рд┐рдпрд░реНрд╕ рдкреИрдХреЗрдЬ, рдЬреЛ рдХрд┐ рдЧреЛ 1.13 рдореЗрдВ рдкреНрд░рдпреЛрдЧ рдХреЗ рддреМрд░ рдкрд░ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛
  • рдбреЗрд╡ рдЪреЗрдиреА рджреНрд╡рд╛рд░рд╛ github.com/pkg/errors рдкреИрдХреЗрдЬ
    • рдкреИрдХреЗрдЬ рдЬрдореЗ рд╣реБрдП рд╣реИ рдФрд░ рд╡рд┐рд╕реНрддрд╛рд░ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдлрд┐рд░ рднреА рдпрд╣ рдЕрдЪреНрдЫрд╛ рд╣реИ

рд╣рдорд╛рд░реА рдЯреАрдо рдЕрднреА рднреА github.com/pkg/errors рдФрд░ errors.WithStack рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреА рд╣реИред errors.WithStack рдлрд╝рдВрдХреНрд╢рди (рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдирд╣реАрдВ рд╣реИ, рд╕реНрдЯреИрдХрдЯреНрд░реЗрд╕ рдХреЛ рдЫреЛрдбрд╝рдХрд░) рдпрд╛ errors.Wrap (рдЬрдм рд╣рдореЗрдВ рдЗрд╕ рддреНрд░реБрдЯрд┐ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рдХрд╣рдирд╛ рд╣реИ)ред рджреЛрдиреЛрдВ рдлрд╝рдВрдХреНрд╢рди рдЗрдирдкреБрдЯ рдореЗрдВ рдПрдХ рддреНрд░реБрдЯрд┐ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдирдИ рддреНрд░реБрдЯрд┐ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕реНрдЯреИрдХрдЯреНрд░реЗрд╕ рдХреЗ рд╕рд╛рдеред рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреА рдкрд░рдд рд╕реЗ рдЙрджрд╛рд╣рд░рдг:


 package mysql import "github.com/pkg/errors" func (r *repository) FindOne(...) { row := r.client.QueryRow(sql, params...) switch err := row.Scan(...) { case sql.ErrNoRows: //     stacktrace return nil, errors.WithStack(app.ErrNoCake) } } 

рд╣рдо рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рддреНрд░реБрдЯрд┐ рдХреЛ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рд▓рдкреЗрдЯрд╛ рдЬрд╛рдПред рдпрджрд┐ рдЖрдк рдирд┐рдпрдореЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдпрд╣ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ:


  • рдХрд┐рд╕реА рднреА рдмреБрдирд┐рдпрд╛рджреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдПрдХ рдмрд╛рд░ рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреЗ рдкреИрдХреЗрдЬ рдореЗрдВ рд▓рдкреЗрдЯрд╛ рдЬрд╛рддрд╛ рд╣реИ
  • рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдирд┐рдпрдореЛрдВ рджреНрд╡рд╛рд░рд╛ рдЙрддреНрдкрдиреНрди рдХреЛрдИ рднреА рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╕реГрдЬрди рдХреЗ рд╕рдордп рд╕реНрдЯреИрдХрдЯреНрд░реЗрд╕ рджреНрд╡рд╛рд░рд╛ рдкреВрд░рдХ рд╣реЛрддреА рд╣реИрдВ

рддреНрд░реБрдЯрд┐ рдХрд╛ рдореВрд▓ рдХрд╛рд░рдг


рд╕рднреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдЙрдореНрдореАрдж рдФрд░ рдЕрдкреНрд░рддреНрдпрд╛рд╢рд┐рдд рд░реВрдк рд╕реЗ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЕрдкреЗрдХреНрд╖рд┐рдд рддреНрд░реБрдЯрд┐ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд░рдЪрдирд╛ рдХреЗ рдкреНрд░рднрд╛рд╡реЛрдВ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред Xerrors рдФрд░ github.com/pkg/errors рдкреИрдХреЗрдЬ рдореЗрдВ рд╡рд╣ рд╕рдм рдХреБрдЫ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдЪрд╛рд╣рд┐рдП: рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ, рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдкреИрдХреЗрдЬ рдореЗрдВ рддреНрд░реБрдЯрд┐рдпрд╛рдБ рд╣реИрдВред рдлрд╝рдВрдХреНрд╢рди рдХреЛ errors.Cause , рдЬреЛ рддреНрд░реБрдЯрд┐ рдХрд╛ рдореВрд▓ рдХрд╛рд░рдг рджреЗрддрд╛ рд╣реИред рд▓реВрдк рдореЗрдВ рдпрд╣ рдлрд╝рдВрдХреНрд╢рди, рдПрдХ рдХреЗ рдмрд╛рдж рдПрдХ, рдкрд╣рд▓реЗ рдХреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рддрд╛ рд╣реИ рдЬрдмрдХрд┐ рдЕрдЧрд▓реА рдирд┐рдХрд╛рд▓реА рдЧрдИ рддреНрд░реБрдЯрд┐ рдХрд╛ Cause() error рд╡рд┐рдзрд┐ рд╣реИред


рдПрдХ рдЙрджрд╛рд╣рд░рдг рдЬрд┐рд╕рдХрд╛ рд╣рдо рдореВрд▓ рдХрд╛рд░рдг рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВ рдФрд░ рд╕реАрдзреЗ рдЗрд╕рдХреА рддреБрд▓рдирд╛ рд╕рдВрддрд░реА рддреНрд░реБрдЯрд┐ рд╕реЗ рдХрд░рддреЗ рд╣реИрдВ:


 func (s *service) SaveCake(...) error { state, err := s.repo.FindOne(...) if errors.Cause(err) == ErrNoCake { err = nil // No cake is OK, create a new one // ... } else if err != nil { // ... } } 

рдбрд┐рдлрд░реЗрдВрд╕ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдореЗрдВ рддреНрд░реБрдЯрд┐


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


рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рд╕рднреА рдХрд╛рд░реНрдп рд▓реЗрди-рджреЗрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрдбрд╝рд╛рдИ рд╕реЗ рд╣реИрдВред рдирд┐рд░реНрднрд░рддрд╛ рдирд┐рдпрдо рдХреЗ рдЕрдиреБрд╕рд╛рд░, рдРрдк рдФрд░ рдбреЛрдореЗрди рдХрд╛ рд╕реНрддрд░ рдмреБрдирд┐рдпрд╛рджреА рдпрд╛ рдПрд╕рдХреНрдпреВрдПрд▓ рддрдХрдиреАрдХ рдкрд░ рдкреНрд░рддреНрдпрдХреНрд╖ рдпрд╛ рдЕрдкреНрд░рддреНрдпрдХреНрд╖ рд░реВрдк рд╕реЗ рдирд┐рд░реНрднрд░ рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рдРрдк рдФрд░ рдбреЛрдореЗрди рдХреЗ рд╕реНрддрд░ рдкрд░ "рд▓реЗрдирджреЗрди" рд╢рдмреНрдж рдирд╣реАрдВ рд╣реИ ред


рд╕рдмрд╕реЗ рд╕рд░рд▓ рд╕рдорд╛рдзрд╛рди рдХреБрдЫ рд╕рд╛рд░ рдХреЗ рд╕рд╛рде "рд▓реЗрдирджреЗрди" рд╢рдмреНрдж рдХреЛ рдмрджрд▓рдирд╛ рд╣реИ; рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдпреВрдирд┐рдЯ рдСрдл рд╡рд░реНрдХ рдкреИрдЯрд░реНрди рдХрд╛ рдЬрдиреНрдо рд╣реЛрддрд╛ рд╣реИред рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ, рдРрдк рдкреИрдХреЗрдЬ рдореЗрдВ рд╕реЗрд╡рд╛ UnitOfWorkFactory рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрд╛рд░рдЦрд╛рдирд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреА рд╣реИ, рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдСрдкрд░реЗрд╢рди рдХреЗ рджреМрд░рд╛рди рдПрдХ UnitOfWork рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рддрд╛ рд╣реИ рдЬреЛ рд▓реЗрдирджреЗрди рдХреЛ рдЫреБрдкрд╛рддрд╛ рд╣реИред UnitOfWork рдСрдмреНрдЬреЗрдХреНрдЯ рдЖрдкрдХреЛ рдПрдХ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред


UnitOfWork рдкрд░ рдЕрдзрд┐рдХ

рдХрд╛рд░реНрдп рдХреА рдЗрдХрд╛рдИ рдХреЗ рдЙрдкрдпреЛрдЧ рдХреЛ рдмреЗрд╣рддрд░ рдврдВрдЧ рд╕реЗ рд╕рдордЭрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрд░реЗрдЦ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:


рдХрд╛рдо рдХреА рдЫрд╡рд┐ рдЬрд╛рдУ рдЗрдХрд╛рдИ


  • рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдПрдХ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдбреЛрдореЗрди рд╕реНрддрд░ рд╕рдореБрдЪреНрдЪрдп) рдХреЗ рдПрдХ рдирд┐рд░рдВрддрд░ рдирд┐рд░рдВрддрд░ рд╕рдВрдЧреНрд░рд╣ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреА рд╣реИ
  • UnitOfWork рд▓реЗрдирджреЗрди рдХреЛ рдЫреБрдкрд╛рддрд╛ рд╣реИ рдФрд░ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рддрд╛ рд╣реИ
  • UnitOfWorkFactory рдмрд╕ рд╕реЗрд╡рд╛ рдХреЛ рд▓реЗрдирджреЗрди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рднреА рдЬрд╛рдиреЗ рдмрд┐рдирд╛ рдирдП рд▓реЗрдирджреЗрди рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред

рдХреНрдпрд╛ рд╣рд░ рдСрдкрд░реЗрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рд▓реЗрди-рджреЗрди рдмрдирд╛рдирд╛ рдЕрддреНрдпрдзрд┐рдХ рдирд╣реАрдВ рд╣реИ, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╢реБрд░реВ рдореЗрдВ рдкрд░рдорд╛рдгреБ рднреА? рдпрд╣ рдЖрдк рдкрд░ рдирд┐рд░реНрднрд░ рд╣реИ; рд╣рдорд╛рд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рд▓реЗрди-рджреЗрди рдмрдирд╛рдиреЗ рд╕реЗ рдмрдЪрд╛рдиреЗ рдХреЗ рдмрдЬрд╛рдп рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдХреА рд╕реНрд╡рддрдВрддреНрд░рддрд╛ рдХреЛ рдмрдирд╛рдП рд░рдЦрдирд╛ рдЕрдзрд┐рдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред


рдХреНрдпрд╛ UnitOfWork рдФрд░ Repository рдХреЛ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдирд╛ рд╕рдВрднрд╡ рд╣реИ? рдпрд╣ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдорд╛рд░рд╛ рдорд╛рдирдирд╛ тАЛтАЛрд╣реИ рдХрд┐ рдпрд╣ рдПрдХрд▓ рдЙрддреНрддрд░рджрд╛рдпрд┐рддреНрд╡ рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрдд рдХрд╛ рдЙрд▓реНрд▓рдВрдШрди рдХрд░рддрд╛ рд╣реИред


рдпрд╣ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ:


 type UnitOfWork interface { Repository() Repository Complete(err *error) } 

UnitOfWork рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкреВрд░реНрдг рд╡рд┐рдзрд┐ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдПрдХ-рдЗрди-рдЖрдЙрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рд▓реЗрддрд╛ рд╣реИ: рддреНрд░реБрдЯрд┐ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реВрдЪрдХред рд╣рд╛рдВ, рдпрд╣ рд╕реВрдЪрдХ рд╣реИ, рдФрд░ рдпрд╣ рдЗрди-рдЖрдЙрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИ - рдХрд┐рд╕реА рднреА рдЕрдиреНрдп рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдХреЙрд▓рд┐рдВрдЧ рд╕рд╛рдЗрдб рдкрд░ рдХреЛрдб рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реЛ рдЬрд╛рдПрдЧрд╛ред


UnitOfWork рдХреЗ рд╕рд╛рде рдЙрджрд╛рд╣рд░рдг рд╕рдВрдЪрд╛рд▓рди:


рд╕рд╛рд╡рдзрд╛рдиреА: рддреНрд░реБрдЯрд┐ рдХреЛ рдирд╛рдо рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдпрджрд┐ рдирд╛рдорд╛рдВрдХрд┐рдд рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп рдХреЗ рдмрдЬрд╛рдп рдЖрдк рд╕реНрдерд╛рдиреАрдп рдЪрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЧрд▓рдд рддрд░реАрдХреЗ рд╕реЗ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЗрд╕реЗ рдбрд┐рдлрд░ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ! рдФрд░ рдПрдХ рднреА рд▓рд┐рдВрдЯрд░ рдЗрд╕рдХрд╛ рдкрддрд╛ рдирд╣реАрдВ рд▓рдЧрд╛рдПрдЧрд╛ - рдЧреЛ-рдЖрд▓реЛрдЪрдХ # 801 рджреЗрдЦреЗрдВ

 func (s *service) CookCake() (err error) { unitOfWork, err := s.unitOfWorkFactory.New() if err != nil { return err } defer unitOfWork.Complete(&err) repo := unitOfWork.Repository() } // ...   

рддреЛ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдХрд╛ рдПрд╣рд╕рд╛рд╕ рд╣реИ рд▓реЗрди-рджреЗрди UnitOfWork:


 func (u *unitOfWork) Complete(err *error) { if *err == nil { //     -  commit txErr := u.tx.Commit() *err = errors.Wrap(txErr, "cannot complete transaction") } else { //    -  rollback txErr := return u.tx.Rollback() //  rollback   ,    *err = mergeErrors(*err, errors.Wrap(txErr, "cannot rollback transaction")) } } 

mergeErrors рдлрд╝рдВрдХреНрд╢рди рджреЛ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдорд░реНрдЬ рдХрд░рддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдПрдХ рдпрд╛ рджреЛрдиреЛрдВ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдмрдЬрд╛рдп рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЗ рдмрд┐рдирд╛ рд╢реВрдиреНрдп рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИред рдЙрд╕реА рд╕рдордп, рд╣рдо рдорд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рджреЛрдиреЛрдВ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЪрд░рдгреЛрдВ рдореЗрдВ рдПрдХ рдСрдкрд░реЗрд╢рди рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рд╣реБрдИрдВ, рдФрд░ рдкрд╣рд▓реА рддреНрд░реБрдЯрд┐ рдЕрдзрд┐рдХ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ - рдЗрд╕рд▓рд┐рдП, рдЬрдм рджреЛрдиреЛрдВ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╢реВрдиреНрдп рдирд╣реАрдВ рд╣реЛрддреА рд╣реИрдВ, рддреЛ рд╣рдо рдкрд╣рд▓реЗ рдХреЛ рдмрдЪрд╛рддреЗ рд╣реИрдВ, рдФрд░ рджреВрд╕рд░реА рддреНрд░реБрдЯрд┐ рд╕реЗ рд╣рдо рдХреЗрд╡рд▓ рд╕рдВрджреЗрд╢ рдХреЛ рдмрдЪрд╛рддреЗ рд╣реИрдВ:


 package errors func mergeErrors(err error, nextErr error) error { if err == nil { err = nextErr } else if nextErr != nil { err = errors.Wrap(err, nextErr.Error()) } return err } 

рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЖрдкрдХреЛ Go рдХреЗ рд▓рд┐рдП рдЕрдкрдиреА рдХреЙрд░реНрдкреЛрд░реЗрдЯ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдореЗрдВ mergeErrors рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЬреЛрдбрд╝рдирд╛ рдЪрд╛рд╣рд┐рдПред

рд▓реЙрдЧрд┐рдВрдЧ рд╕рдмрд╕рд┐рд╕реНрдЯрдо


рдЕрдиреБрдЪреНрдЫреЗрдж рдЪреЗрдХрд▓рд┐рд╕реНрдЯ: рдареЗрд╕ рдореЗрдВ рд╕рд▓рд╛рд╣ рджреЗрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЖрдкрдХреЛ рдХреНрдпрд╛ рдХрд░рдирд╛ рдерд╛ :


  • рд▓реЙрдЧ stderr рдореЗрдВ рд▓рд┐рдЦреЗ рдЧрдП рд╣реИрдВ
  • рд▓реЙрдЧ JSON рдореЗрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдкреНрд░рддрд┐ рдкрдВрдХреНрддрд┐ рдПрдХ JSON рдСрдмреНрдЬреЗрдХреНрдЯ
  • рдЦреЗрддреЛрдВ рдХрд╛ рдПрдХ рдорд╛рдирдХ рд╕реЗрдЯ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:
    • рдЯрд╛рдЗрдорд╕реНрдЯреИрдореНрдк - рдорд┐рд▓реАрд╕реЗрдХрдВрдб рдореЗрдВ рдШрдЯрдирд╛ рдХрд╛ рд╕рдордп, рдЕрдзрд┐рдорд╛рдирддрдГ рдЖрд░рдПрдлрд╕реА 3339 рдкреНрд░рд╛рд░реВрдк рдореЗрдВ (рдЙрджрд╛рд╣рд░рдг: "1985-04-12T23: 20: 50.52Z")
    • рд╕реНрддрд░ - рдорд╣рддреНрд╡ рд╕реНрддрд░, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, "рдЬрд╛рдирдХрд╛рд░реА" рдпрд╛ "рддреНрд░реБрдЯрд┐"
    • app_name - рдЖрд╡реЗрджрди рдирд╛рдо
    • рдФрд░ рдЕрдиреНрдп рдХреНрд╖реЗрддреНрд░

рд╣рдо рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢реЛрдВ рдореЗрдВ рджреЛ рдФрд░ рдлрд╝реАрд▓реНрдб рдЬреЛрдбрд╝рдирд╛ рдкрд╕рдВрдж рдХрд░рддреЗ рд╣реИрдВ: "error" рдФрд░ "stacktrace" ред


рдЧреЛрд▓рдВрдЧ рднрд╛рд╖рд╛ рдХреЗ рд▓рд┐рдП рдХрдИ рдЧреБрдгрд╡рддреНрддрд╛ рд╡рд╛рд▓реЗ рд▓реЙрдЧрд┐рдВрдЧ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рд░реВрдкреЗрдВрд╕ / рд▓реЙрдЧрд░рд╕ , рдЬрд┐рд╕рдХрд╛ рд╣рдо рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рд╣рдо рд╕реАрдзреЗ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЕрдкрдиреЗ log рдкреИрдХреЗрдЬ рдореЗрдВ рд╣рдо рдПрдХ рд▓реЙрдЧрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд▓рд┐рдП рд╡реНрдпрд╛рдкрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдХрдо рдХрд░рддреЗ рд╣реИрдВ:


 package log type Logger interface { WithField(string, interface{}) Logger WithFields(Fields) Logger Debug(...interface{}) Info(...interface{}) Error(error, ...interface{}) } 

рдпрджрд┐ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рд▓реЙрдЧ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рддреЛ рдЙрд╕реЗ рд▓реЙрдЧрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрд╛рд╣рд░ рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдпрд╣ рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреЗ рд╕реНрддрд░ рдкрд░ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рди рдХрд┐ рдРрдк рдпрд╛ рдбреЛрдореЗрди рдкрд░ред рд▓рдХрдбрд╝рд╣рд╛рд░рд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд╣реИ:


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

рдЗрд╕ рддрд░рд╣ рдХреА рд╕рдЦреНрддреА рд╕реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдорд░ рдХреЛ рд╕рд╣реА рджрд┐рд╢рд╛ рдореЗрдВ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдорд┐рд▓рддреА рд╣реИ: рдпрджрд┐ рдХреЛрдИ рд╡реНрдпрдХреНрддрд┐ рд▓реЙрдЧрд┐рдВрдЧ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рддреЛ рдЙрд╕реЗ рдЕрдкрдиреЗ рд╕рдВрдЧреНрд░рд╣ рдФрд░ рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдкреВрд░реЗ рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬреЛ рдХрд┐ рдХреЗрд╡рд▓ рдорд╛рдЗрдХреНрд░реЛ рд╕рд░реНрд╡рд┐рд╕ рдореЗрдВ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ (рдФрд░ рдЖрдорддреМрд░ рдкрд░ рдХрд┐рдмрд╛рдирд╛ рдореЗрдВ рдХрд╣реАрдВ рдФрд░ рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ) Zabbix)ред


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


 package log type MainLogger interface { Logger FatalError(error, ...interface{}) } 

Jsonlog рдкреИрдХреЗрдЬ


рд▓рдХрдбрд╝рд╣рд╛рд░рд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣рдорд╛рд░реЗ jsonlog рдкреИрдХреЗрдЬ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рд▓реЙрдЧрд░рд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЛ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХреЛ рдЕрдореВрд░реНрдд рдХрд░рддрд╛ рд╣реИред рдпреЛрдЬрдирд╛рдПрдВ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреА рд╣реИрдВ:


рдЫрд╡рд┐ рд▓рдХрдбрд╝рд╛рд╣рд╛рд░рд╛ рдкреИрдХреЗрдЬ


рдПрдХ рдорд╛рд▓рд┐рдХрд╛рдирд╛ рдкреИрдХреЗрдЬ рдЖрдкрдХреЛ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕ ( log.Logger рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рджреНрд╡рд╛рд░рд╛ рд╡реНрдпрдХреНрдд), рд▓реЙрдЧрд░рд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреА рдХреНрд╖рдорддрд╛рдУрдВ, рдФрд░ рдЖрдкрдХреЗ рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреА рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рд╕реЗ рдЬреБрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред


рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо ELK (Elastic Search, Logstash, Kibana) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЗрд╕рд▓рд┐рдП jsonlog рдкреИрдХреЗрдЬ рдореЗрдВ рд╣рдо:


  • logrus.JSONFormatter рд╕реНрд╡рд░реВрдк рдХреЗ рд▓рд┐рдП logrus.JSONFormatter рд╕реЗрдЯ рдХрд░реЗрдВ
    • рдЙрд╕реА рд╕рдордп, рд╣рдо рдлрд╝реАрд▓реНрдб рдореИрдк рд╡рд┐рдХрд▓реНрдк рдЪреБрдирддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рд╣рдо "time" рдлрд╝реАрд▓реНрдб рдХреЛ "@timestamp" , рдФрд░ "msg" рдлрд╝реАрд▓реНрдб рдХреЛ "message"
  • рд▓реЙрдЧ рд╕реНрддрд░ рдХрд╛ рдЪрдпрди рдХрд░реЗрдВ
  • Error(error, ...interface{}) рд╡рд┐рдзрд┐ рдореЗрдВ рдкрд╛рд░рд┐рдд Error(error, ...interface{}) рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рд╕реНрдЯреИрдХрдЯреНрд░реЗрд╕ рдирд┐рдХрд╛рд▓рдиреЗ рд╡рд╛рд▓рд╛ рд╣реБрдХ рдЬреЛрдбрд╝реЗрдВ

рдореБрдЦреНрдп рдХрд╛рд░реНрдп рдореЗрдВ рдорд╛рдЗрдХреНрд░реЛрд╕реЗрд╕реНрдЯрд░ рдиреЗ рд▓рдХрдбрд╝рд╣рд╛рд░реЗ рдХреЛ рдЖрд░рдВрднреАрдХреГрдд рдХрд┐рдпрд╛ рд╣реИ:


 func initLogger(config Config) (log.MainLogger, error) { logLevel, err := jsonlog.ParseLevel(config.LogLevel) if err != nil { return nil, errors.Wrap(err, "failed to parse log level") } return jsonlog.NewLogger(&jsonlog.Config{ Level: logLevel, AppName: "cookingservice" }), nil } 

рдорд┐рдбрд┐рд▓рд╡реЗрдпрд░ рдХреЗ рд╕рд╛рде рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдФрд░ рд▓реЙрдЧрд┐рдВрдЧ рдореЗрдВ рддреНрд░реБрдЯрд┐


рд╣рдо рдЧреЛ рдкрд░ рдЕрдкрдиреЗ рдорд╛рдЗрдХреНрд░реЛрд╕рд░реНрд╡рд┐рд╕реЗрдЬ рдореЗрдВ рдЬреАрдЖрд░рдкреАрд╕реА рдкрд░ рд╕реНрд╡рд┐рдЪ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рднрд▓реЗ рд╣реА рдЖрдк HTTP API рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реЛрдВ, рд▓реЗрдХрд┐рди рд╕рд╛рдорд╛рдиреНрдп рд╕рд┐рджреНрдзрд╛рдВрдд рдЖрдкрдХреЗ рд▓рд┐рдП рд╣реИрдВред


рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЯреНрд░рд╛рдВрд╕рдкреЛрд░реНрдЯреЗрд╢рди рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдкреИрдХреЗрдЬ рдореЗрдВ infrastructure рд▓реЗрд╡рд▓ рдкрд░ рдПрд░рд░ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдФрд░ рд▓реЙрдЧрд┐рдВрдЧ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╡рд╣ рд╣реИ рдЬреЛ рдЯреНрд░рд╛рдВрд╕рдкреЛрд░реНрдЯ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдирд┐рдпрдореЛрдВ рдФрд░ app.Service рдЬреНрдЮрд╛рди рдХреЛ app.Service рд╣реИред app.Service рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ app.Service ред рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ рдкреИрдХреЗрдЬ рд╕рдВрдмрдВрдз рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ:


рдЬреАрдЖрд░рдкреА рдкреИрдХреЗрдЬ рдкреИрдХреЗрдЬ


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


рдорд┐рдбрд▓рд╡реЗрдпрд░ рдХреЛ рдХрд╣рд╛рдВ рдЬреЛрдбрд╝реЗрдВ? рдХрд┐рддрдиреЗ рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП?


рдорд┐рдбрд▓рд╡реЗрдпрд░ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ, рдЖрдк рдЪреБрдирддреЗ рд╣реИрдВ:


  • рдЖрдк app.Service рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд╕рдЬрд╛рдиреЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдо рдРрд╕рд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрд╢рдВрд╕рд╛ рдирд╣реАрдВ рдХрд░рддреЗ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдХреНрд▓рд╛рдЗрдВрдЯ рд▓реЗрдпрд░ рдЬреИрд╕реЗ рдЯреНрд░рд╛рдВрд╕рдкреЛрд░реНрдЯ рд▓реЗрдпрд░ рдХреА рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдирд╣реАрдВ рд╣реЛрддреА рд╣реИ
  • рдЬреАрдЖрд░рдкреАрд╕реА рдХреЗ рд╕рд╛рде рдЖрдк рд╕рднреА рдЕрдиреБрд░реЛрдзреЛрдВ рдкрд░ рдПрдХ рд╣реИрдВрдбрд▓рд░ рд▓рдЯрдХрд╛ рд╕рдХрддреЗ рд╣реИрдВ (рдЕрдзрд┐рдХ рд╕рдЯреАрдХ, рджреЛ - рдПрдХрд╛рддреНрдордХ рдФрд░ рднрд╛рдк), рд▓реЗрдХрд┐рди рдлрд┐рд░ рд╕рднреА рдПрдкреАрдЖрдИ рддрд░реАрдХреЛрдВ рдХреЛ рдПрдХ рд╣реА рд╢реИрд▓реА рдореЗрдВ рдПрдХ рд╣реА рдлрд╝реАрд▓реНрдб рдХреЗ рд╕рд╛рде рд▓реЙрдЧ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
  • рдЬреАрдЖрд░рдкреАрд╕реА рдХреЗ рд╕рд╛рде, рдХреЛрдб рдЬрдирд░реЗрдЯрд░ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдПрдХ рд╕рд░реНрд╡рд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╣рдо app.Service рдХрд╣рддреЗ рд╣реИрдВред app.Service рдкрджреНрдзрддрд┐ - рд╣рдо рдЗрд╕ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд╕рдЬрд╛рддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдореЗрдВ рдкрд░рд┐рд╡рд╣рди-рд╕реНрддрд░ рдХреА рдЬрд╛рдирдХрд╛рд░реА рдФрд░ рд╡рд┐рднрд┐рдиреНрди рддрд░реАрдХреЛрдВ рд╕реЗ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдПрдкреАрдЖрдИ рддрд░реАрдХреЛрдВ рдХреЛ рд▓реЙрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реЛрддреА рд╣реИред

рдпреЛрдЬрдирд╛рдПрдВ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддреА рд╣реИрдВ:


рдЫрд╡рд┐ рдЬреАрдЖрд░рдкреА рдорд┐рдбрд┐рд▓рд╡реЗрдпрд░ рдкреИрдХреЗрдЬ рдПрдЧреНрд░реА


рдЖрдк рдПрд░рд░ рд╣реИрдВрдбрд▓рд┐рдВрдЧ (рдФрд░ рдкреИрдирд┐рдХ) рдХреЗ рд▓рд┐рдП рдФрд░ рд▓реЙрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдк рд╕рдм рдХреБрдЫ рдПрдХ рдореЗрдВ рдкрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗ рдЬрд┐рд╕рдореЗрдВ рд╕рдм рдХреБрдЫ рдПрдХ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдореЗрдВ рдкрд╛рд░ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдЗрд╕ рддрд░рд╣ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:


 func NewMiddleware(next api.BackendService, logger log.Logger) api.BackendService { server := &errorHandlingMiddleware{ next: next, logger: logger, } return server } 

рд╣рдо рдПрдХ api.BackendService рд░реВрдк рдореЗрдВ api.BackendService рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдПрдХ api.BackendService рд░реВрдк рдореЗрдВ api.BackendService рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реБрдП api.BackendService ред


Middleware рдореЗрдВ рдПрдХ рдордирдорд╛рдирд╛ рдПрдкреАрдЖрдИ рд╡рд┐рдзрд┐ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд▓рд╛рдЧреВ рдХреА рдЧрдИ рд╣реИ:


 func (m *errorHandlingMiddleware) ListCakes( ctx context.Context, req *api.ListCakesRequest) (*api.ListCakesResponse, error) { start := time.Now() res, err := m.next.ListCakes(ctx, req) m.logCall(start, err, "ListCakes", log.Fields{ "cookIDs": req.CookIDs, }) return res, translateError(err) } 

рдпрд╣рд╛рдБ рд╣рдо рддреАрди рдХрд╛рд░реНрдп рдХрд░рддреЗ рд╣реИрдВ:


  1. рд╕рдЬреЗ рд╣реБрдП рдСрдмреНрдЬреЗрдХреНрдЯ рдХреА ListCakes рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВ
  2. рд╣рдо logCall рд╡рд┐рдзрд┐ рдХреЛ рдХрд╣рддреЗ рд╣реИрдВ, рдЗрд╕рдореЗрдВ рд╕рднреА рдорд╣рддреНрд╡рдкреВрд░реНрдг рдЬрд╛рдирдХрд╛рд░реА рдЧреБрдЬрд░рддреА рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдЪрдпрдирд┐рдд рдлрд╝реАрд▓реНрдб рд╢рд╛рдорд┐рд▓ рд╣реИрдВ рдЬреЛ рд▓реЙрдЧ рдореЗрдВ рдЖрддреЗ рд╣реИрдВ
  3. рдЕрдВрдд рдореЗрдВ, рд╣рдо рдЯреНрд░рд╛рдВрд╕рд▓реЗрд░реНрд░ рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ рддреНрд░реБрдЯрд┐ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВред

рддреНрд░реБрдЯрд┐ рдЕрдиреБрд╡рд╛рдж рдкрд░ рдмрд╛рдж рдореЗрдВ рдЪрд░реНрдЪрд╛ рдХреА рдЬрд╛рдПрдЧреАред рдФрд░ logCall рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдмрд╕ рд╕рд╣реА рд▓реЙрдЧрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╡рд┐рдзрд┐ рдХрд╣рддреЗ рд╣реИрдВ:


 func (m *errorHandlingMiddleware) logCall(start time.Time, err error, method string, fields log.Fields) { fields["duration"] = fmt.Sprintf("%v", time.Since(start)) fields["method"] = method logger := m.logger.WithFields(fields) if err != nil { logger.Error(err, "call failed") } else { logger.Info("call finished") } } 

рдЕрдиреБрд╡рд╛рдж рдореЗрдВ рддреНрд░реБрдЯрд┐


рд╣рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХрд╛ рдореВрд▓ рдХрд╛рд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЗрд╕реЗ рдПрдХ рддреНрд░реБрдЯрд┐ рдореЗрдВ рдмрджрд▓рдирд╛ рдЪрд╛рд╣рд┐рдП рдЬреЛ рдкрд░рд┐рд╡рд╣рди рд╕реНрддрд░ рдкрд░ рд╕рдордЭ рдореЗрдВ рдЖрддрд╛ рд╣реИ рдФрд░ рдЖрдкрдХреА рд╕реЗрд╡рд╛ рдХреЗ рдПрдкреАрдЖрдИ рдореЗрдВ рдкреНрд░рд▓реЗрдЦрд┐рдд рд╣реИред


GRPC рдореЗрдВ, рдпрд╣ рд╕рд░рд▓ рд╣реИ - рд╕реНрдЯреЗрдЯрд╕ рдХреЛрдб рдХреЗ рд╕рд╛рде рдПрдХ рдПрд░рд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП status.Errorf рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред status.Errorf рдлрдВрдХреНрд╢рдиред рдпрджрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ HTTP API (REST API) рд╣реИ, рддреЛ рдЖрдк рдЕрдкрдиреА рд╕реНрд╡рдпрдВ рдХреА рдкреНрд░рдХрд╛рд░ рдХреА рддреНрд░реБрдЯрд┐ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдРрдк рдФрд░ рдбреЛрдореЗрди рд╕реНрддрд░реЛрдВ рдХреЛ рдкрддрд╛ рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред


рдкрд╣рд▓реЗ рд╕рдиреНрдирд┐рдХрдЯрди рдореЗрдВ, рддреНрд░реБрдЯрд┐ рдЕрдиреБрд╡рд╛рдж рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 // ! ! -   err  status.Error func translateError(err error) error { switch errors.Cause(err) { case app.ErrNoCake: err = status.Errorf(codes.NotFound, err.Error()) default: err = status.Errorf(codes.Internal, err.Error()) } return err } 

рдЗрдирдкреБрдЯ рддрд░реНрдХреЛрдВ рдХреЛ рдорд╛рдиреНрдп рдХрд░рддреЗ рд╕рдордп, рд╕рдЬрд╛рдпрд╛ рдЧрдпрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ status.Status рдХреА рдПрдХ рддреНрд░реБрдЯрд┐ рд▓реМрдЯрд╛ рд╕рдХрддрд╛ рд╣реИред рд╕реНрдЯреЗрдЯрд╕ рдХреЛрдб рдХреЗ рд╕рд╛рде status.Status рдкреНрд░рдХрд╛рд░, рдФрд░ рдЯреНрд░рд╛рдВрд╕рд▓реЗрд░ рдХрд╛ рдкрд╣рд▓рд╛ рд╕рдВрд╕реНрдХрд░рдг рдЗрд╕ рд╕реНрдЯреЗрдЯрд╕ рдХреЛрдб рдХреЛ рдЦреЛ рджреЗрдЧрд╛ред


рдЖрдЗрдП рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкреНрд░рдХрд╛рд░ (рд▓рдВрдмреЗ рд╕рдордп рддрдХ рд▓рд╛рдЗрд╡ рдЯрд╛рдЗрдкрд┐рдВрдЧ) рдкрд░ рдХрд╛рд╕реНрдЯрд┐рдВрдЧ рдХрд░рдХреЗ рдПрдХ рдмреЗрд╣рддрд░ рд╕рдВрд╕реНрдХрд░рдг рдмрдирд╛рдПрдВ:


 type statusError interface { GRPCStatus() *status.Status } func isGrpcStatusError(er error) bool { _, ok := err.(statusError) return ok } func translateError(err error) error { if isGrpcStatusError(err) { return err } switch errors.Cause(err) { case app.ErrNoCake: err = status.Errorf(codes.NotFound, err.Error()) default: err = status.Errorf(codes.Internal, err.Error()) } return err } 

translateError рдлрд╝рдВрдХреНрд╢рди рдЖрдкрдХреЗ рдорд╛рдЗрдХреНрд░реЛрд╕ рд╕рд░реНрд╡рд┐рд╕ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╕рдВрджрд░реНрдн (рд╕реНрд╡рддрдВрддреНрд░ рдореЙрдбреНрдпреВрд▓) рдХреЗ рд▓рд┐рдП рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдЯреНрд░рд╛рдВрд╕рдкреЛрд░реНрдЯ-рд╕реНрддрд░реАрдп рддреНрд░реБрдЯрд┐рдпреЛрдВ рдореЗрдВ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдХрд░рддрд╛ рд╣реИред


рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рджреЗрдирд╛


рд╣рдо рдЖрдкрдХреЛ рддреНрд░реБрдЯрд┐рдпреЛрдВ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдФрд░ рд▓реЙрдЧ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рдирд┐рдпрдо рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рдЙрдирдХрд╛ рдкрд╛рд▓рди рдХрд░рдирд╛ рдпрд╛ рди рдХрд░рдирд╛ рдЖрдкрдХреЗ рдКрдкрд░ рд╣реИред


  1. рдХреНрд▓реАрди рдЖрд░реНрдХрд┐рдЯреЗрдХреНрдЪрд░ рдХреЗ рд╕рд┐рджреНрдзрд╛рдВрддреЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░реЗрдВ, рдкреНрд░рддреНрдпрдХреНрд╖ рдпрд╛ рдЕрдкреНрд░рддреНрдпрдХреНрд╖ рд░реВрдк рд╕реЗ рдирд┐рд░реНрднрд░рддрд╛ рдХреЗ рдирд┐рдпрдо рдХреЛ рди рддреЛрдбрд╝реЗрдВред рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рддрд░реНрдХ рдХреЗрд╡рд▓ рдПрдХ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдкрд░ рдирд┐рд░реНрднрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рди рдХрд┐ рдмрд╛рд╣рд░реА рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХрд┐рдпреЛрдВ рдкрд░ред
  2. рдПрдХ рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ рдЬреЛ рддреНрд░реБрдЯрд┐ рд░рдЪрдирд╛ рдФрд░ рд╕реНрдЯреИрдХрдЯреНрд░реЗрд╕ рдирд┐рд░реНрдорд╛рдг рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, "github.com/pkg/errors" рдпрд╛ xerrors рдкреИрдХреЗрдЬ, рдЬреЛ рдЬрд▓реНрдж рд╣реА рдЧреЛ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реЛрдЧрд╛ред
  3. рдорд╛рдЗрдХреНрд░реЛ-рд╕рд░реНрд╡рд┐рд╕ рдореЗрдВ рдерд░реНрдб-рдкрд╛рд░реНрдЯреА рд▓реЙрдЧрд┐рдВрдЧ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рди рдХрд░реЗрдВ - рд▓реЙрдЧ рдФрд░ рдЬреЙрдиреНрд╕рд▓реЙрдЧ рдкреИрдХреЗрдЬ рдХреЗ рд╕рд╛рде рдЕрдкрдиреА рдЦреБрдж рдХреА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдмрдирд╛рдПрдВ, рдЬреЛ рд▓реЙрдЧрд┐рдВрдЧ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╡рд┐рд╡рд░рдг рдХреЛ рдЫрд┐рдкрд╛рдПрдЧрд╛
  4. рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдФрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рдмреБрдирд┐рдпрд╛рджреА рдврд╛рдВрдЪреЗ рдХреЗ рд╕реНрддрд░ рдХреА рдкрд░рд┐рд╡рд╣рди рджрд┐рд╢рд╛ рдкрд░ рд▓реЙрдЧ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдорд┐рдбрд┐рд▓рд╡реЗрдпрд░ рдкреИрдЯрд░реНрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ

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

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


All Articles