рдирдорд╕реНрдХрд╛рд░, рд╣реЗрдмреНрд░! рдореИрдВ рдЖрдкрдХреЗ рд▓рд┐рдП рдЕрдпреВрд▓реБрд╡рд╛ рдпрд╢рд╛рдпрд╛рд╣ рдХреЗ рд▓реЗрдЦ "рдЧреЛ рдХреЗ рд╕рд╛рде рдЕрдкрдирд╛ рдкрд╣рд▓рд╛ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреИрд╕реЗ рдмрдирд╛рдКрдВ" рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реВрдВред
рдпрд╣ рдЖрдкрдХреЗ рдкрд╣рд▓реЗ рдЧреЛ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рдЧрд╛рдЗрдб рд╣реИред рд╣рдо рдПрдХ рд╕рдорд╛рдЪрд╛рд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдПрдВрдЧреЗ рдЬреЛ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рд╡рд┐рд╖рдп рдкрд░ рд╕рдорд╛рдЪрд╛рд░ рд▓реЗрдЦ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рдЪрд╛рд░ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдЕрдВрдд рдореЗрдВ рдЙрддреНрдкрд╛рджрди рд╕рд░реНрд╡рд░ рдкрд░ рддреИрдирд╛рдд рдХрд░рддрд╛ рд╣реИред
рдЖрдк рдЗрд╕ GitHub рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдЗрд╕ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдкреВрд░рд╛ рдХреЛрдб рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ
рдЗрд╕ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рдПрдХрдорд╛рддреНрд░ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдЧреЛ рдЖрдкрдХреЗ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ рд╕реНрдерд╛рдкрд┐рдд рд╣реИ рдФрд░ рдЖрдк рдЗрд╕рдХреЗ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдФрд░ рдирд┐рд░реНрдорд╛рдгреЛрдВ рд╕реЗ рдереЛрдбрд╝рд╛ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВред рдЧреЛ рд╕рдВрд╕реНрдХрд░рдг рдЬрд┐рд╕реЗ рдореИрдВрдиреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдерд╛, рд╡рд╣ рд▓реЗрдЦрди рдХреЗ рд╕рдордп рднреА рдирд╡реАрдирддрдо рд╣реИ: 1.12.9 ред рдЧреЛ рдХреЗ рд╕реНрдерд╛рдкрд┐рдд рд╕рдВрд╕реНрдХрд░рдг рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдЧреЛ go version
рдХрдорд╛рдВрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
рдпрджрд┐ рдЖрдкрдХреЛ рдпрд╣ рдХрд╛рд░реНрдп рдмрд╣реБрдд рдХрдард┐рди рд▓рдЧрддрд╛ рд╣реИ, рддреЛ рдореЗрд░реЗ рдкрд┐рдЫрд▓реЗ рдкрд░рд┐рдЪрдпрд╛рддреНрдордХ рднрд╛рд╖рд╛ рдкрд╛рда рдкрд░ рдЬрд╛рдПрдВ , рдЬрд┐рд╕рд╕реЗ рдЖрдкрдХреЛ рдЖрд░рдВрдн рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдорд┐рд▓рдиреА рдЪрд╛рд╣рд┐рдПред
рддреЛ рдЪрд▓рд┐рдП рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИ!
рд╣рдо рдирд┐рд░реНрдорд┐рдд рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ GitHub рдФрд░ cd
рдкрд░ рдЖрд░рдВрднрд┐рдХ рдлрд╛рдЗрд▓ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдХреЛ рдХреНрд▓реЛрди рдХрд░рддреЗ рд╣реИрдВ ред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рддреАрди рдореБрдЦреНрдп рдлрд╛рдЗрд▓реЗрдВ рд╣реИрдВ: main.go
рдлрд╛рдЗрд▓ рдореЗрдВ main.go
рд╣рдо рдЗрд╕ рдХрд╛рд░реНрдп рдХреЗ рд▓рд┐рдП рд╕рднреА рдЧреЛ рдХреЛрдб рд▓рд┐рдЦреЗрдВрдЧреЗред index.html
рдлрд╝рд╛рдЗрд▓ рд╡рд╣ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рд╣реИ рдЬреЛ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рднреЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛, рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП
assets/styles.css
ред
рдПрдХ рдмреЗрд╕рд┐рдХ рд╡реЗрдм рд╕рд░реНрд╡рд░ рдмрдирд╛рдПрдВ
рдЪрд▓реЛ рдПрдХ рдореВрд▓ рд╕рд░реНрд╡рд░ рдмрдирд╛рдиреЗ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ рдЬреЛ рд╕рд░реНрд╡рд░ рдХреЛ GET рдЕрдиреБрд░реЛрдз рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╕рдордп рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ "рд╣реИрд▓реЛ рд╡рд░реНрд▓реНрдб!" рдкрд╛рда рднреЗрдЬрддрд╛ рд╣реИред рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреА main.go
рдлрд╛рдЗрд▓ рдмрджрд▓реЗрдВ:
package main import ( "net/http" "os" ) func indexHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("<h1>Hello World!</h1>")) } func main() { port := os.Getenv("PORT") if port == "" { port = "3000" } mux := http.NewServeMux() mux.HandleFunc("/", indexHandler) http.ListenAndServe(":"+port, mux) }
package main
рдХреА рдкрд╣рд▓реА рдкрдВрдХреНрддрд┐ - рдШреЛрд╖рдгрд╛ рдХрд░рддреА рд╣реИ рдХрд┐ main.go
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдХреЛрдб рдореБрдЦреНрдп рдкреИрдХреЗрдЬ рдХрд╛ рд╣реИред рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдордиреЗ net/http
рдкреИрдХреЗрдЬ рдХрд╛ рдЖрдпрд╛рдд рдХрд┐рдпрд╛, рдЬреЛ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП HTTP рдХреНрд▓рд╛рдЗрдВрдЯ рдФрд░ рд╕рд░реНрд╡рд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред рдпрд╣ рдкреИрдХреЗрдЬ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдЧреЛ рд╕реНрдерд╛рдкрдирд╛ рдХреЗ рд╕рд╛рде рд╢рд╛рдорд┐рд▓ рд╣реИред
main
рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ, http.NewServeMux()
рдПрдХ рдирдпрд╛ HTTP рдЕрдиреБрд░реЛрдз рдорд▓реНрдЯреАрдкреНрд▓реЗрдХреНрд╕ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ mux
рд╡реЗрд░рд┐рдПрдмрд▓ рдореЗрдВ рдЕрд╕рд╛рдЗрди рдХрд░рддрд╛ рд╣реИред рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ, рдЕрдиреБрд░реЛрдз рдорд▓реНрдЯреАрдкреНрд▓реЗрдХреНрд╕ рдкрдВрдЬреАрдХреГрдд рдкрдереЛрдВ рдХреА рд╕реВрдЪреА рдореЗрдВ рдЖрдиреЗ рд╡рд╛рд▓реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ URL рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ рдФрд░ рдЬрдм рднреА рдХреЛрдИ рдореИрдЪ рдорд┐рд▓рддрд╛ рд╣реИ, рддреЛ рдкрде рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд╣реИрдВрдбрд▓рд░ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред
рдЕрдЧрд▓рд╛, рд╣рдо рд░реВрдЯ рдкрде /
рд▓рд┐рдП рдЕрдкрдирд╛ рдкрд╣рд▓рд╛ рд╣реИрдВрдбрд▓рд░ рдлрд╝рдВрдХреНрд╢рди рдкрдВрдЬреАрдХреГрдд рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рд╣реИрдВрдбрд▓рд░ рдлрдВрдХреНрд╢рди рд╣реИрдВрдбрд▓ рдХрд╛ рджреВрд╕рд░рд╛ рддрд░реНрдХ рд╣реИ рдФрд░ рд╣рдореЗрд╢рд╛ рд╕рд┐рдЧреНрдиреЗрдЪрд░ func (w http.ResponseWriter, r * http.Request)
ред
рдпрджрд┐ рдЖрдк indexHandler
рдлрд╝рдВрдХреНрд╢рди рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдЗрд╕рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рд╣реИ, рдЬреЛ рдЗрд╕реЗ HandleFunc
рд▓рд┐рдП рдПрдХ рд╡реИрдз рджреВрд╕рд░рд╛ рддрд░реНрдХ HandleFunc
ред w
рдкреИрд░рд╛рдореАрдЯрд░ рд╡рд╣ рд╕рдВрд░рдЪрдирд╛ рд╣реИ рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо HTTP рдЕрдиреБрд░реЛрдз рдХреЗ рдЬрд╡рд╛рдм рднреЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ Write()
рд╡рд┐рдзрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдЬреЛ рдмрд╛рдЗрдЯ рд╕реНрд▓рд╛рдЗрд╕ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рд╕рдВрдпреБрдХреНрдд рдбреЗрдЯрд╛ рдХреЛ HTTP рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреЗ рднрд╛рдЧ рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд┐рдЦрддрд╛ рд╣реИред
рджреВрд╕рд░реА рдУрд░, рдкреИрд░рд╛рдореАрдЯрд░ r
рдХреНрд▓рд╛рдЗрдВрдЯ рд╕реЗ рдкреНрд░рд╛рдкреНрдд HTTP рдЕрдиреБрд░реЛрдз рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИред рдпрд╣ рд╣реИ рдХрд┐ рд╣рдо рд╡реЗрдм рдмреНрд░рд╛рдЙрдЬрд╝рд░ рджреНрд╡рд╛рд░рд╛ рд╕рд░реНрд╡рд░ рдкрд░ рднреЗрдЬреЗ рдЧрдП рдбреЗрдЯрд╛ рддрдХ рдХреИрд╕реЗ рдкрд╣реБрдВрдЪрддреЗ рд╣реИрдВред рд╣рдо рдЗрд╕реЗ рдЕрднреА рддрдХ рдпрд╣рд╛рдВ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╣рдо рдмрд╛рдж рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдЬрд░реВрд░ рдХрд░реЗрдВрдЧреЗред
рдЕрдВрдд рдореЗрдВ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ http.ListenAndServe()
рд╡рд┐рдзрд┐ рд╣реИ, рдЬреЛ рдХрд┐ рдкреЛрд░реНрдЯ 3000 рдХреЛ рд╕рд░реНрд╡рд░ рдкрд░ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ рдпрджрд┐ рдкреЛрд░реНрдЯ рдкрд░реНрдпрд╛рд╡рд░рдг рджреНрд╡рд╛рд░рд╛ рд╕реЗрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрджрд┐ рдЖрдкрдХреЗ рдХрдВрдкреНрдпреВрдЯрд░ рдкрд░ 3000 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдПрдХ рдЕрд▓рдЧ рдкреЛрд░реНрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реНрд╡рддрдВрддреНрд░ рдорд╣рд╕реВрд╕ рдХрд░реЗрдВред
рдлрд┐рд░ рдЖрдкрдХреЗ рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦреЗ рдЧрдП рдХреЛрдб рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░реЗрдВ рдФрд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВ:
go run main.go
рдпрджрд┐ рдЖрдк рдЕрдкрдиреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдореЗрдВ http: // localhost: 3000 рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ "рд╣реИрд▓реЛ рд╡рд░реНрд▓реНрдб!" рдкрд╛рда рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдЬрд╛рдПрдВ
рдЖрдЗрдП рджреЗрдЦреЗрдВ рдЧреЛ рдореЗрдВ рдЯреЗрдВрдкрд▓реЗрдЯрд┐рдВрдЧ рдХреА рдореВрд▓ рдмрд╛рддреЗрдВред рдпрджрд┐ рдЖрдк рдЕрдиреНрдп рднрд╛рд╖рд╛рдУрдВ рдХреЗ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рд╕реЗ рдкрд░рд┐рдЪрд┐рдд рд╣реИрдВ, рддреЛ рдЗрд╕реЗ рд╕рдордЭрдирд╛ рдЖрд╕рд╛рди рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
рдЯреЗрдореНрдкрд▓реЗрдЯ рд╡рд┐рднрд┐рдиреНрди рд╕реНрдерд╛рдиреЛрдВ рдореЗрдВ рд╕рдорд╛рди рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд┐рдирд╛ рдорд╛рд░реНрдЧ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдЖрдкрдХреЗ рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЖрд╕рд╛рди рддрд░реАрдХрд╛ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рдиреЗрд╡рд┐рдЧреЗрд╢рди рдмрд╛рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдмрд┐рдирд╛ рдХреЛрдб рдХреА рдирдХрд▓ рдХрд┐рдП рд╕рд╛рдЗрдЯ рдХреЗ рд╕рднреА рдкреГрд╖реНрдареЛрдВ рдкрд░ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдореЗрдВ рдЕрдкрдиреЗ рд╡реЗрдм рдкреЗрдЬреЛрдВ рдореЗрдВ рдХреБрдЫ рдмреБрдирд┐рдпрд╛рджреА рддрд░реНрдХ рдЬреЛрдбрд╝рдиреЗ рдХрд╛ рднреА рдЕрд╡рд╕рд░ рдорд┐рд▓рддрд╛ рд╣реИред
рдЬрд╛рдУ рдЕрдкрдиреЗ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рджреЛ рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ: text/template
рдФрд░ html/template
ред рджреЛрдиреЛрдВ рдПрдХ рд╣реА рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐ HTML рдЖрдЙрдЯрдкреБрдЯ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП html/template
рдкреИрдХреЗрдЬ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬреЛ рдХреЛрдб рдЗрдВрдЬреЗрдХреНрд╢рди рдХреЗ рд╡рд┐рд░реБрджреНрдз рд╕реБрд░рдХреНрд╖рд┐рдд рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдпрд╣рд╛рдВ рдХрд░реЗрдВрдЧреЗред
рдЗрд╕ рдкреИрдХреЗрдЬ рдХреЛ рдЕрдкрдиреА main.go
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЖрдпрд╛рдд рдХрд░реЗрдВ рдФрд░ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
package main import ( "html/template" "net/http" "os" ) var tpl = template.Must(template.ParseFiles("index.html")) func indexHandler(w http.ResponseWriter, r *http.Request) { tpl.Execute(w, nil) } func main() { port := os.Getenv("PORT") if port == "" { port = "3000" } mux := http.NewServeMux() mux.HandleFunc("/", indexHandler) http.ListenAndServe(":"+port, mux) }
tpl
рдПрдХ рдкреИрдХреЗрдЬ рд╕реНрддрд░ рдЪрд░ рд╣реИ рдЬреЛ рдкреНрд░рджрд╛рди рдХреА рдЧрдИ рдлрд╝рд╛рдЗрд▓реЛрдВ рд╕реЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИред Template.ParseFiles рдХреЙрд▓ рд╣рдорд╛рд░реЗ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдбрд╛рдпрд░реЗрдХреНрдЯрд░реА рдХреА рдЬрдбрд╝ рдореЗрдВ index.html
рдлрд╝рд╛рдЗрд▓ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреА рд╡реИрдзрддрд╛ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддрд╛ рд╣реИред
рд╣рдо template.ParseFiles
рдХреЛ template.ParseFiles
рд▓рдкреЗрдЯрддреЗ рд╣реИрдВред рдХреЗрд╡рд▓ рдЗрд╕рд▓рд┐рдП рдХрд┐ рдЬрдм рддреНрд░реБрдЯрд┐ рд╣реЛрддреА рд╣реИ рддреЛ рдХреЛрдб рдЖрддрдВрдХ рдХрд╛ рдХрд╛рд░рдг рдмрдирддрд╛ рд╣реИред рддреНрд░реБрдЯрд┐ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рд╣рдо рдпрд╣рд╛рдВ рдШрдмрд░рд╛рддреЗ рд╣реИрдВ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдХреЛрдб рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд░рдЦрддрд╛ рд╣реИ рдЕрдЧрд░ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рдЕрд╡реИрдз рдЯреЗрдореНрдкрд▓реЗрдЯ рд╣реИред рдпрд╣ рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реИ рдЬрд┐рд╕реЗ рд╕рд░реНрд╡рд░ рдХреЛ рдкреБрдирдГ рдЖрд░рдВрдн рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдареАрдХ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред
indexHandler
рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ indexHandler
рд╣рдо рджреЛ рддрд░реНрдХ рдкреНрд░рджрд╛рди рдХрд░рдХреЗ рдкрд╣рд▓реЗ рдмрдирд╛рдП рдЧрдП рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рддреЗ рд╣реИрдВ: рдЬрд╣рд╛рдВ рд╣рдо рдЖрдЙрдЯрдкреБрдЯ рдФрд░ рдЙрд╕ рдбреЗрдЯрд╛ рдХреЛ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рд╣рдо рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рдкрд╛рд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред
рдЙрдкрд░реЛрдХреНрдд рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдо ResponseWriter
рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЛ рдЖрдЙрдЯрдкреБрдЯ рд▓рд┐рдЦрддреЗ рд╣реИрдВ рдФрд░, рдЪреВрдВрдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрдкрдиреЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рдкрд╛рд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдбреЗрдЯрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП nil
рдХреЛ рджреВрд╕рд░реЗ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
Ctrl-C рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдкрдиреЗ рдЯрд░реНрдорд┐рдирд▓ рдореЗрдВ рдЪрд▓ рд░рд╣реА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдмрдВрдж рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ go run main.go
рд╕рд╛рде рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВ, рдлрд┐рд░ рдЕрдкрдиреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рддрд╛рдЬрд╝рд╛ рдХрд░реЗрдВред рдЖрдкрдХреЛ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдП рдЧрдП рдкреЗрдЬ рдкрд░ "рдиреНрдпреВрдЬрд╝ рдРрдк рдбреЗрдореЛ" рдЯреЗрдХреНрд╕реНрдЯ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:

