рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ рдЖрдкрдХреЛ рдпрд╣ рдмрддрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдк рдЧреЛ рдореЗрдВ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреИрд╕реЗ рдЬрд▓реНрджреА рдФрд░ рдЖрд╕рд╛рдиреА рд╕реЗ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдЕрдкрдиреА рдЫреЛрдЯреА рдЙрдореНрд░ рдХреЗ рдмрд╛рд╡рдЬреВрдж, рдХрдИ рдбреЗрд╡рд▓рдкрд░реНрд╕ рдХрд╛ рдкрдХреНрд╖ рдЬреАрддрдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ред рдЖрдорддреМрд░ рдкрд░, рдРрд╕реЗ рд▓реЗрдЦреЛрдВ рдХреЗ рд▓рд┐рдП рд╡реЗ TODO рд╢реАрдЯ рдХреА рддрд░рд╣ рдХреГрддреНрд░рд┐рдо рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд▓рд┐рдЦрддреЗ рд╣реИрдВред рд╣рдо рдХреБрдЫ рдЙрдкрдпреЛрдЧреА рд▓рд┐рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВрдЧреЗ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рдореМрдЬреВрдж рд╣реИрдВ рдФрд░ рдЬрд┐рдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдЕрдХреНрд╕рд░ рд╕реЗрд╡рд╛рдУрдВ рдХреЛ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╕рдордп, рдЖрдкрдХреЛ рдпрд╣ рд╕рдордЭрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ рдХрд┐ рдХрд┐рд╕реА рдЕрдиреНрдп рд╕реЗрд╡рд╛ рдХреЛ рдХреНрдпрд╛ рдбреЗрдЯрд╛ рднреЗрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрд╛рддрд╛рдпрд╛рдд рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣рдореЗрд╢рд╛ рдЙрдкрд▓рдмреНрдз рдирд╣реАрдВ рд╣реЛрддреА рд╣реИред рдФрд░ рдмрд╕ рдРрд╕реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдкрдХрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ
requestb.in рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ URL рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдПрдХрддреНрд░ рдХрд░рдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╡реЗрдм рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред рд╣рдо рдПрдХ рд╕рдорд╛рди рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓рд┐рдЦрдиреЗ рдореЗрдВ рд▓рдЧреЗ рд░рд╣реЗрдВрдЧреЗред рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдп рдХреЛ рдереЛрдбрд╝рд╛ рд╕рд░рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП, рдЖрдзрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ,
рдорд╛рд░реНрдЯрд┐рдиреА рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд░реВрдкрд░реЗрдЦрд╛ рд▓реЗрдВред
рдЕрдВрддрддрдГ, рд╣рдореЗрдВ рдРрд╕реА рд╕реЗрд╡рд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП:

