рд╢реБрд░реБрдЖрддреА рдХреЗ рд▓рд┐рдП рднрд╛рд╖рд╛ рдЬрд╛рдУ

рдзрд╛рдиреАрдореВрд╖

рдЗрд╕ рд▓реЗрдЦ рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рдЙрди рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдЧреЛ (рдЧреЛрд▓рдВрдЧ) рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рднрд╛рд╖рд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░рдирд╛ рд╣реИ рдЬреЛ рдЗрд╕ рднрд╛рд╖рд╛ рдХреА рдУрд░ рджреЗрдЦрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрднреА рддрдХ рдЗрд╕рдХрд╛ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИред рдХрд╣рд╛рдиреА рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЙрджрд╛рд╣рд░рдг рдкрд░ рдЖрдпреЛрдЬрд┐рдд рдХреА рдЬрд╛рдПрдЧреА, рдЬреЛ рдПрдХ RESTful API рд╡реЗрдм рд╕реЗрд╡рд╛ рд╣реИред

рдореЗрд░рд╛ рдХрд╛рдо рдПрдХ рдореЛрдмрд╛рдЗрд▓ рд╕реЗрд╡рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдмреИрдХрдПрдВрдб рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рдерд╛ред рд╕реЗрд╡рд╛ рдХрд╛ рд╕рд╛рд░ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИред рдПрдХ рдореЛрдмрд╛рдЗрд▓ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЬреЛ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд╛рди рдХреЗ рдкрд╛рд╕ рд╕реНрдерд┐рдд рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рдХреЗ рдкрджреЛрдВ рдХреЛ рджрд┐рдЦрд╛рддрд╛ рд╣реИред рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреЛрд╕реНрдЯ рдкрд░ рдЯрд┐рдкреНрдкрдгреА рдкреЛрд╕реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдмрджрд▓реЗ рдореЗрдВ рдЯрд┐рдкреНрдкрдгреА рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред рдпрд╣ рдПрдХ рддрд░рд╣ рдХрд╛ рдЬрд┐рдпреЛ-рдлреЛрд░рдо рдирд┐рдХрд▓рд╛ред

рдореИрдВ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдХрд┐рд╕реА рднреА рдЧрдВрднреАрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдЧреЛ рднрд╛рд╖рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред рдкрд╕рдВрдж рд╕реНрдкрд╖реНрдЯ рдереА, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рднрд╛рд╖рд╛ рдРрд╕реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рд╕рдмрд╕реЗ рдЙрдкрдпреБрдХреНрдд рд╣реИред

рдЧреЛ рднрд╛рд╖рд╛ рдХреЗ рдореБрдЦреНрдп рд▓рд╛рдн:



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

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

рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреА рд╕рдВрд░рдЪрдирд╛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдереА:

/project/ /conf/ errors.go settings.go /controllers/ posts.go users.go /models/ posts.go users.go /utils/ helpers.go loctalk.go 


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

рдХреЙрдиреНрдл рдкреИрдХреЗрдЬ рдореЗрдВ рд╕реНрдерд┐рд░рд╛рдВрдХ рдФрд░ рд╕рд╛рдЗрдЯ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╣реИрдВред

 package conf import ( "os" ) const ( SITE_NAME string = "LocTalk" DEFAULT_LIMIT int = 10 MAX_LIMIT int = 1000 MAX_POST_CHARS int = 1000 ) func init() { mode := os.Getenv("MARTINI_ENV") switch mode { case "production": SiteUrl = "http://loctalk.net" AbsolutePath = "/path/to/project/" default: SiteUrl = "http://127.0.0.1" AbsolutePath = "/path/to/project/" } } 


рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЗрд╕ рдкрд░ рдЯрд┐рдкреНрдкрдгреА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рдирд╣реАрдВ рд╣реИред рдЗрдирд┐рдЯ () рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдореБрдЦреНрдп рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдкреНрд░рддреНрдпреЗрдХ рдкреИрдХреЗрдЬ рдореЗрдВ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ ()ред рд╡рд┐рднрд┐рдиреНрди рдлрд╝рд╛рдЗрд▓реЛрдВ рдореЗрдВ рдХрдИ рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВред

рдореБрдЦреНрдп рдкреИрдХреЗрдЬред

 package main import ( "github.com/go-martini/martini" "net/http" "loctalk/conf" "loctalk/controllers" "loctalk/models" "loctalk/utils" ) func main() { m := martini.Classic() m.Use(func(w http.ResponseWriter) { w.Header().Set("Content-Type", "application/json; charset=utf-8") }) m.Map(new(utils.MarshUnmarsh)) Auth := func(mu *utils.MarshUnmarsh, req *http.Request, rw http.ResponseWriter) { reqUserId := req.Header.Get("X-Auth-User") reqToken := req.Header.Get("X-Auth-Token") if !models.CheckToken(reqUserId, reqToken) { rw.WriteHeader(http.StatusUnauthorized) rw.Write(mu.Marshal(conf.ErrUserAccessDenied)) } } // ROUTES m.Get("/", controllers.Home) // users m.Get("/api/v1/users", controllers.GetUsers) m.Get("/api/v1/users/:id", controllers.GetUserById) m.Post("/api/v1/users", controllers.CreateUser) // тАж // posts m.Get("/api/v1/posts", controllers.GetRootPosts) m.Get("/api/v1/posts/:id", controllers.GetPostById) m.Post("/api/v1/posts", Auth, controllers.CreatePost) // ... m.Run() } 


рдмрд╣реБрдд рдКрдкрд░, рдкреИрдХреЗрдЬ рдирд╛рдо рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЖрдпрд╛рддрд┐рдд рдкреИрдХреЗрдЬреЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рд╣реИред рд╣рдо рдорд╛рд░реНрдЯрд┐рдиреА рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдпрд╣ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЬрд▓реНрджреА рдФрд░ рдЖрд╕рд╛рдиреА рд╕реЗ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣рд▓реНрдХреА рдкрд░рдд рдЬреЛрдбрд╝рддрд╛ рд╣реИред рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдпрд╣ рдкреИрдХреЗрдЬ рдХреИрд╕реЗ рдЖрдпрд╛рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЖрдкрдХреЛ рдЙрд╕ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЗ рд▓рд┐рдП рдкрде рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ рдЬрд╣рд╛рдБ рд╕реЗ рдЗрд╕реЗ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдФрд░ рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рдХрдВрд╕реЛрд▓ рдореЗрдВ, рдЯрд╛рдЗрдк рдХрд░реЗрдВ рдХрдорд╛рдВрдб рдЬрд╛рдУ github.com/go-martini/martini

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

рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ рдЪрд░ m рдореЗрдВ рдЯрд╛рдЗрдк * ClassicMartini рд╣реИ, рдпрд╣ рдареАрдХ рд╡реИрд╕рд╛ рд╣реА рд╣реИ рдЬреИрд╕реЗ рдХрд┐ martini.Classic () рд░рд┐рдЯрд░реНрдиред * рдХрд╛ рдорддрд▓рдм рд╣реИ рдПрдХ рдкреЙрдЗрдВрдЯрд░, рдпрд╛рдиреА, рдорд╛рди рд╕реНрд╡рдпрдВ рд╕рдВрдЪрд░рд┐рдд рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдХреЗрд╡рд▓ рдПрдХ рдкреЙрдЗрдВрдЯрд░ рд╣реЛрддрд╛ рд╣реИред M.Use () рд╡рд┐рдзрд┐ рдореЗрдВ, рд╣рдо рдПрдХ рд╣реИрдВрдбрд▓рд░ рдлрд╝рдВрдХреНрд╢рди рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рдорд┐рдбрд▓рд╡реЗрдпрд░ рдорд╛рд░реНрдЯрд┐рдиреА рдХреЛ рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдкрд░ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдп рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдордЧреНрд░реА-рдкреНрд░рдХрд╛рд░ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред M.Map () рд╡рд┐рдзрд┐ рдЖрдкрдХреЛ рд╣рдорд╛рд░реА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдмрд╛рдВрдзрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ рдФрд░ рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ (рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди рддрдВрддреНрд░) рдирд┐рдпрдВрддреНрд░рдХ рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдореИрдВрдиреЗ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдХреЛ json рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдПрдиреНрдХреЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╡рд░рдг рдмрдирд╛рдпрд╛ред

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

Conf рдкреИрдХреЗрдЬ рдХреА рддреНрд░реБрдЯрд┐рдпреЛрдВ.go рдлрд╝рд╛рдЗрд▓ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред

 package conf import ( "fmt" "net/http" ) type ApiError struct { Code int `json:"errorCode"` HttpCode int `json:"-"` Message string `json:"errorMsg"` Info string `json:"errorInfo"` } func (e *ApiError) Error() string { return e.Message } func NewApiError(err error) *ApiError { return &ApiError{0, http.StatusInternalServerError, err.Error(), ""} } var ErrUserPassEmpty = &ApiError{110, http.StatusBadRequest, "Password is empty", ""} var ErrUserNotFound = &ApiError{123, http.StatusNotFound, "User not found", ""} var ErrUserIdEmpty = &ApiError{130, http.StatusBadRequest, "Empty User Id", ""} var ErrUserIdWrong = &ApiError{131, http.StatusBadRequest, "Wrong User Id", ""} // тАж  . . 


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

 type error interface { Error() string } 


рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЗрд╕ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рддреНрд░реБрдЯрд┐ () рд╡рд┐рдзрд┐ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реЛрдирд╛ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИред рдореИрдВрдиреЗ рдЕрдкрдирд╛ рд╕реНрд╡рдпрдВ рдХрд╛ рдПрд░рд░ рдЯрд╛рдЗрдк ApiError рдмрдирд╛рдпрд╛, рдЬреЛ рдореЗрд░реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рддреНрд░реБрдЯрд┐ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рд╛рде рд╕рдВрдЧрдд рд╣реИред

рдзреНрдпрд╛рди рджреЗрдВ - ApiError рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдЯрд╛рдЗрдк рдХрд░реЗрдВред рдпрд╣ рд╕рдВрд░рдЪрдирд╛ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рд╣реИ, рдбреЗрдЯрд╛ рдореЙрдбрд▓, рдЬрд┐рд╕реЗ рдЖрдк рдЕрдкрдиреЗ рдХрд╛рдо рдореЗрдВ рд▓рдЧрд╛рддрд╛рд░ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред рдЗрд╕рдореЗрдВ рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХреЗ рдлрд╝реАрд▓реНрдб рд╢рд╛рдорд┐рд▓ рд╣реИрдВ (рдореБрдЭреЗ рдЖрд╢рд╛ рд╣реИ рдХрд┐ рдЖрдк рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд╣реЛрдВрдЧреЗ рдХрд┐ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдЪрд░ рдирд╛рдо рдХреЗ рдмрд╛рдж рд▓рд┐рдЦрд╛ рдЧрдпрд╛ рд╣реИ)ред рд╡реИрд╕реЗ, рдлрд╝реАрд▓реНрдб рдЕрдиреНрдп рд╕рдВрд░рдЪрдирд╛рдПрдВ рд╣реЛ рд╕рдХрддреА рд╣реИрдВ, рд╕рднреА рд╡рд┐рдзрд┐рдпреЛрдВ рдФрд░ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рд╡рд┐рд░рд╛рд╕рдд рдореЗрдВ рдорд┐рд▓рд╛ рд╕рдХрддреА рд╣реИрдВред рдПрдХрд▓ рдЙрджреНрдзрд░рдг рдЪрд┐рд╣реНрди `` рдЯреИрдЧ рджрд░реНрд╢рд╛рддреЗ рд╣реИрдВред рд╡реЗ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╣реИрдВред рдЗрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЗрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдПрдиреНрдХреЛрдбрд┐рдВрдЧ / json рдкреИрдХреЗрдЬ рджреНрд╡рд╛рд░рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рддрд╛рдХрд┐ json рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рдирд╛рдо рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ (рдЛрдг рдЪрд┐рд╣реНрди "-" рдЖрдо рддреМрд░ рдкрд░ рдлрд╝реАрд▓реНрдб рдХреЛ рдЖрдЙрдЯрдкреБрдЯ рд╕реЗ рдмрд╛рд╣рд░ рд░рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред

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

рд╣рдо рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред Func (e * ApiError) Error () рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХрд╛ рдЕрд░реНрде рдЗрд╕ рд╕рдВрд░рдЪрдирд╛ рдХреА рдПрдХ рд╡рд┐рдзрд┐ рд╕реЗ рдЕрдзрд┐рдХ рдХреБрдЫ рдирд╣реАрдВ рд╣реИред рдЪрд░ рдИ рдПрдХ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдХреЗрддрдХ рд╣реИ, рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╕реНрд╡рдпрдВ / рдпрд╣ред рддрджрдиреБрд╕рд╛рд░, рд╕рдВрд░рдЪрдирд╛ рдкрд░ .Error () рдкрджреНрдзрддрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ, рд╣рдореЗрдВ рдЗрд╕рдХрд╛ рд╕рдВрджреЗрд╢ рдлрд╝реАрд▓реНрдб рдорд┐рд▓рддрд╛ рд╣реИред

рдЕрдЧрд▓рд╛, рд╣рдо рдкреВрд░реНрд╡рдирд┐рд░реНрдзрд╛рд░рд┐рдд рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рдкрд╣рдЪрд╛рди рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрдирдХреЗ рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рднрд░рддреЗ рд╣реИрдВред рдкреНрд░рдкрддреНрд░ рдХреЗ рдлрд╝реАрд▓реНрдб http.StatusBadRequest рдорд╛рдирдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЛрдб рдХреЗ рд▓рд┐рдП http рдкреИрдХреЗрдЬ рдореЗрдВ рдЕрдВрддрд░ рдорд╛рди рд╣реИрдВ, рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдирд╛рдоред рд╣рдо рдЖрд░рдВрдн рдХреЗ рд╕рд╛рде & ApiError {} рд╕рдВрд░рдЪрдирд╛ рдХреА рдШреЛрд╖рдгрд╛ рдХреЗ рд▓рд┐рдП рд╢реЙрд░реНрдЯрд╣реИрдВрдб рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рджреВрд╕рд░реЗ рддрд░реАрдХреЗ рд╕реЗ, рдХреЛрдИ рдЗрд╕реЗ рд▓рд┐рдЦ рд╕рдХрддрд╛ рд╣реИ:

 MyError := new(ApiError) MyError.Code = 110 // тАж 


рдЗрд╕ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдХреЗрддрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рддреАрдХ рдФрд░ рд╕рд╛рдзрдиред рдирдпрд╛ () рдСрдкрд░реЗрдЯрд░ рднреА рдПрдХ рд╕реВрдЪрдХ рджреЗрддрд╛ рд╣реИ, рдПрдХ рдореВрд▓реНрдп рдирд╣реАрдВред рд╢реБрд░реБрдЖрдд рдореЗрдВ, рдкреЙрдЗрдВрдЯрд░реНрд╕ рдХреЗ рд╕рд╛рде рдереЛрдбрд╝рд╛ рднреНрд░рдо рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рдордп рдХреЗ рд╕рд╛рде рдЖрдкрдХреЛ рдЗрд╕рдХреА рдЖрджрдд рд╣реЛ рдЬрд╛рдПрдЧреАред

рдЪрд▓реЛ рд╣рдорд╛рд░реЗ рдореЙрдбрд▓ рдкрд░ рдЪрд▓рддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдкреЛрд╕реНрдЯ рдореЙрдбрд▓ рдХрд╛ рдПрдХ рдиреАрдЪреЗ рдЫреАрди рд╕рдВрд╕реНрдХрд░рдг рд╣реИ:

 package models import ( "labix.org/v2/mgo/bson" "loctalk/conf" "loctalk/utils" "time" "unicode/utf8" "log" ) // GeoJSON format type Geo struct { Type string `json:"-"` Coordinates [2]float64 `json:"coordinates"` } type Post struct { Id bson.ObjectId `json:"id" bson:"_id,omitempty"` UserId bson.ObjectId `json:"userId"` UserName string `json:"userName"` ThumbUrl string `json:"thumbUrl"` ParentId bson.ObjectId `json:"parentId,omitempty" bson:",omitempty"` Enabled bool `json:"-"` Body string `json:"body"` Geo Geo `json:"geo"` Date time.Time `json:"date" bson:",omitempty"` } func NewPost() *Post { return new(Post) } func (p *Post) LoadById(id string) *conf.ApiError { if !bson.IsObjectIdHex(id) { return conf.ErrPostIdWrong } session := utils.NewDbSession() defer session.Close() c := session.Col("posts") err := c.Find(bson.M{"_id": bson.ObjectIdHex(id), "enabled": true}).One(p) if p.Id == "" { return conf.ErrPostNotFound } if err != nil { return conf.NewApiError(err) } return nil } func (p *Post) Create() (id string, err *conf.ApiError) { // validation switch { case p.UserId == "": err = conf.ErrUserIdEmpty case p.Body == "": err = conf.ErrPostBodyEmpty case utf8.RuneCountInString(p.Body) > conf.MAX_POST_CHARS: err = conf.ErrPostMaxSize case p.Geo.Coordinates[0] == 0.0 || p.Geo.Coordinates[1] == 0.0: err = conf.ErrPostLocationEmpty } if err != nil { return } p.Id = bson.NewObjectId() p.Geo.Type = "Point" p.Enabled = true p.Date = time.Now() session := utils.NewDbSession() defer session.Close() c := session.Col("posts") errDb := c.Insert(p) if errDb != nil { return "", conf.NewApiError(errDb) } return p.Id.Hex(), nil } func (p *Post) Update() *conf.ApiError { session := utils.NewDbSession() defer session.Close() c := session.Col("posts") err := c.UpdateId(p.Id, p) if err != nil { return conf.NewApiError(err) } return nil } func (p *Post) Disable() *conf.ApiError { session := utils.NewDbSession() defer session.Close() p.Enabled = false c := session.Col("posts") err := c.UpdateId(p.Id, p) if err != nil { return conf.NewApiError(err) } return nil } // тАж 


рдпрд╣рд╛рдВ рд╣рдо рдбреЗрдЯрд╛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП MongoDb - mgo рдХреЗ рд▓рд┐рдП рдЕрджреНрднреБрдд рдбреНрд░рд╛рдЗрд╡рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ mgo api - utils.NewDbSession рдкрд░ рдПрдХ рдЫреЛрдЯрд╛ рд░реИрдкрд░ рдмрдирд╛рдпрд╛ред рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХрд╛ рддрд░реНрдХ: рдкрд╣рд▓реЗ рд╣рдо рднрд╛рд╖рд╛ рдХреА рдЖрдВрддрд░рд┐рдХ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдПрдХ рд╡рд╕реНрддреБ рдмрдирд╛рддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░, рдЗрд╕ рд╕рдВрд░рдЪрдирд╛ рдХреА рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдЗрд╕реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕рд╣реЗрдЬреЗрдВред

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

рдЦреИрд░, рдпрд╣ рдирд┐рдпрдВрддреНрд░рдХ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рд░рдЦрдирд╛ рд╣реИ, рдЬреЛ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рддрд╛ рд╣реИ рдФрд░ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдЬреЛрдВрд╕ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред

 package controllers import ( "encoding/json" "fmt" "github.com/go-martini/martini" "labix.org/v2/mgo/bson" "loctalk/conf" "loctalk/models" "loctalk/utils" "net/http" ) func GetPostById(mu *utils.MarshUnmarsh, params martini.Params) (int, []byte) { id := params["id"] post := models.NewPost() err := post.LoadById(id) if err != nil { return err.HttpCode, mu.Marshal(err) } return http.StatusOK, mu.Marshal(post) } // ... 


рдпрд╣рд╛рдВ рд╣рдореЗрдВ URL рд╕реЗ рдЕрдиреБрд░реЛрдзрд┐рдд рдкреЛрд╕реНрдЯ рдХреА рдЖрдИрдбреА рдорд┐рд▓рддреА рд╣реИ, рд╣рдорд╛рд░реА рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдПрдХ рдирдпрд╛ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕реЗ рдбреЗрдЯрд╛ рд▓реЛрдб рдХрд░рдиреЗ рдФрд░ рдЗрд╕ рд╕рдВрд░рдЪрдирд╛ рдХреЛ рднрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрд╕ рдкрд░ LoadById (рдЖрдИрдбреА) рд╡рд┐рдзрд┐ рдХрд╣рддреЗ рд╣реИрдВред рдЬрд┐рд╕реЗ рд╣рдо рдЕрдкрдиреЗ mu.Marshal (рдкреЛрд╕реНрдЯ) рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ json рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж HTTP рдкрд░ рдЖрдЙрдЯрдкреБрдЯ рдХрд░рддреЗ рд╣реИрдВред

рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдкрд░ рдзреНрдпрд╛рди рджреЗрдВ:
 func GetPostById(mu *utils.MarshUnmarsh, params martini.Params) (int, []byte) 

рдорд╛рд░реНрдЯрд┐рдиреА рд╣рдореЗрдВ рдирд┐рд░реНрднрд░рддрд╛ рдЗрдВрдЬреЗрдХреНрд╢рди рддрдВрддреНрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрдирдкреБрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдФрд░ рд╣рдо рджреЛ рдорд╛рдкрджрдВрдбреЛрдВ (рдЙрджрд╛рд╣рд░рдг, [] рдмрд╛рдЗрдЯ) - рдПрдХ рд╕рдВрдЦреНрдпрд╛ (рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╕реНрдерд┐рддрд┐) рдФрд░ рдмрд╛рдЗрдЯреНрд╕ рдХреА рдПрдХ рд╕рд░рдгреА рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред

рддреЛ, рд╣рдордиреЗ рдореБрдЦреНрдп рдШрдЯрдХреЛрдВ рдФрд░ рджреГрд╖реНрдЯрд┐рдХреЛрдгреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХреА рд╣реИ, рдЬрд┐рд╕рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рдЖрдк рдХрдо рд╕рдордп рдореЗрдВ рдПрдХ рдкреНрд░рднрд╛рд╡реА RESTful API рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рд▓реЗрдЦ рдорджрджрдЧрд╛рд░ рд░рд╣рд╛ рд╣реЛрдЧрд╛ рдФрд░ рдЖрдкрдореЗрдВ рд╕реЗ рдХреБрдЫ рдХреЛ рдЕрджреНрднреБрдд рдЧреЛ рднрд╛рд╖рд╛ рд╕реАрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░реЗрд░рд┐рдд рдХрд░реЗрдЧрд╛ред рдореБрдЭреЗ рдпрдХреАрди рд╣реИ рдХрд┐ рднрд╡рд┐рд╖реНрдп рдЙрд╕рдХреЗ рд╕рд╛рде рд╣реИред

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

UPD: рд░рд╢рд┐рдпрди рдореЗрдВ рдЯреВрд░ рдЧреЛ ред

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


All Articles