рдкреЗрдЬ рдкрд░ рдПрдХ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдмрд╛рд░ рдЬреЛрдбрд╝реЗрдВ
рдиреАрдЪреЗ рджрд┐рдЦрд╛рдП рдЕрдиреБрд╕рд╛рд░ рдЕрдкрдиреА index.html рдлрд╝рд╛рдЗрд▓ рдореЗрдВ <body>
рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдмрджрд▓реЗрдВ:
<main> <header> <a class="logo" href="/">News Demo</a> <form action="/search" method="GET"> <input autofocus class="search-input" value="" placeholder="Enter a news topic" type="search" name="q"> </form> <a href="https://github.com/freshman-tech/news" class="button github-button">View on Github</a> </header> </main>
рдлрд┐рд░ рд╕рд░реНрд╡рд░ рдХреЛ рд░рд┐рдмреВрдЯ рдХрд░реЗрдВ рдФрд░ рдЕрдкрдиреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рддрд╛рдЬрд╝рд╛ рдХрд░реЗрдВред рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рд╕рдорд╛рди рдХреБрдЫ рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:

рд╕реНрдерд┐рд░ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВ
рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдордиреЗ рдЬреЛ рдиреЗрд╡рд┐рдЧреЗрд╢рди рдмрд╛рд░ рдЬреЛрдбрд╝рд╛ рд╣реИ рдЙрд╕рдореЗрдВ рд╢реИрд▓рд┐рдпреЛрдВ рдирд╣реАрдВ рд╣реИ, рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрдиреНрд╣реЗрдВ рд╣рдорд╛рд░реЗ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝ рдХреЗ <head>
рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд┐рдпрд╛ рд╣реИред
рдРрд╕рд╛ рдЗрд╕рд▓рд┐рдП рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдкрде /
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрди рд╕рднреА рд░рд╛рд╕реНрддреЛрдВ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ рдЬреЛ рдЕрдиреНрдпрддреНрд░ рд╕рдВрд╕рд╛рдзрд┐рдд рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВред рдЗрд╕рд▓рд┐рдП, рдпрджрд┐ рдЖрдк http: // рд▓реЛрдХрд▓рд╣реЛрд╕реНрдЯ: 3000 / рдПрд╕реЗрдЯреНрд╕ / рд╕реНрдЯрд╛рдЗрд▓.рд╕реАрдПрд╕рдПрд╕ рдкрд░ рдЬрд╛рддреЗ рд╣реИрдВ , рддреЛ рдЖрдкрдХреЛ рдЕрднреА рднреА рд╕реАрдПрд╕рдПрд╕ рдлрд╛рдЗрд▓ рдХреЗ рдмрдЬрд╛рдп рдиреНрдпреВрдЬ рдбреЗрдореЛ рд╣реЛрдордкреЗрдЬ рдорд┐рд▓реЗрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рд░реВрдЯ /assets/style.css
рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдШреЛрд╖рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред
рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реА рд╕рднреА рд╕реНрдЯреИрдЯрд┐рдХ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд▓рд┐рдП рд╕реНрдкрд╖реНрдЯ рд╣реИрдВрдбрд▓рд░ рдШреЛрд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдЕрд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╣реИ рдФрд░ рдХреЛрдИ рдкреИрдорд╛рдирд╛ рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рд╣рдо рд╕рднреА рд╕реНрдерд┐рд░ рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреА рд╕реЗрд╡рд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реИрдВрдбрд▓рд░ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдкрд╣рд▓реА рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдлрд╝рд╛рдЗрд▓ рд╕рд░реНрд╡рд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдирд╛ рд╣реИ, рдЙрд╕ рдирд┐рд░реНрджреЗрд╢рд┐рдХрд╛ рдореЗрдВ рдЧреБрдЬрд░рдирд╛ рдЬрд┐рд╕рдореЗрдВ рд╣рдорд╛рд░реА рд╕рднреА рд╕реНрдерд┐рд░ рдлрд╛рдЗрд▓реЗрдВ рд╕реНрдерд┐рдд рд╣реИрдВ:
fs := http.FileServer(http.Dir("assets"))
рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рдЕрдкрдиреЗ рд░рд╛рдЙрдЯрд░ рдХреЛ рдЗрд╕ рдлрд╛рдЗрд▓ рд╕рд░реНрд╡рд░ рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ /assets/
рдкреНрд░реАрдлрд┐рдХреНрд╕ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рд╕рднреА рд░рд╛рд╕реНрддреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрддрд╛рдирд╛ рд╣реЛрдЧрд╛:
mux.Handle("/assets/", http.StripPrefix("/assets/", fs))
рдЕрдм рд╕рднреА рдПрдХ рд╕рд╛рде:
рд╕рд░реНрд╡рд░ рдХреЛ рд░реАрдмреВрдЯ рдХрд░реЗрдВ рдФрд░ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рд░рд┐рдлреНрд░реЗрд╢ рдХрд░реЗрдВред рдиреАрдЪреЗ рджреА рдЧрдИ рд╢реИрд▓рд┐рдпреЛрдВ рдХреЛ рдЪрд╛рд▓реВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП:

