Go2 рдХрд╛ рдЙрджреНрджреЗрд╢реНрдп рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рдУрд╡рд░рд╣реЗрдб рдХреЛ рдХрдо рдХрд░рдирд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдЖрдк рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдмреЗрд╣рддрд░ рд╕рд┐рдВрдЯреИрдХреНрд╕ рд╕реЗ рдмреЗрд╣рддрд░ рдХреНрдпрд╛ рд╣реИ?
рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рдВрднрд╛рд▓рдиреЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдореИрдВ рдирд╣реАрдВ рдХрд╣рддрд╛ рдХрд┐ "рдЕрдкрдиреА рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рдХреЛрдб рдХреЛ рд╣рдЯрд╛рдПрдВ", рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдореИрдВ рдЖрдкрдХреЗ рдХреЛрдб рдХреЛ рдмрджрд▓рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реВрдВ рддрд╛рдХрд┐ рдЖрдкрдХреЗ рдкрд╛рд╕ рд╕рдВрднрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдИ рддреНрд░реБрдЯрд┐рдпрд╛рдВ рди рд╣реЛрдВред
рдпрд╣ рд▓реЗрдЦ рдЬреЙрди рдУрд╕реНрдЯрд░рд╣реМрдЯ рдХреА рдкреБрд╕реНрддрдХ "
рд╕реЙрдлреНрдЯрд╡реЗрдпрд░ рдбрд┐рдЬрд╛рдЗрди рдХрд╛ рдПрдХ рджрд░реНрд╢рди " рдХреЗ "рдЕрд╕реНрддрд┐рддреНрд╡ рд╕реЗ рдмрд╛рд╣рд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ" рдХреЗ рдЕрдзреНрдпрд╛рдп рд╕реЗ рдкреНрд░реЗрд░рдгрд╛ рд▓реЗрддрд╛ рд╣реИред рдореИрдВ рдЙрдирдХреА рд╕рд▓рд╛рд╣ рдХреЛ рдЧреЛ рдкрд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реВрдВрдЧрд╛ред
рдкрд╣рд▓рд╛ рдЙрджрд╛рд╣рд░рдг
рдпрд╣рд╛рдБ рдПрдХ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд▓рд╛рдЗрдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рд╣реИ:
func CountLines(r io.Reader) (int, error) { var ( br = bufio.NewReader(r) lines int err error ) for { _, err = br.ReadString('\n') lines++ if err != nil { break } } if err != io.EOF { return 0, err } return lines, nil }
рд╣рдо bufio.Reader рдмрдирд╛рддреЗ рд╣реИрдВ, рдлрд┐рд░ рдПрдХ рдкрд╛рд╢ рдореЗрдВ рдмреИрдарддреЗ рд╣реИрдВ, ReadString рдкрджреНрдзрддрд┐ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рдХрд╛рдЙрдВрдЯрд░ рдХреЛ рдмрдврд╝рд╛рддреЗ рд╣реИрдВ рдЬрдм рддрдХ рд╣рдо рдлрд╝рд╛рдЗрд▓ рдХреЗ рдЕрдВрдд рддрдХ рдирд╣реАрдВ рдкрд╣реБрдВрдЪрддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдкрдврд╝реА рдЧрдИ рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рд╡рд╛рдкрд╕ рдХрд░рддреЗ рд╣реИрдВред рдпрд╣ рд╡рд╣ рдХреЛрдб рд╣реИ рдЬрд┐рд╕реЗ рд╣рдо рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рддреЗ рдереЗ, рдЗрд╕рдХреЗ рдмрдЬрд╛рдп CountLines рддреНрд░реБрдЯрд┐ рд╕реЗ рдЬрдЯрд┐рд▓ рд╣реИред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣ рдХрд╛ рдПрдХ рдЕрдЬреАрдм рдирд┐рд░реНрдорд╛рдг рд╣реИ:
_, err = br.ReadString('\n') lines++ if err != nil { break }
рд╣рдо рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд▓рд╛рдЗрдиреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдмрдврд╝рд╛рддреЗ рд╣реИрдВ - рдпрд╣ рдЕрдЬреАрдм рд▓рдЧрддрд╛ рд╣реИред рд╣рдореЗрдВ рдЗрд╕реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд▓рд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП рдХреНрдпреЛрдВрдХрд┐ рд░реАрдбрд▓рд╛рдЗрди рдПрдХ рддреНрд░реБрдЯрд┐ рд╡рд╛рдкрд╕ рдХрд░ рджреЗрдЧрд╛ рдпрджрд┐ рдпрд╣ рдлрд╝рд╛рдЗрд▓ рдХреЗ рдЕрдВрдд рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддрд╛ рд╣реИ - io.EOF - рдиреНрдпреВрд▓рд╛рдЗрди рд╡рд░реНрдг рдХреЛ рджрдмрд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗред рдРрд╕рд╛ рддрдм рднреА рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдЬрдм рдХреЛрдИ рдирдИ рд░реЗрдЦрд╛ рди рд╣реЛред
рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдкрдВрдХреНрддрд┐рдпреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдмрдврд╝рд╛рдиреЗ рдХреЗ рд▓рд┐рдП рддрд░реНрдХ рдХреЛ рдкреБрдирд░реНрдЧрдард┐рдд рдХрд░реЗрдВрдЧреЗ, рдФрд░ рдлрд┐рд░ рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдХреНрдпрд╛ рд╣рдореЗрдВ рд▓реВрдк рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ (рдпрд╣ рддрд░реНрдХ рдЕрднреА рднреА рд╕рд╣реА рдирд╣реАрдВ рд╣реИ, рдХреНрдпрд╛ рдЖрдк рдПрдХ рддреНрд░реБрдЯрд┐ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВ?)ред
рд▓реЗрдХрд┐рди рд╣рдордиреЗ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рдЬрд╛рдБрдЪ рдкреВрд░реА рдирд╣реАрдВ рдХреА рд╣реИред ReadString рдлрд╝рд╛рдЗрд▓ рдХреЗ рдЕрдВрдд рддрдХ рдкрд╣реБрдБрдЪрдиреЗ рдкрд░ io.EOF рдХреЛ рд▓реМрдЯрд╛ рджреЗрдЧрд╛ред рдпрд╣ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╣реИ, ReadString рдХреЛ рд░реЛрдХрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рд╕реА рддрд░рд╣ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдкрдврд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдХреБрдЫ рдирд╣реАрдВ рд╣реИред рдЗрд╕рд▓рд┐рдП, CountLine рдХреЗ рдХреЙрд▓рд░ рдореЗрдВ рддреНрд░реБрдЯрд┐ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ io.EOF рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рдорд┐рд▓реА рд╣реИ, рдФрд░ рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдЙрд╕реЗ рдХреЙрд▓рд░ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рджреЗрдВ, рдЕрдиреНрдпрдерд╛ рд╣рдо рд╕рдм рдХреБрдЫ рдареАрдХ рд╣реЛрдиреЗ рдкрд░ рд╢реВрдиреНрдп рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдПрдВрдЧреЗред рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдХреА рдЕрдВрддрд┐рдо рдкрдВрдХреНрддрд┐ рдЖрд╕рд╛рди рдирд╣реАрдВ рд╣реИ
return lines, err
рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд░рд╕ рдХреЙрдХреНрд╕ рдХреЗ рдЕрд╡рд▓реЛрдХрди рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг рд╣реИ рдХрд┐
рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рд╕реЗ рдлрд╝рдВрдХреНрд╢рди рдЕрдзрд┐рдХ рдХрдард┐рди рд╣реЛ рд╕рдХрддрд╛ рд╣реИ ред рдЖрдЗрдП рдмреЗрд╣рддрд░ рд╕рдВрд╕реНрдХрд░рдг рджреЗрдЦреЗрдВред
func CountLines(r io.Reader) (int, error) { sc := bufio.NewScanner(r) lines := 0 for sc.Scan() { lines++ } return lines, sc.Err() }
рдпрд╣ bufio.Reader рд╕реЗ bufio.Scanner рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╕реЗ рд╕рдВрд╕реНрдХрд░рдг рдореЗрдВ рд╕реБрдзрд╛рд░ рд╣реБрдЖ рд╣реИред рд╣реБрдб рдХреЗ рдЕрдВрддрд░реНрдЧрдд, bufio.Scanner bufio.Reader рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ, рдПрдХ рдПрдмреНрд╕реНрдЯреНрд░реЗрдХреНрд╢рди рд▓реЗрдпрд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рд╕реЗ рдПрд░рд░ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдХреЛ рд╣рдЯрд╛рдиреЗ рдореЗрдВ рдорджрдж рдорд┐рд▓рддреА рд╣реИ, рдЬреЛ рдХрд╛рдЙрдВрдЯрд▓рд╛рдЗрди рдХреЗ рд╣рдорд╛рд░реЗ рдкрд┐рдЫрд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдХреЗ рдХрд╛рдо рдореЗрдВ рдмрд╛рдзрд╛ рдбрд╛рд▓рддреА рд╣реИ (bufio.Scanner рдХрд┐рд╕реА рднреА рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рд╕реНрдХреИрди рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдпрд╣ рдирдИ рд▓рд╛рдЗрдиреЛрдВ рдХреА рдЦреЛрдЬ рдХрд░рддрд╛ рд╣реИ)ред
Sc.Scan () рд╡рд┐рдзрд┐ рд╕рд╣реА рд╣реЛ рдЬрд╛рддреА рд╣реИ рдпрджрд┐ рд╕реНрдХреИрдирд░ рдиреЗ рдкрд╛рда рдХреА рдПрдХ рдкрдВрдХреНрддрд┐ рдкрд╛рдИ рдФрд░ рдХреЛрдИ рддреНрд░реБрдЯрд┐ рдирд╣реАрдВ рдорд┐рд▓реАред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд▓реВрдк рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ рд╢рд░реАрд░ рдХреЛ рдХреЗрд╡рд▓ рддрднреА рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛ рдЬрдм рд╕реНрдХреИрдирд░ рдмрдлрд░ рдореЗрдВ рдкрд╛рда рдХреА рдПрдХ рдкрдВрдХреНрддрд┐ рд╣реЛред рдЗрд╕рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рд░реЗрдбрд▓рд╛рдЗрди рдХрд╛рдЙрдВрдЯрд▓рд╛рдЗрди рдорд╛рдорд▓реЗ рдХреЛ рд╕рд╣реА рдврдВрдЧ рд╕реЗ рд╣реИрдВрдбрд▓ рдХрд░рддреЗ рд╣реИрдВ рдЬрдм рдХреЛрдИ рдЕрдиреБрдЧрд╛рдореА рдиреНрдпреВрд▓рд╛рдЗрди рд╡рд░реНрдг рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рд╕рд╛рде рд╣реА рдЕрдм рдорд╛рдорд▓рд╛ рдЬрдм рдлрд╝рд╛рдЗрд▓ рдЦрд╛рд▓реА рд╣реИ рддреЛ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рд╕рдВрднрд╛рд▓рд╛ рдЧрдпрд╛ рд╣реИред
рджреВрд╕рд░реЗ, рдЪреВрдВрдХрд┐ scред рдХреЛрдИ рддреНрд░реБрдЯрд┐ рд╣реЛрдиреЗ рдкрд░ рдЧрд▓рдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдлрд╝рд╛рдЗрд▓ рдХреЗ рдЕрдВрдд рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдпрд╛ рддреНрд░реБрдЯрд┐ рд╣реЛрдиреЗ рдкрд░ рд▓реВрдк рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░рд╛ рдЕрдВрдд рд╣реЛ рдЬрд╛рдПрдЧрд╛ред рдкреНрд░рдХрд╛рд░ bufio.Scanner рдкрд╣рд▓реА рддреНрд░реБрдЯрд┐ рдХрд╛ рдкрддрд╛ рдЪрд▓рд╛ рддреНрд░реБрдЯрд┐ рдХреЛ рдпрд╛рдж рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╣рдо sc.Err () рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд▓реВрдк рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреЗ рдмрд╛рдж рдЗрд╕ рддреНрд░реБрдЯрд┐ рдХреЛ рдареАрдХ рдХрд░рддреЗ рд╣реИрдВред
рдЕрдВрдд рдореЗрдВ, Buffo.Scanner рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг io.EOF рдХрд╛ рдЦреНрдпрд╛рд▓ рд░рдЦрддрд╛ рд╣реИ рдФрд░ рдЕрдЧрд░ рдлрд╝рд╛рдЗрд▓ рдмрд┐рдирд╛ рдХрд┐рд╕реА рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддреА рд╣реИ, рддреЛ рдЗрд╕реЗ рд╢реВрдиреНрдп рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░ рджреЗрддрд╛ рд╣реИред
рджреВрд╕рд░рд╛ рдЙрджрд╛рд╣рд░рдг
рдореЗрд░рд╛ рджреВрд╕рд░рд╛ рдЙрджрд╛рд╣рд░рдг рд░реЛрдм рдкрд╛рдЗрдХреНрд╕ рдХреА
рддреНрд░реБрдЯрд┐рдпреЛрдВ рд╕реЗ рдкреНрд░реЗрд░рд┐рдд рд╣реИ рдЬреЛ
рдорд╛рди рдмреНрд▓реЙрдЧ рдкреЛрд╕реНрдЯ рд╣реИрдВред
рдлрд╝рд╛рдЗрд▓реЗрдВ рдЦреЛрд▓рдиреЗ, рд▓рд┐рдЦрдиреЗ рдФрд░ рдмрдВрдж рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп, рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ, рд▓реЗрдХрд┐рди рдмрд╣реБрдд рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реА рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╕рдВрдЪрд╛рд▓рди ioutil.ReadFile рдФрд░ ioutil.WriteFile рдЬреИрд╕реЗ рд╕рд╣рд╛рдпрдХреЛрдВ рдореЗрдВ рд╕рдВрдкрдиреНрди рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдЬрдм рдирд┐рдореНрди-рд╕реНрддрд░ рдХреЗ рдиреЗрдЯрд╡рд░реНрдХ рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЕрдХреНрд╕рд░ I / O рдкреНрд░рд╛рдЗрдореЗрдЯрд┐рд╡реНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реАрдзреЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреА рдкреБрдирд░рд╛рд╡реГрддреНрддрд┐ рд╢реБрд░реВ рд╣реЛ рд╕рдХрддреА рд╣реИред HTTP / 1.1 рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдмрдирд╛рдиреЗ рд╡рд╛рд▓реЗ HTTP рд╕рд░реНрд╡рд░ рдХреЗ рдЗрд╕ рдЯреБрдХрдбрд╝реЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
type Header struct { Key, Value string } type Status struct { Code int Reason string } func WriteResponse(w io.Writer, st Status, headers []Header, body io.Reader) error { _, err := fmt.Fprintf(w, "HTTP/1.1 %d %s\r\n", st.Code, st.Reason) if err != nil { return err } for _, h := range headers { _, err := fmt.Fprintf(w, "%s: %s\r\n", h.Key, h.Value) if err != nil { return err } } if _, err := fmt.Fprint(w, "\r\n"); err != nil { return err } _, err = io.Copy(w, body) return err }
рдкрд╣рд▓реЗ рд╣рдо fmt.Fprintf рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рд╕реНрдерд┐рддрд┐ рдкрдЯреНрдЯреА рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рддреНрд░реБрдЯрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВред рдлрд┐рд░, рдкреНрд░рддреНрдпреЗрдХ рд╣реЗрдбрд░ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╣реЗрдбрд░ рдХреА рдХреБрдВрдЬреА рдФрд░ рдореВрд▓реНрдп рд░рд┐рдХреЙрд░реНрдб рдХрд░рддреЗ рд╣реИрдВ, рд╣рд░ рдмрд╛рд░ рддреНрд░реБрдЯрд┐ рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХрд░рддреЗ рд╣реИрдВред рдЕрдВрдд рдореЗрдВ, рд╣рдо рд╣реЗрдбрд░ рдЕрдиреБрднрд╛рдЧ рдХреЛ рдЕрддрд┐рд░рд┐рдХреНрдд \ r \ n рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ, рддреНрд░реБрдЯрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЧреНрд░рд╛рд╣рдХ рдХреЛ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдирд┐рдХрд╛рдп рдХреА рдирдХрд▓ рдХрд░рддреЗ рд╣реИрдВред рдЕрдВрдд рдореЗрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рд╣рдореЗрдВ io.Copy рд╕реЗ рддреНрд░реБрдЯрд┐ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рд╣рдореЗрдВ рдЗрд╕реЗ рджреЛ рд░рд┐рдЯрд░реНрди рдорд╛рдиреЛрдВ рдХреЗ рд╕рд╛рде рдлрд╝реЙрд░реНрдо рд╕реЗ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬреЛ io.Copy рд╕рд┐рдВрдЧрд▓ рд░рд┐рдЯрд░реНрди рд╡реИрд▓реНрдпреВ рдкрд░ рд▓рд┐рдЦрддрд╛ рд╣реИ рдЬреЛ рдХрд┐ WriteResponse рдЙрдореНрдореАрдж рдХрд░рддрд╛ рд╣реИред
рдпрд╣ рди рдХреЗрд╡рд▓ рдмрд╣реБрдд рджреЛрд╣рд░рд╛рд╡ рд╡рд╛рд▓рд╛ рдХрд╛рдо рд╣реИ, рдкреНрд░рддреНрдпреЗрдХ рдСрдкрд░реЗрд╢рди, рдЬреЛ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ io.Writer рдХреЛ рдмрд╛рдЗрдЯреНрд╕ рд▓рд┐рдЦ рд░рд╣рд╛ рд╣реИ, рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдХрд╛ рдПрдХ рдЕрд▓рдЧ рд░реВрдк рд╣реИред рд▓реЗрдХрд┐рди рд╣рдо рдПрдХ рдЫреЛрдЯреЗ рд░реИрдкрд░ рдХреЛ рдкреЗрд╢ рдХрд░рдХреЗ рдЕрдкрдиреЗ рдХрд╛рдо рдХреЛ рдЖрд╕рд╛рди рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред
type errWriter struct { io.Writer err error } func (e *errWriter) Write(buf []byte) (int, error) { if e.err != nil { return 0, e.err } var n int n, e.err = e.Writer.Write(buf) return n, nil }
рдЗрд░рд░реНрд░рд┐рдЯрд░ io.Writer рдЕрдиреБрдмрдВрдз рдХреЛ рдкреВрд░рд╛ рдХрд░рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдореМрдЬреВрджрд╛ io.Writer рдХреЛ рдорд╛рдЗрдЧреНрд░реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЗрд░реНрд░рд┐рдЯрд░ рдПрдХ рддреНрд░реБрдЯрд┐ рдХрд╛ рдкрддрд╛ рдЪрд▓рдиреЗ рддрдХ рд░рд┐рдХреЙрд░реНрдбрд┐рдВрдЧ рдХреЛ рдЕрдкрдиреЗ рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд░рд┐рдХреЙрд░реНрдбрд░ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддрд╛ рд╣реИред рдЕрдм рд╕реЗ, рдпрд╣ рдХрд┐рд╕реА рднреА рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐ рдХреЛ рдЫреЛрдбрд╝ рджреЗрддрд╛ рд╣реИ рдФрд░ рдкрд┐рдЫрд▓реА рддреНрд░реБрдЯрд┐ рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИред
func WriteResponse(w io.Writer, st Status, headers []Header, body io.Reader) error { ew := &errWriter{Writer: w} fmt.Fprintf(ew, "HTTP/1.1 %d %s\r\n", st.Code, st.Reason) for _, h := range headers { fmt.Fprintf(ew, "%s: %s\r\n", h.Key, h.Value) } fmt.Fprint(ew, "\r\n") io.Copy(ew, body) return ew.err }
рдЗрд░рд┐рдЯреНрд░рд╡реЗрдЯ рдХреЛ рд░рд╛рдЗрдЯрдкреНрд░реЗрдиреНрд╕ рдкрд░ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рд╕реЗ рдХреЛрдб рд╕реНрдкрд╖реНрдЯрддрд╛ рдореЗрдВ рд╕реБрдзрд╛рд░ рд╣реЛрддрд╛ рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдСрдкрд░реЗрд╢рди рдХреЛ рдЕрдм рддреНрд░реБрдЯрд┐ рдЬрд╛рдБрдЪ рдХреЗ рд▓рд┐рдП рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЕрдВрдд рдореЗрдВ рдЬрд╛рддрд╛ рд╣реИ, ew.err рдлрд╝реАрд▓реНрдб рдХреА рдЬрд╛рдБрдЪ рдХрд░рддрд╛ рд╣реИ рдФрд░ рд▓реМрдЯрд╛рдП рдЧрдП io.Copy рдорд╛рдиреЛрдВ рдХреЗ рдХрд╖реНрдЯрдкреНрд░рдж рдЕрдиреБрд╡рд╛рдж рд╕реЗ рдмрдЪрддрд╛ рд╣реИ
рдирд┐рд╖реНрдХрд░реНрд╖
рдЬрдм рдЖрдк рдЕрддреНрдпрдзрд┐рдХ рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХрд╛ рд╕рд╛рдордирд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдХреБрдЫ рдСрдкрд░реЗрд╢рди рдХреЛ рд╕рд╣рд╛рдпрдХ рдЖрд╡рд░рдг рдкреНрд░рдХрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдирд┐рдХрд╛рд▓рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред
рд▓реЗрдЦрдХ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ
рдЗрд╕ рд▓реЗрдЦ рдХреЗ рд▓реЗрдЦрдХ
рдбреЗрд╡ рдЪреЗрдиреА , рдЧреЛ рдХреЗ рд▓рд┐рдП рдХрдИ рд▓реЛрдХрдкреНрд░рд┐рдп рдкреИрдХреЗрдЬреЛрдВ рдХреЗ рд▓реЗрдЦрдХ рд╣реИрдВ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП
github.com/pkg/errors рдФрд░
github.com/davecheney/httpstat ред