рдЯреНрд░реЗрдирд┐рдВрдЧ
рдЗрд╕ рд▓реЗрдЦ рдХреЛ рдЪрд░рдгреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдореЗрдВ GitHub рдкрд░ рдПрдХ рдЕрд▓рдЧ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рд╢рд╛рдЦрд╛ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХреЛрдб рд╣реЛрдЧрд╛ред рдЖрдк рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рд╣рдореЗрд╢рд╛ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА рдХреЛрдб рдХреЗ рд╕рд╛рде рдЦреЗрд▓ рд╕рдХрддреЗ рд╣реИрдВред
рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЪрд▓рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЕрдкрдиреА рдорд╢реАрди рдкрд░ рдПрдХ рдЧреЛ рд╕рдВрдХрд▓рдХ рд░рдЦрдирд╛ рд╣реЛрдЧрд╛ред рдореИрдВ рдЗрд╕ рдзрд╛рд░рдгрд╛ рд╕реЗ рдЖрдЧреЗ рдмрдврд╝рддрд╛ рд╣реВрдВ рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдпрд╣ рд╣реИ рдФрд░ рдЙрд╕ рддрд░рд╣ рд╕реЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЗ рдЕрдиреБрд░реВрдк рд╣реИред рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рдЖрдк рдпрд╣ рдЬрд╛рди рд╕рдХрддреЗ рд╣реИрдВ
рдХрд┐ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдкреГрд╖реНрда рдкрд░ рдпрд╣ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдПред
рдПрдХ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдорд╛рд╣реМрд▓ рдХреЗ рд░реВрдк рдореЗрдВ, рдЖрдк рдЕрдкрдиреЗ рд▓рд┐рдП рдЕрдзрд┐рдХ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдЧреЛ рдХреЗ рд▓рд┐рдП рд▓рдЧрднрдЧ рд╣рд░ рд╕рдВрдкрд╛рджрдХ рдкреНрд▓рдЧ-рдЗрди рдХрд░ рд░рд╣реЗ рд╣реИрдВред рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп
GoSublime рд╣реИ ред рд▓реЗрдХрд┐рди рдореИрдВ IntelijIdea +
go-lang-ide-plugin рдХреА рд╕рд▓рд╛рд╣ рджреВрдВрдЧрд╛, рдЬреЛ рд╣рд╛рд▓ рд╣реА рдореЗрдВ рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкрд┐рдЫрд▓реЗ рдПрдХ рдЬреЛрдбрд╝рд╛ - рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдбрд┐рдмрдЧ рд╕реЗред
рдЖрдк
skimmer.tulu.la рдкрд░ рдХрд╛рдо рдореЗрдВ рддреИрдпрд╛рд░ рд╕реЗрд╡рд╛ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЕрдкрдиреА рдорд╢реАрди рдХреЗ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЛ рдХреБрдЫ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдХреНрд▓реЛрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдЗрд╕ рддрд░рд╣:
git clone https://github.com/m0sth8/skimmer ./skimmer
рдЖрдк рдЕрдкрдиреЗ рдХрд╛рдо рдХреЗ рдорд╛рд╣реМрд▓ рдореЗрдВ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ (рдЗрд╕ рдкрд░ рдЕрдзрд┐рдХ
рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╡реЗрдмрд╕рд╛рдЗрдЯ рдкрд░ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ), рдпрд╛ рдЕрдкрдиреА рдЗрдЪреНрдЫрд╛рдиреБрд╕рд╛рд░ рдХреЛрдб рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдкреНрд░рд╕реНрддреБрддрд┐ рдХреА рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рдореИрдВ
рдЧреЛрдПрдирд╡ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛
рд╣реВрдВ , рдЬреЛ рдЖрдкрдХреЛ рд╕рдВрдХрд▓рдХ рд╕рдВрд╕реНрдХрд░рдгреЛрдВ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдФрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдПрдХ рд╕реНрд╡рдЪреНрдЫ рдХрд╛рд░реНрдп рд╡рд╛рддрд╛рд╡рд░рдг рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
рдЕрдм рд╣рдореЗрдВ рд╕реНрдХрд┐рдорд░ рдХреНрд▓реЛрди рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдЬрд╛рдиреЗ рдФрд░ рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде рдЖрд╡рд╢реНрдпрдХ рдирд┐рд░реНрднрд░рддрд╛ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
go get -d ./src/
рдирд┐рд░реНрднрд░рддрд╛ рдХреА рд╕реНрдерд╛рдкрдирд╛ рдХреЛ рдкреВрд░рд╛ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
go run ./src/main.go
рдЖрдкрдХреА рд╡реЗрдм рд╕реЗрд╡рд╛ рдкреЛрд░реНрдЯ 3000 рдкрд░ рд╢реБрд░реВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдП (рдкреЛрд░реНрдЯ рдФрд░ рд╣реЛрд╕реНрдЯ рдХреНрд░рдорд╢рдГ рдкреЛрд░реНрдЯ рдФрд░ HOST рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ)ред рдЕрдм рдЖрдк рдЗрд╕реЗ 127.0.0.1000000 рдкрд░ рдПрдХ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ рдЦреЛрд▓ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдХрд╛рдо рдореЗрдВ рддреИрдпрд╛рд░ рд╕реЗрд╡рд╛ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЪрд░рдг рд╣рдореЗрдВ рдЗрдВрддрдЬрд╛рд░ рдХрд░ рд░рд╣реЗ рд╣реИрдВ:
- рдкрд╣рд▓рд╛ рдХрджрдоред рдкреЗрд╢ рд╣реИ рдорд╛рд░реНрдЯрд┐рдиреА
- рдЪрд░рдг рджреЛ рд╣рдо рдмрд┐рди рдореЙрдбрд▓ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЕрдиреБрд░реЛрдзреЛрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрддреЗ рд╣реИрдВ;
- рдЪрд░рдг рддреАрди рд╣рдо рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рднрдВрдбрд╛рд░ рдореЗрдВ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВ;
- рдЪреМрдерд╛ рдЪрд░рдгред рд▓реЗрдХрд┐рди рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХрд╛ рдХреНрдпрд╛?
- рдкрд╛рдВрдЪ рдЪрд░рдг - рдЕрд▓рдВрдХрд░рдг рдФрд░ рдПрдХ рд╡реЗрдм рдЗрдВрдЯрд░рдлрд╝реЗрд╕;
- рдЪрд░рдг рдЫрд╣ рдХреБрдЫ рдЧреЛрдкрдиреАрдпрддрд╛ рдЬреЛрдбрд╝реЗрдВ;
- рд╕рд╛рддрд╡рд╛рдВ рдЪрд░рдгред рд╣рдо рдЕрдирд╛рд╡рд╢реНрдпрдХ рдХреЛ рд╕рд╛рдл рдХрд░рддреЗ рд╣реИрдВ;
- рдЪрд░рдг рдЖрдаред рд╣рдо рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рд░реЗрдбрд┐рд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
рд▓реЗрдЦ рдХреЗ рдкрд╣рд▓реЗ рдФрд░ рджреВрд╕рд░реЗ рднрд╛рдЧ рдХреЛ рд╕рд╣реА рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
рдХрд╛рд╡реВ рдХрд╛ рд╡рд┐рд╢реЗрд╖ рдзрдиреНрдпрд╡рд╛рджред
рд╣рдо рд╡рд┐рдХрд╛рд╕ рдХреЗ рд▓рд┐рдП рдЖрдЧреЗ рдмрдврд╝рддреЗ рд╣реИрдВред
рдкрд╣рд▓рд╛ рдХрджрдоред рдкреЗрд╢ рд╣реИ рдорд╛рд░реНрдЯрд┐рдиреАред
рдкрд╣рд▓реЗ рдЪрд░рдг рдХреЗ рд▓рд┐рдП рдХреЛрдб рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ:
git checkout step-1
рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреБрд░реЛрдз рдХреЛ рдкреНрд░рд┐рдВрдЯ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдЧреЛ рдкрд░ рдХрд┐рд╕реА рднреА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХрд╛ рдкреНрд░рд╡реЗрд╢ рдмрд┐рдВрджреБ рдореБрдЦреНрдп рдкреИрдХреЗрдЬ рдХрд╛ рдореБрдЦреНрдп рдХрд╛рд░реНрдп рд╣реИред Src рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ main.go рдлрд╝рд╛рдЗрд▓ рдмрдирд╛рдПрдБ рдорд╛рд░реНрдЯрд┐рдиреА рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рдкреВрд░реНрд╡-рдирд┐рд░реНрдорд┐рдд рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╣реИ рдЬреЛ рд▓реЙрдЧреНрд╕, рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд┐рдВрдЧ, рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдФрд░ рдПрдХ рд░рд╛рдЙрдЯрд░ рдЬреЛрдбрд╝рддрд╛ рд╣реИ; рдФрд░ рдЦреБрдж рдХреЛ рди рджреЛрд╣рд░рд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрд╕рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░реЗрдВрдЧреЗред
рдорд╛рд░реНрдЯрд┐рдиреА рдЦреБрдж рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИрдВ:
рдпрд╣ ServeHTTP рд╡рд┐рдзрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдХреЗ
http.Handler рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЖрдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рдЕрдиреБрд░реЛрдз рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╡рд┐рднрд┐рдиреНрди рд╣реИрдВрдбрд▓рд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкрд╛рд░рд┐рдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдЕрдВрдд рдореЗрдВ рд╣реИрдВрдбрд▓рд░ рдПрдХреНрд╢рди рдХрд░рддреЗ рд╣реИрдВред
рдХреНрд▓рд╛рд╕рд┐рдХ рдорд╛рд░реНрдЯрд┐рдиреА:
рдЗрд╕ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдЯрд╛рдЗрдк рдорд╛рд░реНрдЯрд┐рдиреА рдФрд░ рд░рд╛рдЙрдЯрд░ рдХрд╛ рдПрдХ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЕрдиреБрд░реЛрдз рд▓реЙрдЧрд┐рдВрдЧ, рдкреИрдирд┐рдХ рдЗрдВрдЯрд░рд╕реЗрдкреНрд╢рди (рдЗрд╕ рддрдВрддреНрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ
рдЕрдзрд┐рдХ ), рд╕реНрдерд┐рд░ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рд╣реИрдВрдбрд▓рд░ рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рдорд╛рд░реНрдЯрд┐рдиреА.рдпреВрдПрд╕ рд╡рд┐рдзрд┐ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдЕрдВрддрд┐рдо рдХреНрд░рд┐рдпрд╛ рд░рд╛рдЙрдЯрд░ рд╣реИрдВрдбрд▓рд░ рд╕реЗрдЯ рдХрд░рддреА рд╣реИред
рд╣рдо рд░рд╛рдЙрдЯрд░ рдкрд░
Any
рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ,
Any
рднреА рдпреВрдЖрд░рдПрд▓ рдФрд░ рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯ рдХрд░рддреЗ рд╣реБрдП рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд░реЛрдХреЗрдВрдЧреЗред рд░рд╛рдКрдЯрд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рд╡рд░реНрдгрди рдорд╛рд░реНрдЯрд┐рдиреА рдореЗрдВ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
type Router interface {
рдпрджрд┐ рдЖрдк рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдПрдбреНрд░реЗрд╕ рд╣реИрдВрдбрд▓рд░ рдХреЗ рдЕрдкрдиреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдо рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдорд╛рд░реНрдЯрд┐рдиреА рдХреЗ рд╕рд╛рде рдЖрдиреЗ рд╡рд╛рд▓реЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред
рдкрд╣рд▓рд╛ рдкреИрд░рд╛рдореАрдЯрд░ рд╕реНрдерд╛рди рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред
":param"
, рдирд┐рдпрдорд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐, рд╕рд╛рде рд╣реА
рдЧреНрд▓реЛрдм рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдорд╛рд░реНрдЯрд┐рдиреА рдореЗрдВ рд╕реНрдерд╛рди рдХрд╛ рд╕рдорд░реНрдерди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рджреВрд╕рд░рд╛ рдкреИрд░рд╛рдореАрдЯрд░ рдФрд░ рдЕрдЧрд▓рд╛, рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓реЗрдВ рдЬреЛ рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рдВрднрд╛рд▓ рд▓реЗрдЧрд╛ред рдЪреВрдВрдХрд┐ рдорд╛рд░реНрдЯрд┐рдиреА рд╣реИрдВрдбрд▓рд░ рдХреА рдПрдХ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рд╕рд╣рд╛рдпрдХ рд╣реИрдВрдбрд▓рд░ рдпрд╣рд╛рдВ рдЬреЛрдбрд╝реЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХреНрд╕реЗрд╕ рдХрдВрдЯреНрд░реЛрд▓ред рд╣рдореЗрдВ рдЕрднреА рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рд╕рд╛рдорд╛рдиреНрдп рдЧреЛ рд╡реЗрдм рд╣реИрдВрдбрд▓рд░ рджреНрд╡рд╛рд░рд╛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд┐рдП рдЧрдП рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд╕рд╛рде рдХреЗрд╡рд▓ рдПрдХ рд╣реИрдВрдбрд▓рд░ рдЬреЛрдбрд╝реЗрдВрдЧреЗ (
рдЗрд╕ рдкрд░ рд╡рд┐рдХрд╛рд╕ рдХреЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ
рд▓рд┐рдП рдкреНрд░рд▓реЗрдЦрди рджреЗрдЦреЗрдВ)ред рдпрд╣рд╛рдБ рд╣рдорд╛рд░реЗ рд╣реИрдВрдбрд▓рд░ рдХреЗ рд▓рд┐рдП рдХреЛрдб рд╣реИ:
func main() { api := martini.Classic() api.Any("/", func(res http.ResponseWriter, req *http.Request,) { if dumped, err := httputil.DumpRequest(req, true); err == nil { res.WriteHeader(200) res.Write(dumped) } else { res.WriteHeader(500) fmt.Fprintf(res, "Error: %v", err) } }) api.Run() }
рдиреЙрдЯрдкреБрдЯрд┐рд▓ рдкреИрдХреЗрдЬ рд╕реЗ рддреИрдпрд╛рд░
рдбрдореНрдкрд░реЗрд╕рдкреЗрд╕реНрдЯ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ
, рд╣рдо http.Request рдЕрдиреБрд░реЛрдз рд╕рдВрд░рдЪрдирд╛ рдХреЛ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ HTTP.ResponseWriter рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд▓рд┐рдЦрддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╕рдВрднрд╡ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдордд рднреВрд▓рдирд╛ред Api.Run рдлрд╝рдВрдХреНрд╢рди рдХреЗрд╡рд▓ рдорд╛рдирдХ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╕реЗ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рдЧреЛ рд╕рд░реНрд╡рд░ рдХреЛ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ, рдкреЛрд░реНрдЯ рдФрд░ рд╣реЛрд╕реНрдЯ рдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЗрд╕реЗ рдкрд░реНрдпрд╛рд╡рд░рдг рд╕реЗрдЯрд┐рдВрдЧреНрд╕ PORT (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ 3000) рдФрд░ HOST рд╕реЗ рд▓реЗрддрд╛ рд╣реИред
рд╣рдорд╛рд░рд╛ рдкрд╣рд▓рд╛ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд▓реЙрдиреНрдЪ рдХрд░реЗрдВ:
go run ./src/main.go
рдЖрдЗрдП рд╕рд░реНрд╡рд░ рд╕реЗ рдЕрдиреБрд░реЛрдз рднреЗрдЬрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВ:
> curl -X POST -d "fizz=buzz" http://127.0.0.1:3000 POST / HTTP/1.1 Host: 127.0.0.1:3000 Accept: */* Content-Type: application/x-www-form-urlencoded User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5 fizz=buzz
рдпрд╣ рд╕рд┐рд░реНрдл рд╢рдХреНрддрд┐ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдерд╛, рдЕрдм рдЗрд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рд▓рд┐рдЦрдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВред
рдЪрд░рдг рджреЛ рд╣рдо рдмрд┐рди рдореЙрдбрд▓ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЕрдиреБрд░реЛрдзреЛрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрддреЗ рд╣реИрдВред
рдХреЛрдб рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ:
git checkout step-2
рдореБрдЦреНрдп рдкреИрдХреЗрдЬ рдХреЗ рдЕрдВрджрд░ рдХреЛрдб рд░рдЦрдирд╛ рдмрд╣реБрдд рд╕рд╣реА рдирд╣реАрдВ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП,
Google рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдЗрдВрдЬрди рдЕрдкрдирд╛ рдореБрдЦреНрдп рдкреИрдХреЗрдЬ рдмрдирд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдЖрдкрдХрд╛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЬреБрдбрд╝рд╛ рд╣реБрдЖ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╣рдо рдПрдкреАрдЖрдИ рдХреЗ рдирд┐рд░реНрдорд╛рдг рдХреЛ рдПрдХ рдЕрд▓рдЧ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВ, рдЪрд▓реЛ рдЗрд╕реЗ рдирд╛рдо рджреЗрддреЗ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рд╕реНрдХрд┐рдорд░ / рдПрдкреАрдЖрдИрдУрдЧреЛред
рдЕрдм рд╣рдореЗрдВ рдПрдХ рдЗрдХрд╛рдИ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдкрдХрдбрд╝реЗ рдЧрдП рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЪрд▓реЛ рдмрд┐рди рдХреЛ рдЕрдиреБрд░реЛрдз рдХреЗ рд╕рд╛рде рд╕рд╛рджреГрд╢реНрдп рджреНрд╡рд╛рд░рд╛ рдмрд┐рди рдХрд╣рддреЗ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЬреЛ рдореЙрдбрд▓ рд╣реИ рд╡рд╣ рдХреЗрд╡рд▓ рд╕рд╛рдорд╛рдиреНрдп рдЧреЛ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рд╣реИред
рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдлрд╝реАрд▓реНрдб рдХрд╛ рдХреНрд░рдо рдХрд╛рдлреА рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдо рдЗрд╕рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдирд╣реАрдВ рд╕реЛрдЪрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЬреЛ рд▓реЛрдЧ рдЬрд╛рдирдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдХрд┐ рдСрд░реНрдбрд░ рдореЗрдореЛрд░реА рдореЗрдВ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдЖрдХрд╛рд░ рдХреЛ рдХреИрд╕реЗ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░рддрд╛ рд╣реИ, рд╡реЗ рдЗрди рд▓реЗрдЦреЛрдВ рдХреЛ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ - www.goinggo.net/2013/07/understanding-type-in -go.html рдФрд░ www.geeksforgeeks.org/structure-member-alignment-padding-and-data-packing ред
рдЗрд╕рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рдмрд┐рди рдореЙрдбрд▓ рдореЗрдВ рдПрдХ рдирд╛рдо рдХреЗ рд╕рд╛рде рдлрд╝реАрд▓реНрдб, рдкрдХрдбрд╝реЗ рдЧрдП рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдФрд░ рдирд┐рд░реНрдорд╛рдг рдФрд░ рдкрд░рд┐рд╡рд░реНрддрди рдХреА рддрд╛рд░реАрдЦреЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реЛрдВрдЧреАред рдкреНрд░рддреНрдпреЗрдХ рдХреНрд╖реЗрддреНрд░ рдХреЛ рдПрдХ рдЯреИрдЧ рджреНрд╡рд╛рд░рд╛ рднреА рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рдЯреИрдЧ рд╕рд╛рдзрд╛рд░рдг рд░реЗрдЦрд╛рдПрдВ рд╣реИрдВ рдЬреЛ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рд╕рдВрдкреВрд░реНрдг рд░реВрдк рд╕реЗ рдкреНрд░рднрд╛рд╡рд┐рдд рдирд╣реАрдВ рдХрд░рддреА рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЙрдиреНрд╣реЗрдВ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдкрдврд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдЬрдмрдХрд┐ рдХрд╛рд░реНрдпрдХреНрд░рдо рдЪрд▓ рд░рд╣рд╛ рд╣реИ (рддрдерд╛рдХрдерд┐рдд рдЖрддреНрдордирд┐рд░реАрдХреНрд╖рдг), рдФрд░ рдЗрд╕рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдЕрдкрдиреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рдмрджрд▓реЗрдВ ( рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЯреИрдЧ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХреИрд╕реЗ рдХрд░реЗрдВ)ред рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, json рдкреИрдХреЗрдЬ рдЯреИрдЧ рдХреА рд╡реИрд▓реНрдпреВ рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦрддрд╛ рд╣реИ рдЬрдм рдПрдиреНрдХреЛрдбрд┐рдВрдЧ / рдбрд┐рдХреЛрдбрд┐рдВрдЧ, рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рд╕реЗ:
package main import ( "reflect" "fmt" ) type Bin struct { Name string `json:"name"` } func main() { bin := Bin{} bt := reflect.TypeOf(bin) field := bt.Field(0) fmt.Printf("Field's '%s' json name is '%s'", field.Name, field.Tag.Get("json")) }
рдЙрддреНрдкрд╛рджрди рдХрд░реЗрдЧрд╛
Field's 'Name' json name is 'name'
рдПрдиреНрдХреЛрдбрд┐рдВрдЧ / json рдкреИрдХреЗрдЬ рдЯреИрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╡рд┐рднрд┐рдиреНрди рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ:
рджреВрд╕рд░рд╛ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, omitempty рд╡рд┐рдХрд▓реНрдк - рдпрджрд┐ рдорд╛рди рдореЗрдВ рдорд╛рди рдЫреЛрдбрд╝рд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдлрд╝реАрд▓реНрдб рдирд╣реАрдВ рднрд░рд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдлрд╝реАрд▓реНрдб рдПрдХ рд▓рд┐рдВрдХ рд╣реИ, рддреЛ рд╣рдо рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рдпрд╣ рд╢реВрдиреНрдп рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдореЗрдВ рдореМрдЬреВрдж рд╣реИред рдЖрдк рдбреЙрдХреНрдпреВрдореЗрдВрдЯреЗрд╢рди рдореЗрдВ json serialization рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ ред
рд╣рдо рд╕рд╣рд╛рдпрдХ рдлрд╝рдВрдХреНрд╢рди рдиреНрдпреВрдмрд┐рди рдХрд╛ рднреА рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рдореЗрдВ рдмрд┐рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдЖрд░рдВрднреАрдХреГрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ (рдПрдХ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирд┐рд░реНрдорд╛рдг):
type Bin struct { Name string `json:"name"` Created int64 `json:"created"` Updated int64 `json:"updated"` RequestCount int `json:"requestCount"` } func NewBin() *Bin { now := time.Now().Unix() bin := Bin{ Created: now, Updated: now, Name: rs.Generate(6), } return &bin }
рдЧреЛ рдореЗрдВ рд╕рдВрд░рдЪрдирд╛рдПрдВ рджреЛ рддрд░реАрдХреЛрдВ рд╕реЗ рдЖрд░рдВрдн рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИрдВ:
1) рдХреНрд░рдо рдореЗрдВ рд╕рднреА рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреА рдЕрдирд┐рд╡рд╛рд░реНрдп рд╕реВрдЪреА:
Bin{rs.Generate(6), now, now, 0}
2) рдЙрди рдХреНрд╖реЗрддреНрд░реЛрдВ рдХрд╛ рд╕рдВрдХреЗрдд рдЬрд┐рдирдХреЗ рд▓рд┐рдП рдорд╛рди рдЕрд╕рд╛рдЗрди рдХрд┐рдП рдЧрдП рд╣реИрдВ:
Bin{ Created: now, Updated: now, Name: rs.Generate(6), }
рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдлрд╝реАрд▓реНрдб рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рд╕реНрд╡реАрдХрд╛рд░ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкреВрд░реНрдгрд╛рдВрдХ рдХреЗ рд▓рд┐рдП рдпрд╣ 0 рд╣реЛрдЧрд╛, рд╕реНрдЯреНрд░рд┐рдВрдЧреНрд╕ рдХреЗ рд▓рд┐рдП - рдПрдХ рд░рд┐рдХреНрдд рд╕реНрдЯреНрд░рд┐рдВрдЧ "", рд▓рд┐рдВрдХ, рдЪреИрдирд▓, рд╕рд░рдгрд┐рдпреЛрдВ, рд╕реНрд▓рд╛рдЗрд╕ рдФрд░ рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдХреЗ рд▓рд┐рдП - рдпрд╣ рд╢реВрдиреНрдп рд╣реЛрдЧрд╛ред рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реАред рдпрд╛рдж рд░рдЦрдиреЗ рд╡рд╛рд▓реА рдореБрдЦреНрдп рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЖрдк рдЗрди рджреЛрдиреЛрдВ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЖрд░рдВрднреАрдХрд░рдг рдХреЛ рдирд╣реАрдВ рдорд┐рд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдЕрдм рдЖрд░рдПрд╕ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рддрд╛рд░ рдХреА рдкреАрдврд╝реА рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗред рдЗрд╕реЗ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдЖрд░рдВрднреАрдХреГрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
var rs = NewRandomString("0123456789abcdefghijklmnopqrstuvwxyz")
рдХреЛрдб рд╣реА utils.go рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╣реИред рд╣рдо рдЙрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рд╡рд░реНрдгреЛрдВ рдХрд╛ рдПрдХ рд╕рд░рдгреА рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдБ рд╕реЗ рд╣рдореЗрдВ рдПрдХ рд▓рд╛рдЗрди рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдФрд░ рдПрдХ рд░реИрдВрдбрдо рд╕реНрдЯреНрд░реАрдВрдЧ рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ:
type RandomString struct { pool string rg *rand.Rand } func NewRandomString(pool string) *RandomString { return &RandomString{ pool, rand.New(rand.NewSource(time.Now().Unix())), } } func (rs *RandomString) Generate(length int) (r string) { if length < 1 { return } b := make([]byte, length) for i, _ := range b { b[i] = rs.pool[rs.rg.Intn(len(rs.pool))] } r = string(b) return }
рдпрд╣рд╛рдВ рд╣рдо
рдЧрдгрд┐рдд / рд░реИрдВрдб рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдЬрд┐рд╕рд╕реЗ рд╣рдореЗрдВ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдВрдЦреНрдпрд╛ рдкреАрдврд╝реА рддрдХ рдкрд╣реБрдВрдЪ рдорд┐рд▓рддреА рд╣реИред рд╕рдмрд╕реЗ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЬрдирд░реЗрдЯрд░ рдХреЛ рдмреЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЖрдк рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рджреЗрдВ, рддрд╛рдХрд┐ рд╣рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рд╢реБрд░реБрдЖрдд рдореЗрдВ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХрд╛ рд╕рдорд╛рди рдХреНрд░рдо рди рдорд┐рд▓реЗред
рдЬрдирд░реЗрдЯ рд╡рд┐рдзрд┐ рдореЗрдВ, рд╣рдо рдмрд╛рдЗрдЯреНрд╕ рдХреА рдПрдХ рд╕рд░рдгреА рдмрдирд╛рддреЗ рд╣реИрдВ, рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдмрд╛рдЗрдЯреНрд╕ рдХреЛ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдкреВрд▓ рд╕реЗ рдПрдХ рдпрд╛рджреГрдЪреНрдЫрд┐рдХ рдЪрд░рд┐рддреНрд░ рдХреЗ рд╕рд╛рде рднрд░рддреЗ рд╣реИрдВред рдкрд░рд┐рдгрд╛рдореА рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╡рд╛рдкрд╕ рдЖ рдЧрдИ рд╣реИред
рдЪрд▓рд┐рдП, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЖрдкреА рдХреЗ рд╡рд░реНрдгрди рдХреЗ рд▓рд┐рдПред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╡рд╕реНрддреБ рдХреЗ рдкреНрд░рдХрд╛рд░, рдмрд┐рди рдХреЛ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рдиреЗ, рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдмрдирд╛рдиреЗ рдФрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддреАрди рддрд░реАрдХреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ, рдореИрдВрдиреЗ рд▓рд┐рдЦрд╛ рдерд╛ рдХрд┐ рдорд╛рд░реНрдЯрд┐рдиреА рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рд╣реИрдВрдбрд▓рд░рдлрдВрдХ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рд╕рд╛рде рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдорд╛рд░реНрдЯрд┐рдиреА рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ {} рдХреЗ рд░реВрдк рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ - рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рдХрд┐рд╕реА рднреА рдлрд╝рдВрдХреНрд╢рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рддрд░реНрдХ рдХреИрд╕реЗ рдбрд╛рд▓реЗ рдЬрд╛рддреЗ рд╣реИрдВ? рдпрд╣ рд▓реЗрдЦрдХ рдкрд╛рдгрд┐рдиреА рдХреЗ рдПрдХ рдЫреЛрдЯреЗ рдкреИрдХреЗрдЬ
рдЗрдВрдЬреЗрдХреНрд╢рди рдХреА рдорджрдж рд╕реЗ рдкреНрд░рд╕рд┐рджреНрдз рдкреИрдЯрд░реНрди -
рдбрд┐рдкреЗрдВрдбреЗрдВрд╕реА рдЗрдВрдЬреЗрдХреНрд╢рди (рдЗрд╕рдХреЗ рдмрд╛рдж DI) рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдореИрдВ рдЗрд╕ рдмрд╛рд░реЗ рдореЗрдВ рд╡рд┐рд╡рд░рдг рдореЗрдВ рдирд╣реАрдВ рдЬрд╛рдКрдВрдЧрд╛ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЖрдк рдХреЛрдб рдХреЛ рд╕реНрд╡рдпрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдмрдбрд╝рд╛ рдирд╣реАрдВ рд╣реИ рдФрд░ рд╡рд╣рд╛рдВ рд╕рдм рдХреБрдЫ рдХрд╛рдлреА рд╕рд░рд▓ рд╣реИред рд▓реЗрдХрд┐рди рдЕрдЧрд░ рджреЛ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рддреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рджрд░реНрд╢рд╛рдП рдЧрдП рдкреИрдХреЗрдЬ рдХреА рдорджрдж рд╕реЗ, рдкреНрд░рдХрд╛рд░ рдХреЗ рддрд░реНрдХ рддрд░реНрдХ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреА рдЖрд╡рд╢реНрдпрдХ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЬрдм рдЗрдВрдЬреЗрдХреНрд╢рди рдкреНрд░рдХрд╛рд░ * http.Request рджреЗрдЦрддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдЗрд╕ рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ req * http.Request рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддрд╛ рд╣реИред
рд╣рдо рд╡рд┐рд╢реНрд╡ рд╕реНрддрд░ рдкрд░ рдореИрдк рдФрд░ рдореЗрдкреЛрдЯреЛ рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рддрд░реАрдХреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдпрд╛ рдорд╛рд░реНрдЯрд┐рдиреА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рддрд┐рдмрд┐рдВрдм рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдкреНрд░рддреНрдпреЗрдХ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдЕрдиреБрд░реЛрдз рдХреЗ рд▓рд┐рдП рдорд╛рд░реНрдЯрд┐рдиреАред рдХреЙрдиреНрдЯреЗрдХреНрд╕реНрдЯ рдЕрдиреБрд░реЛрдз рд╕рдВрджрд░реНрдн рд╡рд╕реНрддреБред
рд╣рдо рдЕрд╕реНрдерд╛рдпреА рдЪрд░ рдЗрддрд┐рд╣рд╛рд╕ рдФрд░ рдбрд┐рдмреНрдмреЗ рдХреА рдШреЛрд╖рдгрд╛ рдХрд░реЗрдВрдЧреЗ, рдкрд╣рд▓реЗ рдореЗрдВ рдмрд┐рди рд╡рд╕реНрддреБрдУрдВ рдХрд╛ рдЗрддрд┐рд╣рд╛рд╕ рд╣реЛрдЧрд╛ рдЬреЛ рд╣рдордиреЗ рдмрдирд╛рдпрд╛ рдерд╛, рдФрд░ рджреВрд╕рд░рд╛ рдмрд┐рди рд╡рд╕реНрддреБ рднрдВрдбрд╛рд░рдг рдХрд╛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд▓рдШреБ рд╕рдВрд╕реНрдХрд░рдг рд╣реЛрдЧрд╛ред
рдЕрдм рдмрдирд╛рдИ рдЧрдИ рд╡рд┐рдзрд┐рдпреЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред
рдПрдХ рдмрд┐рди рд╡рд╕реНрддреБ рдХрд╛ рдирд┐рд░реНрдорд╛рдг
api.Post("/api/v1/bins/", func(r render.Render){ bin := NewBin() bins[bin.Name] = bin history = append(history, bin.Name) r.JSON(http.StatusCreated, bin) })
рдмрд┐рди рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛
api.Get("/api/v1/bins/", func(r render.Render){ filteredBins := []*Bin{} for _, name := range(history) { if bin, ok := bins[name]; ok { filteredBins = append(filteredBins, bin) } } r.JSON(http.StatusOK, filteredBins) })
рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛
api.Get("/api/v1/bins/:bin", func(r render.Render, params martini.Params){ if bin, ok := bins[params["bin"]]; ok{ r.JSON(http.StatusOK, bin) } else { r.Error(http.StatusNotFound) } })
рдПрдХ рд╡рд┐рдзрд┐ рдЬреЛ рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рдирд╛рдо рд╕реЗ рдПрдХ рдмрд┐рди рдСрдмреНрдЬреЗрдХреНрдЯ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ, рдЗрд╕рдореЗрдВ рд╣рдо рдорд╛рд░реНрдЯрд┐рдиреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╢рдмреНрдж рдСрдмреНрдЬреЗрдХреНрдЯ (рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рд╕рд┐рд░реНрдл рдПрдХ рдирдХреНрд╢рд╛ [рд╕реНрдЯреНрд░рд┐рдВрдЧ] рд╕реНрдЯреНрд░рд┐рдВрдЧ) рдЬрд┐рд╕рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣рдо рдкрд╛рд░реНрд╕ рдХрд┐рдП рдЧрдП рдкрддреЗ рдорд╛рдкрджрдВрдбреЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рд╕рдХрддреЗ рд╣реИрдВред
рдЧреЛ рдореЗрдВ, рд╣рдо рдПрдХ рд╢рдмреНрджрдХреЛрд╢ рддрддреНрд╡ рдХреЛ рджреЛ рддрд░реАрдХреЛрдВ рд╕реЗ рдПрдХреНрд╕реЗрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
- рдХреБрдВрдЬреА рдореВрд▓реНрдп рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж
a := m[key]
, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╛ рддреЛ рд╢рдмреНрджрдХреЛрд╢ рдореЗрдВ рдореБрдЦреНрдп рдореВрд▓реНрдп, рдпрджрд┐ рдХреЛрдИ рд╣реЛ, рдпрд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдореВрд▓реНрдп рдЖрд░рдВрднреАрдХрд░рдг рдореВрд▓реНрдп рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдПрдЧрд╛ред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рд▓рд┐рдП, рдпрд╣ рд╕рдордЭрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдХреБрдВрдЬреА рдореЗрдВ 0 рд╣реИ рдпрд╛ рдмрд╕ рдЗрд╕ рдХреБрдВрдЬреА рдХрд╛ рдорд╛рди рдореМрдЬреВрдж рдирд╣реАрдВ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдЧреЛ рдХреЗ рд▓рд┐рдП рджреВрд╕рд░рд╛ рд╡рд┐рдХрд▓реНрдк рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред - рдЗрд╕ рд╡рд┐рдзрд┐ рдореЗрдВ, рдХреБрдВрдЬреА рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рдирд╛ рдФрд░ рдкрд╣рд▓реЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрд╕рдХрд╛ рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдФрд░ рджреВрд╕рд░реЗ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕ рдХреБрдВрдЬреА рдХреЗ рдЕрд╕реНрддрд┐рддреНрд╡ рдХрд╛ рд╕реВрдЪрдХ -
a, ok := m[key]
рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рд╕рд╛рде рдкреНрд░рдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕реЗ рдЪрд▓рд╛рдПрдВ:
go run ./src/main.go
рдПрдХ рдирдпрд╛ рдмрд┐рди рдСрдмреНрдЬреЗрдХреНрдЯ рдЬреЛрдбрд╝реЗрдВ:
> curl -i -X POST "127.0.0.1:3000/api/v1/bins/" HTTP/1.1 201 Created Content-Type: application/json; charset=UTF-8 Date: Mon, 03 Mar 2014 04:10:38 GMT Content-Length: 76 {"name":"7xpogf","created":1393819838,"updated":1393819838,"requestCount":0}
рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рдмрд┐рди рд╡рд╕реНрддреБрдУрдВ рдХреА рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ:
> curl -i "127.0.0.1:3000/api/v1/bins/" HTTP/1.1 200 OK Content-Type: application/json; charset=UTF-8 Date: Mon, 03 Mar 2014 04:11:18 GMT Content-Length: 78 [{"name":"7xpogf","created":1393819838,"updated":1393819838,"requestCount":0}]
рд╣рдо рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдмрд┐рди рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╣реИрдВ, рдкрд┐рдЫрд▓реЗ рдЕрдиреБрд░реЛрдз рд╕реЗ рдирд╛рдо рдорд╛рди рд▓реЗрддреЗ рд╣реИрдВ:
curl -i "127.0.0.1:3000/api/v1/bins/7xpogf" HTTP/1.1 200 OK Content-Type: application/json; charset=UTF-8 Date: Mon, 03 Mar 2014 04:12:13 GMT Content-Length: 76 {"name":"7xpogf","created":1393819838,"updated":1393819838,"requestCount":0}
рдЦреИрд░, рдЕрдм рд╣рдордиреЗ рд╕реАрдЦрд╛ рд╣реИ рдХрд┐ рдореЙрдбрд▓ рдХреИрд╕реЗ рдмрдирд╛рдПрдВ рдФрд░ рдЕрдиреБрд░реЛрдзреЛрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдВ, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЕрдм рдХреБрдЫ рднреА рдирд╣реАрдВ рд╣рдореЗрдВ рд╕рдм рдХреБрдЫ рдкреВрд░рд╛ рдХрд░рдиреЗ рд╕реЗ рд░реЛрдХ рд╕рдХрддрд╛ рд╣реИред
рдЪрд░рдг рддреАрди рд╣рдо рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рднрдВрдбрд╛рд░ рдореЗрдВ рд╕рд╣реЗрдЬрддреЗ рд╣реИрдВред
рдЕрдм рд╣рдореЗрдВ рдпрд╣ рд╕реАрдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рд╡рд╛рдВрдЫрд┐рдд рдмрд┐рди рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдХреИрд╕реЗ рдмрдЪрд╛рдпрд╛ рдЬрд╛рдПред
рддреАрд╕рд░реЗ рдЪрд░рдг рдХреЗ рд▓рд┐рдП рдХреЛрдб рдбрд╛рдЙрдирд▓реЛрдб рдХрд░реЗрдВ
git checkout step-3
рдЕрдиреБрд░реЛрдз рдореЙрдбрд▓
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдПрдХ рдореЙрдбрд▓ рдмрдирд╛рдПрдВ рдЬреЛ рдПрдХ HTTP рдЕрдиреБрд░реЛрдз рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдЧрд╛ред
type Request struct { Id string `json:"id"` Created int64 `json:"created"` Method string `json:"method"` // GET, POST, PUT, etc. Proto string `json:"proto"` // "HTTP/1.0" Header http.Header `json:"header"` ContentLength int64 `json:"contentLength"` RemoteAddr string `json:"remoteAddr"` Host string `json:"host"` RequestURI string `json:"requestURI"` Body string `json:"body"` FormValue map[string][]string `json:"formValue"` FormFile []string `json:"formFile"` }
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕рдордЭрд╛рдиреЗ рдХрд╛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИ рдХрд┐ рдпрд╣ рдХрд┐рд╕ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рд╣реИ, рд▓реЗрдХрд┐рди рдХреБрдЫ рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдВ рд╣реИрдВ: рдлрд╛рдЗрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╣рдо рдХреЗрд╡рд▓ рдЙрдирдХреЗ рдирд╛рдореЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдлреЙрд░реНрдо рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рд╣рдо рдореВрд▓реНрдпреЛрдВ рдХреЗ рддреИрдпрд╛рд░ рд╢рдмреНрджрдХреЛрд╢ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдВрдЧреЗред
рдПрдХ рдмрд┐рди рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдирддрд╛ рд╕реЗ, рд╣рдо рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдЬреЛ HTTP рдЕрдиреБрд░реЛрдз рд╕реЗ рдПрдХ рдЕрдиреБрд░реЛрдз рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рддрд╛ рд╣реИ:
func NewRequest(httpRequest *http.Request, maxBodySize int) *Request { var ( bodyValue string formValue map[string][]string formFile []string ) // if body, err := ioutil.ReadAll(httpRequest.Body); err == nil { if len(body) > 0 && maxBodySize != 0 { if maxBodySize == -1 || httpRequest.ContentLength < int64(maxBodySize) { bodyValue = string(body) } else { bodyValue = fmt.Sprintf("%s\n<<<TRUNCATED , %d of %d", string(body[0:maxBodySize]), maxBodySize, httpRequest.ContentLength) } } httpRequest.Body = ioutil.NopCloser(bytes.NewBuffer(body)) defer httpRequest.Body.Close() } httpRequest.ParseMultipartForm(0) if httpRequest.MultipartForm != nil { formValue = httpRequest.MultipartForm.Value for key := range httpRequest.MultipartForm.File { formFile = append(formFile, key) } } else { formValue = httpRequest.PostForm } request := Request{ Id: rs.Generate(12), Created: time.Now().Unix(), Method: httpRequest.Method, Proto: httpRequest.Proto, Host: httpRequest.Host, Header: httpRequest.Header, ContentLength: httpRequest.ContentLength, RemoteAddr: httpRequest.RemoteAddr, RequestURI: httpRequest.RequestURI, FormValue: formValue, FormFile: formFile, Body: bodyValue, } return &request }
рдлрд╝рдВрдХреНрд╢рди рдХрд╛рдлреА рдмрдбрд╝рд╛ рдирд┐рдХрд▓рд╛, рд▓реЗрдХрд┐рди рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рд╕рдордЭрдиреЗ рдпреЛрдЧреНрдп, рдореИрдВ рдХреЗрд╡рд▓ рдХреБрдЫ рдмрд┐рдВрджреБрдУрдВ рдХреА рд╡реНрдпрд╛рдЦреНрдпрд╛ рдХрд░реВрдВрдЧрд╛ред
Http.Request рдСрдмреНрдЬреЗрдХреНрдЯ рдореЗрдВ, рдЕрдиреБрд░реЛрдз рдмреЙрдбреА - рдмреЙрдбреА рдПрдХ рдмрдлрд░ рд╣реИ рдЬреЛ
io.ReadCloser рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕ рдХрд╛рд░рдг рд╕реЗ, рдлреЙрд░реНрдо рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж (ParseMultipartForm рд╡рд┐рдзрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рдХреЗ), рд╣рдо рдХрдЪреНрдЪреЗ рдЕрдиреБрд░реЛрдз рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рдирд╣реАрдВ рдХрд░ рдкрд╛рдПрдВрдЧреЗред рдЗрд╕рд▓рд┐рдП, рд╢реБрд░реБрдЖрдд рдХреЗ рд▓рд┐рдП, рд╣рдо рд╢рд░реАрд░ рдХреЛ рдПрдХ рдЕрд▓рдЧ рдЪрд░ рдореЗрдВ рдХреЙрдкреА рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╣рдо рдореВрд▓ рдмрдлрд░ рдХреЛ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рд╕рд╛рде рдкреНрд░рддрд┐рд╕реНрдерд╛рдкрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдЕрдЧрд▓рд╛, рд╣рдо рдЖрдиреЗ рд╡рд╛рд▓реЗ рдбреЗрдЯрд╛ рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЛ рдХрд╣рддреЗ рд╣реИрдВ рдФрд░ рд░реВрдкреЛрдВ рдФрд░ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдПрдХрддреНрд░ рдХрд░рддреЗ рд╣реИрдВред
рдмрд┐рди рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЕрдм рд╣рдореЗрдВ рдЙрд╕реА рддрд░рд╣ рд╕реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП, рдпрд╣ рд╣рдорд╛рд░реА рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдбреЗрдЯрд╛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред рд╣рдо Storage.go рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЗрд╕рдХреЗ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ:
type Storage interface { LookupBin(name string) (*Bin, error) // get one bin element by name LookupBins(names []string) ([]*Bin, error) // get slice of bin elements LookupRequest(binName, id string) (*Request, error) // get request from bin by id LookupRequests(binName string, from, to int) ([]*Request, error) // get slice of requests from bin by position CreateBin(bin *Bin) error // create bin in memory storage UpdateBin(bin *Bin) error // save CreateRequest(bin *Bin, req *Request) error }
рдЧреЛ рдореЗрдВ рдЗрдВрдЯрд░рдлреЗрд╕ рдЕрдкреЗрдХреНрд╖рд┐рдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдФрд░ рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЬреЛрдбрд╝рдиреЗ рд╡рд╛рд▓рд╛ рдПрдХ рдЕрдиреБрдмрдВрдз рд╣реИред рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдордиреЗ рднрдВрдбрд╛рд░рдг рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рдмрд╛рдж рдореЗрдВ рдХрд╛рд░реНрдпрдХреНрд░рдо рдореЗрдВ рдХрд░реЗрдВрдЧреЗ, рд▓реЗрдХрд┐рди рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЗ рдЖрдзрд╛рд░ рдкрд░, рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрд╣ рд░реЗрдбрд┐рд╕ рдпрд╛ рдореИрдВрдЧреЛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ)ред рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдПрдХ рдмреБрдирд┐рдпрд╛рджреА рднрдВрдбрд╛рд░рдг рд╡рд╕реНрддреБ рдмрдирд╛рдПрдВрдЧреЗ, рдЬрд┐рд╕рдореЗрдВ рд╕рд╣рд╛рдпрдХ рдХреНрд╖реЗрддреНрд░ рд╣реЛрдВрдЧреЗ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА:
type BaseStorage struct { maxRequests int }
рдЕрдм рд╣рдорд╛рд░реЗ рднрдВрдбрд╛рд░рдг рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЗрди
рдореНрдпреВрдЯреЗрдХреНрд╕ рдХреЗ рд╕рдорд╛рдирд╛рдВрддрд░ рдкрд╣реБрдВрдЪ рдХреЛ
рдкрд░рд┐рд╕реАрдорд┐рдд рдХрд░рддреЗ
рд╣реБрдП , рдореЗрдореЛрд░реА рдореЗрдВ рд╕рдм рдХреБрдЫ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред
рдПрдХ рдореИрдореЛрд░реА рдмрдирд╛рдПрдБред рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░реЗрдВ рд╣рдорд╛рд░рд╛ рд╕рдВрдЧреНрд░рд╣рдг рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реЛрдЧрд╛:
type MemoryStorage struct { BaseStorage sync.RWMutex binRecords map[string]*BinRecord }
рдЗрд╕рдореЗрдВ рдиреЗрд╕реНрдЯреЗрдб, рдЕрдирд╛рдо рдмреЗрд╕рд╕реНрдЯреЛрд░реАрдЬ рдФрд░ рд╕рд┐рдВрдХ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рд░реБрдореЗрдЯреЗрдХреНрд╕ рдХреНрд╖реЗрддреНрд░ред
рдмреЗрдирд╛рдореА рдХреНрд╖реЗрддреНрд░ рд╣рдореЗрдВ рд╕реАрдзреЗ рдЧреБрдордирд╛рдо рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рддрд░реАрдХреЛрдВ рдФрд░ рдХреНрд╖реЗрддреНрд░реЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдореЗрдореЛрд░реАрд╕реНрдЯреЛрд░реАрдЬ рдХрд╛ рдПрдХ рдУрдмреНрдЬреЗрдХреНрдЯ рд╡реЗрд░рд┐рдПрдмрд▓ рд╣реИ, рддреЛ рд╣рдо рд╕реАрдзреЗ maxjequests рдлрд╝реАрд▓реНрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ obj.BaseStorage.maxRequests, рдпрд╛ рдорд╛рдиреЛ рд╡реЗ MemoryStorage obj.maxRequest рдХреЗ рд╕рджрд╕реНрдп рд╣реИрдВред рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рдбреЗрдЯрд╛ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдореЗрдВ рдЕрдирд╛рдо рдлрд╝реАрд▓реНрдб рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдФрд░ рдкрдврд╝реЗрдВред
рд╣рдореЗрдВ
RWMutex рдХреЛ BinRecords рдбрд┐рдХреНрд╢рдирд░реА рдХреЗ рдпреБрдЧрдкрдд рд╕рдВрдЪрд╛рд▓рди рдХреЛ рдмреНрд▓реЙрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЧреЛ рд╕рдорд╛рдирд╛рдВрддрд░ рдореЗрдВ рд╢рдмреНрджрдХреЛрд╢реЛрдВ рдореЗрдВ рдбреЗрдЯрд╛ рдмрджрд▓рддреЗ рд╕рдордп рд╕рд╣реА рд╡реНрдпрд╡рд╣рд╛рд░ рдХреА рдЧрд╛рд░рдВрдЯреА рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред
рдбреЗрдЯрд╛ рдХреЛ рдЦреБрдж рд╣реА BinRecords рдлрд╝реАрд▓реНрдб рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ Bin рдСрдмреНрдЬреЗрдХреНрдЯреНрд╕ рдХреЗ рдирд╛рдо рдлрд╝реАрд▓реНрдб рд╕реЗ рдХреБрдВрдЬрд┐рдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╢рдмреНрджрдХреЛрд╢ рд╣реИ рдФрд░ BinRecord рдкреНрд░рдХрд╛рд░ рдХрд╛ рдбреЗрдЯрд╛ред
type BinRecord struct { bin *Bin requests []*Request requestMap map[string]*Request }
рдЗрд╕ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рд╕рднреА рдЖрд╡рд╢реНрдпрдХ рдбреЗрдЯрд╛ рд╢рд╛рдорд┐рд▓ рд╣реИрдВред рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдВрдХ рджреЛ рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ, рд╕реВрдЪреА рдореЗрдВ рдЬрд╣рд╛рдВ рд╡реЗ рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдФрд░ рд╢рдмреНрджрдХреЛрд╢ рдореЗрдВ, рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рддреЗрдЬреА рд╕реЗ рдЦреЛрдЬ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд╕рд░рдг рдХрд░рддреЗ рд╣реИрдВред
рд╡рд░реНрддрдорд╛рди рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рд╢рдмреНрджрдХреЛрд╢ рдореЗрдВ рд╢рдмреНрджрдХреЛрд╢ рддрд╛рд▓рд┐рдХрд╛ рдХрд╛ рдПрдХ рд╣реИрд╢ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╢рдмреНрджрдХреЛрд╢ рдореЗрдВ рдПрдХ рддрддреНрд╡ рдХреА рдЦреЛрдЬ рдХрд╛ рдПрдХ рдирд┐рд░рдВрддрд░ рдореВрд▓реНрдп рд╣реИред рдЗрд╕ рдЦреВрдмрд╕реВрд░рдд рд▓реЗрдЦ рдореЗрдВ рдЖрдВрддрд░рд┐рдХ рдЙрдкрдХрд░рдг рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдФрд░ рдкрдврд╝реЗрдВред
BinRecord рдСрдмреНрдЬреЗрдХреНрдЯ рдЕрдирд╛рд╡рд╢реНрдпрдХ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рдЯреНрд░рд┐рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рдзрд┐ рднреА рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдХреЗрд╡рд▓ рдЕрдирд╛рд╡рд╢реНрдпрдХ рддрддреНрд╡реЛрдВ рдХреЛ рдЕрдиреБрд░реЛрдзреЛрдВ рдФрд░ рдЕрдиреБрд░реЛрдзреЛрдВ рд╕реЗ рд╣рдЯрд╛рддрд╛ рд╣реИред
func (binRecord *BinRecord) ShrinkRequests(size int) { if size > 0 && len(binRecord.requests) > size { requests := binRecord.requests lenDiff := len(requests) - size removed := requests[:lenDiff] for _, removedReq := range removed { delete(binRecord.requestMap, removedReq.Id) } requests = requests[lenDiff:] binRecord.requests = requests } }
рдореЗрдореЛрд░реАрд╕реНрдЯреЛрд░реЗрдЬ рдХреЗ рд╕рднреА рддрд░реАрдХреЗ рд╕реНрдЯреЛрд░реЗрдЬ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рд╡реНрдпрд╡рд╣рд╛рд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╣реИрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╕рд╣рд╛рдпрдХ рддрд░реАрдХрд╛ getBinRecord рднреА рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдЕрдкрдиреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдХреЗ рд░рд┐рдХреЙрд░реНрдб рдХреЛ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред рдЬрд┐рд╕ рд╕рдордп рд╣рдо рд░рд┐рдХреЙрд░реНрдб рдкрдврд╝рддреЗ рд╣реИрдВ, рд╣рдо рд▓реЙрдХ рдХреЛ рд░реАрдб рдкрд░ рдбрд╛рд▓рддреЗ рд╣реИрдВ рдФрд░ рддреБрд░рдВрдд рд▓реЙрдХ рдХреЛ рд░рд┐рд▓реАрдЬрд╝ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╕реНрдердЧрд┐рдд рдХреЙрд▓ рдХрд╛ рд╕рдВрдХреЗрдд рджреЗрддреЗ рд╣реИрдВред рдЖрд╕реНрдердЧрд┐рдд рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рд╣рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ рдЬреЛ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рдкрд░ рд╣рдореЗрд╢рд╛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдЧреА, рднрд▓реЗ рд╣реА рдлрд╝рдВрдХреНрд╢рди рдЖрддрдВрдХ рд╕реЗ рдмрд╛рдзрд┐рдд рд╣реЛред рдЖрдк
рдкреНрд░рд▓реЗрдЦрди рдореЗрдВ рдбрд┐рдлрд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЕрдзрд┐рдХ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ
редрдореЗрдореЛрд░реАрд╕реНрдЯреЛрд░реАрдЬ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рддрд░реАрдХреЗ рдкрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реИ, рд╕рдм рдХреБрдЫ рд╡реИрд╕реЗ рднреА рдЬрдЯрд┐рд▓ рдирд╣реАрдВ рд╣реИ, рдЖрдк рд╕реНрд╡рдпрдВ рдХреЛрдб рдореЗрдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред
рдореЗрдореЛрд░реАрд╕реНрдЯреЛрд░реАрдЬ рдХреЛрдб package skimmer import ( "errors" "sync" ) type MemoryStorage struct { BaseStorage sync.RWMutex binRecords map[string]*BinRecord } type BinRecord struct { bin *Bin requests []*Request requestMap map[string]*Request } func (binRecord *BinRecord) ShrinkRequests(size int) { if size > 0 && len(binRecord.requests) > size { requests := binRecord.requests lenDiff := len(requests) - size removed := requests[:lenDiff] for _, removedReq := range removed { delete(binRecord.requestMap, removedReq.Id) } requests = requests[lenDiff:] binRecord.requests = requests } } func NewMemoryStorage(maxRequests int) *MemoryStorage { return &MemoryStorage{ BaseStorage{ maxRequests: maxRequests, }, sync.RWMutex{}, map[string]*BinRecord{}, } } func (storage *MemoryStorage) getBinRecord(name string) (*BinRecord, error) { storage.RLock() defer storage.RUnlock() if binRecord, ok := storage.binRecords[name]; ok { return binRecord, nil } return nil, errors.New("Bin not found") } func (storage *MemoryStorage) LookupBin(name string) (*Bin, error) { if binRecord, err := storage.getBinRecord(name); err == nil { return binRecord.bin, nil } else { return nil, err } } func (storage *MemoryStorage) LookupBins(names []string) ([]*Bin, error) { bins := []*Bin{} for _, name := range names { if binRecord, err := storage.getBinRecord(name); err == nil { bins = append(bins, binRecord.bin) } } return bins, nil } func (storage *MemoryStorage) CreateBin(bin *Bin) error { storage.Lock() defer storage.Unlock() binRec := BinRecord{bin, []*Request{}, map[string]*Request{}} storage.binRecords[bin.Name] = &binRec return nil } func (storage *MemoryStorage) UpdateBin(_ *Bin) error { return nil } func (storage *MemoryStorage) LookupRequest(binName, id string) (*Request, error) { if binRecord, err := storage.getBinRecord(binName); err == nil { if request, ok := binRecord.requestMap[id]; ok { return request, nil } else { return nil, errors.New("Request not found") } } else { return nil, err } } func (storage *MemoryStorage) LookupRequests(binName string, from int, to int) ([]*Request, error) { if binRecord, err := storage.getBinRecord(binName); err == nil { requestLen := len(binRecord.requests) if to >= requestLen { to = requestLen } if to < 0 { to = 0 } if from < 0 { from = 0 } if from > to { from = to } reversedLen := to - from reversed := make([]*Request, reversedLen) for i, request := range binRecord.requests[from:to] { reversed[reversedLen-i-1] = request } return reversed, nil } else { return nil, err } } func (storage *MemoryStorage) CreateRequest(bin *Bin, req *Request) error { if binRecord, err := storage.getBinRecord(bin.Name); err == nil { storage.Lock() defer storage.Unlock() binRecord.requests = append(binRecord.requests, req) binRecord.requestMap[req.Id] = req binRecord.ShrinkRequests(storage.maxRequests) binRecord.bin.RequestCount = len(binRecord.requests) return nil } else { return err } }
рдЕрдм рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рднрдВрдбрд╛рд░ рд╣реИ, рддреЛ рд╣рдо рдЖрдкреА рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣рд╛рдВ рдХреНрдпрд╛ рдмрджрд▓ рд░рд╣рд╛ рд╣реИредрд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЕрдкрдиреЗ рдирдП рднрдВрдбрд╛рд░ рдХреЗ рд▓рд┐рдП рд╕рдорд░реНрдерди рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред memoryStorage := NewMemoryStorage(MAX_REQUEST_COUNT) api.MapTo(memoryStorage, (*Storage)(nil))
рдЕрдм рдХрд┐рд╕реА рднреА рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рд╣рдо рдЯрд╛рдЗрдк рд╕реНрдЯреЛрд░реЗрдЬ рдХрд╛ рдПрдХ рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╣рдорд╛рд░реЗ рд╕реНрдЯреЛрд░реЗрдЬ рддрдХ рдкрд╣реБрдБрдЪ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рдо рдЬреЛ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╡рд╣ рдмрд┐рди рдХреЗ рд▓рд┐рдП рд╕рднреА рдЕрдиреБрд░реЛрдз рд╕рдВрдЪрд╛рд▓рдХреЛрдВ рдореЗрдВ рд╕реНрдЯреЛрд░реЗрдЬ рдХреЛ рдХреЙрд▓ рдХреЗ рд╕рд╛рде рдбрд┐рдХреНрд╢рдирд░реА рдХреЗ рдХрд╛рдо рдХреА рдЬрдЧрд╣ рд▓реЗ рд░рд╣рд╛ рд╣реИред api.Post("/api/v1/bins/", func(r render.Render, storage Storage){ bin := NewBin() if err := storage.CreateBin(bin); err == nil { history = append(history, bin.Name) r.JSON(http.StatusCreated, bin) } else { r.JSON(http.StatusInternalServerError, ErrorMsg{err.Error()}) } }) api.Get("/api/v1/bins/", func(r render.Render, storage Storage){ if bins, err := storage.LookupBins(history); err == nil { r.JSON(http.StatusOK, bins) } else { r.JSON(http.StatusInternalServerError, ErrorMsg{err.Error()}) } }) api.Get("/api/v1/bins/:bin", func(r render.Render, params martini.Params, storage Storage){ if bin, err := storage.LookupBin(params["bin"]); err == nil{ r.JSON(http.StatusOK, bin) } else { r.JSON(http.StatusNotFound, ErrorMsg{err.Error()}) } })
рджреВрд╕рд░реЗ, рд╣рдордиреЗ рдкреНрд░рдХрд╛рд░ рдЕрдиреБрд░реЛрдз рдХреА рд╡рд╕реНрддреБрдУрдВ рдХреЗ рд▓рд┐рдП рд╣реИрдВрдбрд▓рд░ рдЬреЛрдбрд╝реЗред // api.Get("/api/v1/bins/:bin/requests/", func(r render.Render, storage Storage, params martini.Params, req *http.Request){ if bin, error := storage.LookupBin(params["bin"]); error == nil { from := 0 to := 20 if fromVal, err := strconv.Atoi(req.FormValue("from")); err == nil { from = fromVal } if toVal, err := strconv.Atoi(req.FormValue("to")); err == nil { to = toVal } if requests, err := storage.LookupRequests(bin.Name, from, to); err == nil { r.JSON(http.StatusOK, requests) } else { r.JSON(http.StatusInternalServerError, ErrorMsg{err.Error()}) } } else { r.Error(http.StatusNotFound) } }) // Request api.Get("/api/v1/bins/:bin/requests/:request", func(r render.Render, storage Storage, params martini.Params){ if request, err := storage.LookupRequest(params["bin"], params["request"]); err == nil { r.JSON(http.StatusOK, request) } else { r.JSON(http.StatusNotFound, ErrorMsg{err.Error()}) } }) // http Request Bin(name) api.Any("/bins/:name", func(r render.Render, storage Storage, params martini.Params, req *http.Request){ if bin, error := storage.LookupBin(params["name"]); error == nil { request := NewRequest(req, REQUEST_BODY_SIZE) if err := storage.CreateRequest(bin, request); err == nil { r.JSON(http.StatusOK, request) } else { r.JSON(http.StatusInternalServerError, ErrorMsg{err.Error()}) } } else { r.Error(http.StatusNotFound) } })
рдЖрдЗрдП, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЬреЛ рдХреБрдЫ рдЕрдиреБрд░реЛрдз рд╣реИрдВ рдЙрдиреНрд╣реЗрдВ рдЪрд▓рд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВредрд╣рдорд╛рд░реЗ HTTP рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд┐рди рдХрдВрдЯреЗрдирд░ рдмрдирд╛рдПрдБ > curl -i -X POST "127.0.0.1:3000/api/v1/bins/" HTTP/1.1 201 Created Content-Type: application/json; charset=UTF-8 Date: Mon, 03 Mar 2014 12:19:28 GMT Content-Length: 76 {"name":"ws87ui","created":1393849168,"updated":1393849168,"requestCount":0}
рд╣рдо рдЕрдкрдиреЗ рдХрдВрдЯреЗрдирд░ рдореЗрдВ рдПрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬреЗрдВрдЧреЗ > curl -X POST -d "fizz=buzz" http://127.0.0.1:3000/bins/ws87ui {"id":"i0aigrrc1b40","created":1393849284,...}
рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рдХреНрдпрд╛ рд╣рдорд╛рд░рд╛ рдЕрдиреБрд░реЛрдз рд╕рд╣реЗрдЬ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: > curl http://127.0.0.1:3000/api/v1/bins/ws87ui/requests/ [{"id":"i0aigrrc1b40","created":1393849284,...}]
рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕рдм рдХреБрдЫ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рд▓реЗрдХрд┐рди рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рдЖрдкрдХреЛ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдХреЗ рд╕рд╛рде рдХреЛрдб рдХреЛ рдХрд╡рд░ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рджреВрд╕рд░реЗ рднрд╛рдЧрдореЗрдВ рд▓реЗрдЦ рдХреА рдирд┐рд░рдВрддрд░рддрд╛ , рдЬрд╣рд╛рдВ рд╣рдо рд╕реАрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдкрд░реАрдХреНрд╖рдг рдХреИрд╕реЗ рд▓рд┐рдЦрдирд╛ рд╣реИ, AngularJS рдФрд░ рдмреВрдЯрд╕реНрдЯреНрд░реИрдк рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХрд▓-рдкреГрд╖реНрда рд╡реЗрдм рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛, рдереЛрдбрд╝реА рдЧреЛрдкрдиреАрдпрддрд╛ рдЬреЛрдбрд╝реЗрдВ рдФрд░ рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП Redis рд╕рдорд░реНрдерди рд▓рд╛рдЧреВ рдХрд░реЗрдВред