рд╣рдо рдПрдХ рдорд╛рд░реНрдЧ / рдЦреЛрдЬ рдмрдирд╛рддреЗ рд╣реИрдВ
рдЖрдЗрдП рдПрдХ рдорд╛рд░реНрдЧ рдмрдирд╛рдПрдВ рдЬреЛ рд╕рдорд╛рдЪрд╛рд░ рд▓реЗрдЦреЛрдВ рдХреЗ рд▓рд┐рдП рдЦреЛрдЬ рдкреНрд░рд╢реНрдиреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рддрд╛ рд╣реИред рд╣рдо рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдорд╛рдЪрд╛рд░ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдпрд╣рд╛рдВ рдореБрдлреНрдд рдПрдкреАрдЖрдИ рдХреБрдВрдЬреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрдВрдЬреАрдХрд░рдг рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ ред
рдпрд╣ рдорд╛рд░реНрдЧ рджреЛ рдХреНрд╡реЗрд░реА рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рдЕрдкреЗрдХреНрд╖рд╛ рдХрд░рддрд╛ рд╣реИ: q
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рдХреНрд╡реЗрд░реА рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП page
рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдпрд╣ page
рдкреИрд░рд╛рдореАрдЯрд░ рд╡реИрдХрд▓реНрдкрд┐рдХ рд╣реИред рдпрджрд┐ рдпрд╣ URL рдореЗрдВ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рд╣реИ, рддреЛ рд╣рдо рдмрд╕ рдпрд╣ рдорд╛рди рд▓реЗрддреЗ рд╣реИрдВ рдХрд┐ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рдкреГрд╖реНрда рд╕рдВрдЦреНрдпрд╛ "1" рдкрд░ рд╕реЗрдЯ рд╣реИред
indexHandler
рддрд╣рдд рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИрдВрдбрд▓рд░ рдХреЛ рдЕрдкрдиреА main.go
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ:
func searchHandler(w http.ResponseWriter, r *http.Request) { u, err := url.Parse(r.URL.String()) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Internal server error")) return } params := u.Query() searchKey := params.Get("q") page := params.Get("page") if page == "" { page = "1" } fmt.Println("Search Query is: ", searchKey) fmt.Println("Results page is: ", page) }
рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдЕрдиреБрд░реЛрдз URL рд╕реЗ q
рдФрд░ page
рдкреИрд░рд╛рдореАрдЯрд░ рдирд┐рдХрд╛рд▓рддрд╛ рд╣реИ рдФрд░ рдЯрд░реНрдорд┐рдирд▓ рдореЗрдВ рджреЛрдиреЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИред
рдлрд┐рд░ searchHandler
рдлрд╝рдВрдХреНрд╢рди рдХреЛ /search
рдкрде рд╣реИрдВрдбрд▓рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдкрдВрдЬреАрдХреГрдд рдХрд░реЗрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:
func main() { port := os.Getenv("PORT") if port == "" { port = "3000" } mux := http.NewServeMux() fs := http.FileServer(http.Dir("assets")) mux.Handle("/assets/", http.StripPrefix("/assets/", fs))
рдКрдкрд░ рд╕реЗ fmt
рдФрд░ net/url
рд╕рдВрдХреБрд▓ рдЖрдпрд╛рдд рдХрд░рдирд╛ рдпрд╛рдж рд░рдЦреЗрдВ:
import ( "fmt" "html/template" "net/http" "net/url" "os" )
рдЕрдм рд╕рд░реНрд╡рд░ рдХреЛ рдкреБрдирд░рд╛рд░рдВрдн рдХрд░реЗрдВ, рдЦреЛрдЬ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдХреНрд╡реЗрд░реА рджрд░реНрдЬ рдХрд░реЗрдВ рдФрд░ рдЯрд░реНрдорд┐рдирд▓ рдХреА рдЬрд╛рдВрдЪ рдХрд░реЗрдВред рдЖрдкрдХреЛ рдЯрд░реНрдорд┐рдирд▓ рдореЗрдВ рдЕрдкрдирд╛ рдЕрдиреБрд░реЛрдз рджреЗрдЦрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬреИрд╕рд╛ рдХрд┐ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:
рдПрдХ рдбреЗрдЯрд╛ рдореЙрдбрд▓ рдмрдирд╛рдПрдБ
рдЬрдм рд╣рдо News API/everything
рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдПрдХ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХреА рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ:
{ "status": "ok", "totalResults": 4661, "articles": [ { "source": { "id": null, "name": "Gizmodo.com" }, "author": "Jennings Brown", "title": "World's Dumbest Bitcoin Scammer Tries to Scam Bitcoin Educator, Gets Scammed in The Process", "description": "Ben Perrin is a Canadian cryptocurrency enthusiast and educator who hosts a bitcoin show on YouTube. This is immediately apparent after a quick a look at all his social media. Ten seconds of viewing on of his videos will show that he is knowledgeable about diтАж", "url": "https://gizmodo.com/worlds-dumbest-bitcoin-scammer-tries-to-scam-bitcoin-ed-1837032058", "urlToImage": "https://i.kinja-img.com/gawker-media/image/upload/s--uLIW_Oxp--/c_fill,fl_progressive,g_center,h_900,q_80,w_1600/s4us4gembzxlsjrkmnbi.png", "publishedAt": "2019-08-07T16:30:00Z", "content": "Ben Perrin is a Canadian cryptocurrency enthusiast and educator who hosts a bitcoin show on YouTube. This is immediately apparent after a quick a look at all his social media. Ten seconds of viewing on of his videos will show that he is knowledgeable about..." } ] }
рдЧреЛ рдореЗрдВ рдЗрд╕ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдПрдХ рд╕рдВрд░рдЪрдирд╛ рддреИрдпрд╛рд░ рдХрд░рдиреА рд╣реЛрдЧреА рдЬреЛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╢рд░реАрд░ рдХреЛ рдбрд┐рдХреЛрдб рдХрд░рддреЗ рд╕рдордп рдбреЗрдЯрд╛ рдХреЛ рджрд░реНрд╢рд╛рддреА рд╣реИред рдмреЗрд╢рдХ, рдЖрдк рдЗрд╕реЗ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдореИрдВ JSON-to-Go рд╡реЗрдмрд╕рд╛рдЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдкрд╕рдВрдж рдХрд░рддрд╛ рд╣реВрдВ, рдЬреЛ рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЖрд╕рд╛рди рдмрдирд╛рддрд╛ рд╣реИред рдпрд╣ рдПрдХ рдЧреЛ рд╕рдВрд░рдЪрдирд╛ (рдЯреИрдЧ рдХреЗ рд╕рд╛рде) рдЙрддреНрдкрдиреНрди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЗрд╕ JSON рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдЧрд╛ред
рдЖрдкрдХреЛ рдмрд╕ JSON рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЛ рдХреЙрдкреА рдХрд░рдирд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ JSON рдХреЗ рд╕рд╛рде рдЪрд┐рд╣реНрдирд┐рдд рдлрд╝реАрд▓реНрдб рдореЗрдВ рдкреЗрд╕реНрдЯ рдХрд░рдирд╛ рд╣реИ, рдлрд┐рд░ рдЖрдЙрдЯрдкреБрдЯ рдХреЙрдкреА рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рдЕрдкрдиреЗ рдХреЛрдб рдореЗрдВ рдкреЗрд╕реНрдЯ рдХрд░реЗрдВред рдпрд╣рд╛рдВ рд╣рдореЗрдВ рдЙрдкрд░реЛрдХреНрдд JSON рдСрдмреНрдЬреЗрдХреНрдЯ рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рдорд┐рд▓реЗрдЧрд╛:
type AutoGenerated struct { Status string `json:"status"` TotalResults int `json:"totalResults"` Articles []struct { Source struct { ID interface{} `json:"id"` Name string `json:"name"` } `json:"source"` Author string `json:"author"` Title string `json:"title"` Description string `json:"description"` URL string `json:"url"` URLToImage string `json:"urlToImage"` PublishedAt time.Time `json:"publishedAt"` Content string `json:"content"` } `json:"articles"` }

рдореИрдВрдиреЗ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдврд╛рдВрдЪреЗ рдореЗрдВ Articles
рдЯреБрдХрдбрд╝реЗ рдХреЛ рдЕрд▓рдЧ рдХрд░рдХреЗ рдФрд░ рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдирд╛рдо рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдХреЗ AutoGenerated
рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдХрдИ рдмрджрд▓рд╛рд╡ рдХрд┐рдП рд╣реИрдВред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд main.go
рдЪрд░ рдШреЛрд╖рдгрд╛ main.go
рдореЗрдВ main.go
рдФрд░ рдЕрдкрдиреЗ рдЖрдпрд╛рдд рдореЗрдВ time
рдкреИрдХреЗрдЬ рдЬреЛрдбрд╝реЗрдВ:
type Source struct { ID interface{} `json:"id"` Name string `json:"name"` } type Article struct { Source Source `json:"source"` Author string `json:"author"` Title string `json:"title"` Description string `json:"description"` URL string `json:"url"` URLToImage string `json:"urlToImage"` PublishedAt time.Time `json:"publishedAt"` Content string `json:"content"` } type Results struct { Status string `json:"status"` TotalResults int `json:"totalResults"` Articles []Article `json:"articles"` }
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ, рдЧреЛ рдХреЛ рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рд╕рднреА рдирд┐рд░реНрдпрд╛рддрд┐рдд рдлрд╝реАрд▓реНрдб рдПрдХ рдмрдбрд╝реЗ рдЕрдХреНрд╖рд░ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣ JSON рдлрд╝реАрд▓реНрдбреНрд╕ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреНрд░рдерд╛рдЧрдд рд╣реИ, рдЬреЛ CamelCase рдпрд╛ snake_case рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИ , рдЬреЛ рдХрд┐ рдмрдбрд╝реЗ рдЕрдХреНрд╖рд░ рд╕реЗ рд╢реБрд░реВ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред
рдЗрд╕рд▓рд┐рдП, рд╣рдо рд╕рдВрд░рдЪрдирд╛ рдлрд╝реАрд▓реНрдб рдЯреИрдЧ рдЬреИрд╕реЗ рдХрд┐ json:"id"
рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ JSON рдлрд╝реАрд▓реНрдб рдореЗрдВ рд╕рдВрд░рдЪрдирд╛ рдлрд╝реАрд▓реНрдб рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░рддреЗ рд╣реИрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдКрдкрд░ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдпрджрд┐ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рддреЛ рдпрд╣ рдЖрдкрдХреЛ рд╕рдВрд░рдЪрдирд╛ рдХреНрд╖реЗрддреНрд░ рдФрд░ рд╕рдВрдмрдВрдзрд┐рдд рдЬреЛрди рдХреНрд╖реЗрддреНрд░ рдХреЗ рд▓рд┐рдП рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рдирд╛рдореЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рднреА рджреЗрддрд╛ рд╣реИред
рдЕрдВрдд рдореЗрдВ, рдЖрдЗрдП рдкреНрд░рддреНрдпреЗрдХ рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рдкреНрд░рдХрд╛рд░ рдХреА рд╕рдВрд░рдЪрдирд╛ рдмрдирд╛рдПрдВред рдореБрдЦреНрдп рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ Results
рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдиреАрдЪреЗ рдЗрд╕реЗ рдЬреЛрдбрд╝реЗрдВ:
type Search struct { SearchKey string NextPage int TotalPages int Results Results }
рдпрд╣ рд╕рдВрд░рдЪрдирд╛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдИ рдЧрдИ рдкреНрд░рддреНрдпреЗрдХ рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддреА рд╣реИред SearchKey
рд╕реНрд╡рдпрдВ рдХреНрд╡реЗрд░реА рд╣реИ, NextPage
рдлрд╝реАрд▓реНрдб NextPage
рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИ, TotalPages
- рдХреНрд╡реЗрд░реА рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рдХреБрд▓ рдкреГрд╖реНрда рдФрд░ Results
- рдХреНрд╡реЗрд░реА рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рд╡рд░реНрддрдорд╛рди рдкреГрд╖реНрдаред
рд╕рдорд╛рдЪрд╛рд░ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬреЗрдВ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗрдВ
рдЕрдм рдЬрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣рдорд╛рд░реЗ рдЖрд╡реЗрджрди рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛ рдореЙрдбрд▓ рд╣реИ, рддреЛ рдЪрд▓реЗрдВ рдЬрд╛рд░реА рд░рдЦреЗрдВ рдФрд░ рд╕рдорд╛рдЪрд╛рд░ рдПрдкреАрдЖрдИ рд╕реЗ рдЕрдиреБрд░реЛрдз рдХрд░реЗрдВ, рдФрд░ рдлрд┐рд░ рдкреГрд╖реНрда рдкрд░ рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╕реНрддреБрдд рдХрд░реЗрдВред
рдЪреВрдВрдХрд┐ рд╕рдорд╛рдЪрд╛рд░ рдПрдкреАрдЖрдИ рдХреЗ рд▓рд┐рдП рдПрдкреАрдЖрдИ рдХреБрдВрдЬреА рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдХреЛрдб рдореЗрдВ рд╣рд╛рд░реНрдб рдХреЛрдбрд┐рдВрдЧ рдХреЗ рдмрд┐рдирд╛ рдЗрд╕реЗ рдЕрдкрдиреЗ рдЖрд╡реЗрджрди рдореЗрдВ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рддрд░реАрдХрд╛ рдЦреЛрдЬрдирд╛ рд╣реЛрдЧрд╛ред рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╣реИ, рд▓реЗрдХрд┐рди рдореИрдВрдиреЗ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдЭрдВрдбреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рдЬрд╛рдУ рдПрдХ flag
рдкреИрдХреЗрдЬ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдХрдорд╛рдВрдб рд▓рд╛рдЗрди рдХреЗ рдЭрдВрдбреЗ рдХреЗ рдмреБрдирд┐рдпрд╛рджреА рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдпрд╣реА рд╡рд╣ рд╣реИ рдЬреЛ рд╣рдо рдпрд╣рд╛рдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ apiKey
рд╡реИрд░рд┐рдПрдмрд▓ рдХреЗ рддрд╣рдд рдПрдХ рдирдпрд╛ apiKey
рд╡реЗрд░рд┐рдПрдмрд▓ рдШреЛрд╖рд┐рдд рдХрд░реЗрдВ:
var apiKey *string
рдлрд┐рд░ рдЗрд╕реЗ рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░ рд╕реЗ main
рдХрд╛рд░реНрдп рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
func main() { apiKey = flag.String("apikey", "", "Newsapi.org access key") flag.Parse() if *apiKey == "" { log.Fatal("apiKey must be set") }
рдпрд╣рд╛рдВ рд╣рдо рдзреНрд╡рдЬ рдХрд╣рддреЗ рд╣реИрдВред рд╕реНрдЯреНрд░рд┐рдВрдЧ flag.String()
рд╡рд┐рдзрд┐, рдЬреЛ рд╣рдореЗрдВ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рдзреНрд╡рдЬ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреА рд╣реИред рдЗрд╕ рдкрджреНрдзрддрд┐ рдХрд╛ рдкрд╣рд▓рд╛ рддрд░реНрдХ рдзреНрд╡рдЬ рдирд╛рдо рд╣реИ, рджреВрд╕рд░рд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рд╣реИ, рдФрд░ рддреАрд╕рд░рд╛ рдЙрдкрдпреЛрдЧ рд╡рд┐рд╡рд░рдг рд╣реИред
рд╕рднреА рдЭрдВрдбреЗ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдкрдХреЛ рдзреНрд╡рдЬ рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред flag.Parse()
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЙрдиреНрд╣реЗрдВ flag.Parse()
рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдЕрдВрдд рдореЗрдВ, рдЪреВрдВрдХрд┐ apikey
рдЗрд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЖрд╡рд╢реНрдпрдХ рдШрдЯрдХ рд╣реИ, рд╣рдо рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рдпрджрд┐ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдлреНрд▓реИрдЧ рдХреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдХреЗ рджреМрд░рд╛рди рд╕реЗрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рддреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреНрд░реИрд╢ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред
рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдЖрдк рдЕрдкрдиреЗ рдЖрдпрд╛рдд рдореЗрдВ flag
рдкреИрдХреЗрдЬ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ, рдлрд┐рд░ рд╕рд░реНрд╡рд░ рдХреЛ рдкреБрдирд░рд╛рд░рдВрдн рдХрд░реЗрдВ рдФрд░ рдЖрд╡рд╢реНрдпрдХ apikey
рдзреНрд╡рдЬ рдХреЛ рдкрд╛рд╕ рдХрд░реЗрдВ, рдЬреИрд╕рд╛ рдХрд┐ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:
go run main.go -apikey=<your newsapi access key>
рдЕрдЧрд▓рд╛, рдЖрдЗрдП searchHandler
рдЬрд╛рд░реА рд░рдЦреЗрдВ рдФрд░ рдЕрдкрдбреЗрдЯ searchHandler
рддрд╛рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рдЦреЛрдЬ рдХреНрд╡реЗрд░реА newsapi.org рдкрд░ рднреЗрдЬреА рдЬрд╛рдП рдФрд░ рдкрд░рд┐рдгрд╛рдо рд╣рдорд╛рд░реЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрдВред
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЙрд▓ рдХреЗ рд╕рд╛рде рджреЛ рдХреЙрд▓ рдХреЛ fmt.Println()
рдореЗрдердб рдореЗрдВ рдЦреЛрдЬреЗрдВред
func searchHandler(w http.ResponseWriter, r *http.Request) {
рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо Search
рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдПрдХ рдирдпрд╛ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ SearchKey
рдЕрдиреБрд░реЛрдз рдореЗрдВ URL рдкреИрд░рд╛рдореАрдЯрд░ q
рдХреЗ рдорд╛рди рдореЗрдВ SearchKey
рдлрд╝реАрд▓реНрдб рдХрд╛ рдорд╛рди рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред
рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо page
рдЪрд░ рдХреЛ рдкреВрд░реНрдгрд╛рдВрдХ рдореЗрдВ рдмрджрд▓рддреЗ рд╣реИрдВ рдФрд░ рдкрд░рд┐рдгрд╛рдо рдХреЛ search
рдЪрд░ рдХреЗ NextPage
рдлрд╝реАрд▓реНрдб рдореЗрдВ рдЕрд╕рд╛рдЗрди рдХрд░рддреЗ рд╣реИрдВред рддрдм рд╣рдо pageSize
рд╡реИрд░рд┐рдПрдмрд▓ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЙрд╕рдХрд╛ рдорд╛рди 20 рдкрд░ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ pageSize
рд╡реИрд░рд┐рдПрдмрд▓ рдЙрди рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ, pageSize
рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рд╕рдорд╛рдЪрд╛рд░ рдПрдкреАрдЖрдИ рд╡рд╛рдкрд╕ рдЖрдПрдЧрд╛ред рдпрд╣ рдорд╛рди 0 рд╕реЗ 100 рддрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рдлрд┐рд░ рд╣рдо fmt.Sprintf()
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ GET рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╣реИрдВред рдпрджрд┐ рд╕рдорд╛рдЪрд╛рд░ рдПрдкреАрдЖрдИ рдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ 200 рдареАрдХ рдирд╣реАрдВ рд╣реИ, рддреЛ рд╣рдо рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рд╕рд░реНрд╡рд░ рддреНрд░реБрдЯрд┐ рд▓реМрдЯрд╛рдПрдВрдЧреЗред рдЕрдиреНрдпрдерд╛, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд┐рдХрд╛рдп рдЦреЛрдЬ рдореЗрдВ рдкрд╛рд░реНрд╕ рдХрд┐рдпрд╛ search.Results
ред
рддрдм рд╣рдо TotalResults
рдлрд╝реАрд▓реНрдб рдХреЛ pageSize
рджреНрд╡рд╛рд░рд╛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдХреЗ рдкреГрд╖реНрдареЛрдВ рдХреА рдХреБрд▓ рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рдХреЛрдИ рдХреНрд╡реЗрд░реА 100 рдкрд░рд┐рдгрд╛рдо рджреЗрддрд╛ рд╣реИ, рдФрд░ рд╣рдо рдПрдХ рдмрд╛рд░ рдореЗрдВ рдХреЗрд╡рд▓ 20 рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдЙрд╕ рдХреНрд╡реЗрд░реА рдХреЗ рд╕рднреА 100 рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╛рдВрдЪ рдкреГрд╖реНрдареЛрдВ рдХреЛ рд╕реНрдХреНрд░реЙрд▓ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдЕрдкрдиреЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рдкреНрд░рд╕реНрддреБрдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдбреЗрдЯрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд░реВрдк рдореЗрдВ search
рдЪрд░ рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ search
ред рдпрд╣ рд╣рдореЗрдВ рд╣рдорд╛рд░реЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ JSON рдСрдмреНрдЬреЗрдХреНрдЯ рд╕реЗ рдбреЗрдЯрд╛ рдПрдХреНрд╕реЗрд╕ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦреЗрдВрдЧреЗред
index.html
рдкрд░ рдЬрд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдиреАрдЪреЗ рджрд┐рдЦрд╛рдП рдЕрдиреБрд╕рд╛рд░ рдЕрдкрдиреЗ рдЖрдпрд╛рдд рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдирд╛ рди рднреВрд▓реЗрдВ:
import ( "encoding/json" "flag" "fmt" "html/template" "log" "math" "net/http" "net/url" "os" "strconv" "time" )
рдЪрд▓рд┐рдП рдЬрд╛рд░реА рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкреГрд╖реНрда рдкрд░ рдкрд░рд┐рдгрд╛рдо рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдЗрд╕реЗ <header>
рддрд╣рдд рдЬреЛрдбрд╝реЗрдВ:
<section class="container"> <ul class="search-results"> {{ range .Results.Articles }} <li class="news-article"> <div> <a target="_blank" rel="noreferrer noopener" href="{{.URL}}"> <h3 class="title">{{.Title }}</h3> </a> <p class="description">{{ .Description }}</p> <div class="metadata"> <p class="source">{{ .Source.Name }}</p> <time class="published-date">{{ .PublishedAt }}</time> </div> </div> <img class="article-image" src="{{ .URLToImage }}"> </li> {{ end }} </ul> </section>
рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рд╕рдВрд░рдЪрдирд╛ рдХреНрд╖реЗрддреНрд░ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдмрд┐рдВрджреБ рдСрдкрд░реЗрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рдСрдкрд░реЗрдЯрд░ рдПрдХ рд╕рдВрд░рдЪрдирд╛ рдСрдмреНрдЬреЗрдХреНрдЯ (рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, search
) рдХреЛ рд╕рдВрджрд░реНрднрд┐рдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдлрд┐рд░ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рдЕрдВрджрд░ рд╣рдо рдХреЗрд╡рд▓ рдлрд╝реАрд▓реНрдб рдирд╛рдо ( {{.Results}}
) рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░рддреЗ рд╣реИрдВред
range
рдмреНрд▓реЙрдХ рд╣рдореЗрдВ рдЧреЛ рдореЗрдВ рдПрдХ рд╕реНрд▓рд╛рдЗрд╕ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддрд┐ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдФрд░ рд╕реНрд▓рд╛рдЗрд╕ рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреЗ рд▓рд┐рдП рдХреБрдЫ HTML рдЖрдЙрдЯрдкреБрдЯ рдХрд░рддрд╛ рд╣реИред рдпрд╣рд╛рдБ, рд╣рдо Articles
рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдирд┐рд╣рд┐рдд Article
рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЗ рдЯреБрдХрдбрд╝реЗ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рдкрд░ HTML рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддреЗ рд╣реИрдВред
рд╕рд░реНрд╡рд░ рдХреЛ рд░рд┐рдмреВрдЯ рдХрд░реЗрдВ, рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рддрд╛рдЬрд╝рд╛ рдХрд░реЗрдВ рдФрд░ рдПрдХ рд▓реЛрдХрдкреНрд░рд┐рдп рд╡рд┐рд╖рдп рдкрд░ рд╕рдорд╛рдЪрд╛рд░ рдЦреЛрдЬреЗрдВред рдЖрдкрдХреЛ рдкреНрд░рддрд┐ рдкреГрд╖реНрда 20 рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдорд┐рд▓рдиреА рдЪрд╛рд╣рд┐рдП, рдЬреИрд╕рд╛ рдХрд┐ рдиреАрдЪреЗ рд╕реНрдХреНрд░реАрдирд╢реЙрдЯ рдореЗрдВ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЬрдм рдкреГрд╖реНрда рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рд╕рд╛рде рддрд╛рдЬрд╝рд╛ рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ рддреЛ рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рдЗрдирдкреБрдЯ рд╕реЗ рдЧрд╛рдпрдм рд╣реЛ рдЬрд╛рддреА рд╣реИред рдЖрджрд░реНрд╢ рд░реВрдк рд╕реЗ, рдХреНрд╡реЗрд░реА рддрдм рддрдХ рд░рдЦреА рдЬрд╛рдиреА рдЪрд╛рд╣рд┐рдП рдЬрдм рддрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдПрдХ рдирдИ рдЦреЛрдЬ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, Google рдЦреЛрдЬ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рд╣рдо рдЕрдкрдиреА index.html
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ input
рдЯреИрдЧ рдХреЗ value
рд╡рд┐рд╢реЗрд╖рддрд╛ рдХреЛ рдирд┐рдореНрди рдкреНрд░рдХрд╛рд░ рд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ рдареАрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
<input autofocus class="search-input" value="{{ .SearchKey }}" placeholder="Enter a news topic" type="search" name="q">
рдЕрдкрдиреЗ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЛ рдкреБрдирд░рд╛рд░рдВрдн рдХрд░реЗрдВ рдФрд░ рдПрдХ рдирдИ рдЦреЛрдЬ рдХрд░реЗрдВред рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рдХреЛ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдП рдЕрдиреБрд╕рд╛рд░ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛:

рдпрджрд┐ рдЖрдк рдкреНрд░рддреНрдпреЗрдХ рд▓реЗрдЦ рдореЗрдВ рддрд╛рд░реАрдЦ рдХреЛ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдпрд╣ рдЦрд░рд╛рдм рдкрдардиреАрдп рд╣реИред рд╡рд░реНрддрдорд╛рди рдЖрдЙрдЯрдкреБрдЯ рджрд┐рдЦрд╛рддрд╛ рд╣реИ рдХрд┐ рд╕рдорд╛рдЪрд╛рд░ рдПрдкреАрдЖрдИ рд▓реЗрдЦ рдХреА рдкреНрд░рдХрд╛рд╢рди рддрд┐рдерд┐ рдХреИрд╕реЗ рд▓реМрдЯрд╛рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдо рдЗрд╕реЗ рдЖрд╕рд╛рдиреА рд╕реЗ Article
рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдПрдХ рд╡рд┐рдзрд┐ рдЬреЛрдбрд╝рдХрд░ рдФрд░ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рджрд┐рдирд╛рдВрдХ рдХреЛ рдкреНрд░рд╛рд░реВрдкрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред
рдЪрд▓рд┐рдП main.go
рдореЗрдВ Article
рд╕реНрдЯреНрд░рдХреНрдЪрд░ рдХреЗ рдареАрдХ рдиреАрдЪреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб main.go
:
func (a *Article) FormatPublishedDate() string { year, month, day := a.PublishedAt.Date() return fmt.Sprintf("%v %d, %d", month, day, year) }
рдпрд╣рд╛рдВ, рдПрдХ рдирдпрд╛ FormatPublishedDate
рд╡рд┐рдзрд┐ Article
рд╕рдВрд░рдЪрдирд╛ рдореЗрдВ рдмрдирд╛рдИ рдЧрдИ рд╣реИ, рдФрд░ рдпрд╣ рд╡рд┐рдзрд┐ Article
рдореЗрдВ FormatPublishedDate
рдлрд╝реАрд▓реНрдб рдХреЛ рдкреНрд░рд╛рд░реВрдкрд┐рдд рдХрд░рддреА рд╣реИ рдФрд░ рдирд┐рдореНрди рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд▓реМрдЯрд╛рддреА рд╣реИ: 10 2009
ред
рдЕрдкрдиреЗ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рдЗрд╕ рдирдИ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЕрдкрдиреАред .FormatPublishedDate
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ .PublishedAt
рд╕рд╛рдеред рдлрд┐рд░ рд╕рд░реНрд╡рд░ рдХреЛ рдкреБрдирд░рд╛рд░рдВрдн рдХрд░реЗрдВ рдФрд░ рдкрд┐рдЫрд▓реА рдЦреЛрдЬ рдХреНрд╡реЗрд░реА рдХреЛ рджреЛрд╣рд░рд╛рдПрдВред рдпрд╣ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд╕реНрд╡рд░реВрдкрд┐рдд рд╕рдордп рдХреЗ рд╕рд╛рде рдЖрдЙрдЯрдкреБрдЯ рдХрд░реЗрдЧрд╛, рдЬреИрд╕рд╛ рдХрд┐ рдиреАрдЪреЗ рджрд┐рдЦрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ:

рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рдХреБрд▓ рд╕рдВрдЦреНрдпрд╛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдВред
рдЖрдЗрдП рдкреГрд╖реНрда рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреА рдХреБрд▓ рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рдХреЗ рд╣рдорд╛рд░реЗ рд╕рдорд╛рдЪрд╛рд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░реЗрдВ, рдФрд░ рдлрд┐рд░ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдХреНрд╡реЗрд░реА рдХреЗ рд▓рд┐рдП рдХреЛрдИ рдкрд░рд┐рдгрд╛рдо рдирд╣реАрдВ рдорд┐рд▓рдиреЗ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдПрдХ рд╕рдВрджреЗрд╢ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдВред
рдЖрдкрдХреЛ рдмрд╕ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЛрдб рдХреЛ .container
рдмрдЪреНрдЪреЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЬреЛрдбрд╝рдирд╛ рд╣реИ, рдЕрдкрдиреА index.html
рдлрд╝рд╛рдЗрд▓ рдореЗрдВ .search-results
рддрддреНрд╡ рдХреЗ рдареАрдХ рдКрдкрд░:
<div class="result-count"> {{ if (gt .Results.TotalResults 0)}} <p>About <strong>{{ .Results.TotalResults }}</strong> results were found.</p> {{ else if (ne .SearchKey "") and (eq .Results.TotalResults 0) }} <p>No results found for your query: <strong>{{ .SearchKey }}</strong>.</p> {{ end }} </div>
Go , . gt
, , TotalResults
Results
. , .
, SearchKey
( (ne .SearchKey "")
) TotalResults
( (eq .Results.TotalResults 0)
), ┬лNo results found┬╗.
, . ┬лNo results found┬╗.

. , :

20 , , .
Next , . , , Search
main.go
:
func (s *Search) IsLastPage() bool { return s.NextPage >= s.TotalPages }
, NextPage
, TotalPages
Search
. , NextPage
, . :
func searchHandler(w http.ResponseWriter, r *http.Request) {
, , . .search-results
index.html
.
<div class="pagination"> {{ if (ne .IsLastPage true) }} <a href="/search?q={{ .SearchKey }}&page={{ .NextPage }}" class="button next-page">Next</a> {{ end }} </div>
, Next .
, href
/search
q
, NextPage
page
.
Previous . , 1. , CurrentPage()
Search
, . IsLastPage
:
func (s *Search) CurrentPage() int { if s.NextPage == 1 { return s.NextPage } return s.NextPage - 1 }
NextPage - 1
, , NextPage
1. , 1 . :
func (s *Search) PreviousPage() int { return s.CurrentPage() - 1 }
, Previous , 1. .pagination
index.html
:
<div class="pagination"> {{ if (gt .NextPage 2) }} <a href="/search?q={{ .SearchKey }}&page={{ .PreviousPage }}" class="button previous-page">Previous</a> {{ end }} {{ if (ne .IsLastPage true) }} <a href="/search?q={{ .SearchKey }}&page={{ .NextPage }}" class="button next-page">Next</a> {{ end }} </div>
. , :
, , , , .
index.html
:
<div class="result-count"> {{ if (gt .Results.TotalResults 0)}} <p>About <strong>{{ .Results.TotalResults }}</strong> results were found. You are on page <strong>{{ .CurrentPage }}</strong> of <strong> {{ .TotalPages }}</strong>.</p> {{ else if (ne .SearchKey "") and (eq .Results.TotalResults 0) }} <p>No results found for your query: <strong>{{ .SearchKey }}</strong>.</p> {{ end }} </div>
, , .

Heroku
, , Heroku. , , . . freshman-news .
, Heroku . heroku login
, Heroku.
, git- . , git init
, , heroku git-. freshman-news
.
heroku git:remote -a freshman-news
Procfile ( touch Procfile
) :
web: bin/news-demo -apikey $NEWS_API_KEY
GitHub Go, , go.mod
, . , , .
module github.com/freshman-tech/news-demo go 1.12.9
Settings Heroku Reveal Config Vars . NEWS_API_KEY , .

, Heroku :
git add . git commit -m "Initial commit" git push heroku master
https://__.herokuapp.com , .
рдирд┐рд╖реНрдХрд░реНрд╖
News Go -. , Heroku.
, . - , , .
рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж!