рд╕реНрдЯреЗрд░реЙрдпрдб рдкрд░ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдк

рд╣реЗрд▓реЛ, рд╣реЗрдмреНрд░! рдореИрдВ рдЖрдкрдХреЛ M├бrk S├бgi-Kaz├бr рджреНрд╡рд╛рд░рд╛ рд╕реНрдЯреЗрд░реЙрдпрдб рдкрд░ рд▓реЗрдЦ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХрд╛ рдЕрдиреБрд╡рд╛рдж рдкреНрд░рд╕реНрддреБрдд рдХрд░рддрд╛ рд╣реВрдВ ред

рдЫрд╡рд┐

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

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

рдкрд░рд┐рдЪрдп - рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдк рдХреНрдпрд╛ рд╣реИрдВ?


рдЖрдорддреМрд░ рдкрд░, рдЬрдм рдЖрдк "рдСрдмреНрдЬреЗрдХреНрдЯ" рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдЖрд╡рд╢реНрдпрдХ рддрд░реНрдХ рдХреЗ рд╕рд╛рде рдирд┐рд░реНрдорд╛рддрд╛ рдХреЛ рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ:

obj := New(arg1, arg2)

(рдЖрдЗрдП рдЗрд╕ рддрдереНрдп рдХреЛ рдирдЬрд░рдЕрдВрджрд╛рдЬ рдХрд░реЗрдВ рдХрд┐ рдЧреЛ рдореЗрдВ рдХреЛрдИ рдкрд╛рд░рдВрдкрд░рд┐рдХ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдирд╣реАрдВ рд╣реИрдВред)

рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдк рдЖрдкрдХреЛ рдЕрддрд┐рд░рд┐рдХреНрдд рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдПрдкреАрдЖрдИ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ, рдЙрдкрд░реЛрдХреНрдд рдкрдВрдХреНрддрд┐ рдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдореЗрдВ рдмрджрд▓ рджреЗрддреЗ рд╣реИрдВ:

// I can still do this...
obj := New(arg1, arg2)

// ...but this works too
obj := New(arg1, arg2, myOption1, myOption2)

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

рдкреИрдЯрд░реНрди рдХреЛ рдмреЗрд╣рддрд░ рдврдВрдЧ рд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рдПрдХ рдпрдерд╛рд░реНрдерд╡рд╛рджреА рдЙрджрд╛рд╣рд░рдг (рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рдмрд┐рдирд╛) рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:

type Server struct {
    addr string
}

// NewServer initializes a new Server listening on addr.
func NewServer(addr string) *Server {
    return &Server {
        addr: addr,
    }
}

рдЯрд╛рдЗрдордЖрдЙрдЯ рд╡рд┐рдХрд▓реНрдк рдЬреЛрдбрд╝рдиреЗ рдХреЗ рдмрд╛рдж, рдХреЛрдб рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:

type Server struct {
    addr string

    // default: no timeout
    timeout time.Duration
}

// Timeout configures a maximum length of idle connection in Server.
func Timeout(timeout time.Duration) func(*Server) {
    return func(s *Server) {
        s.timeout = timeout
    }
}

// NewServer initializes a new Server listening on addr with optional configuration.
func NewServer(addr string, opts ...func(*Server)) *Server {
    server := &Server {
        addr: addr,
    }

    // apply the list of options to Server
    for _, opt := range opts {
        opt(server)
    }

    return server
}

рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк API рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рд╣реИ рдФрд░ рдкрдврд╝рдиреЗ рдореЗрдВ рдЖрд╕рд╛рди рд╣реИ:

// no optional paramters, use defaults
server := NewServer(":8080")

// configure a timeout in addition to the address
server := NewServer(":8080", Timeout(10 * time.Second))

// configure a timeout and TLS in addition to the address
server := NewServer(":8080", Timeout(10 * time.Second), TLS(&TLSConfig{}))


рддреБрд▓рдирд╛ рдХреЗ рд▓рд┐рдП, рдпрд╣рд╛рдВ рдмрддрд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдХрдВрд╕реНрдЯреНрд░рдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдФрд░ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдЖрд░рдВрднреАрдХрд░рдг рдХреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ:

// constructor variants
server := NewServer(":8080")
server := NewServerWithTimeout(":8080", 10 * time.Second)
server := NewServerWithTimeoutAndTLS(":8080", 10 * time.Second, &TLSConfig{})


// config struct
server := NewServer(":8080", Config{})
server := NewServer(":8080", Config{ Timeout: 10 * time.Second })
server := NewServer(":8080", Config{ Timeout: 10 * time.Second, TLS: &TLSConfig{} })

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

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

рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдк рдЕрднреНрдпрд╛рд╕


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

рдореБрдЭреЗ рдИрдореЗрд▓ рдХрд░реЗрдВ рдЕрдЧрд░ рдЖрдкрдХреЛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдХреБрдЫ рдпрд╛рдж рдЖ рд░рд╣реА рд╣реИред

рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХрд╛ рдкреНрд░рдХрд╛рд░


рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдк рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддреЗ рд╕рдордп рдЖрдк рдкрд╣рд▓реА рдмрд╛рдд рдпрд╣ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╡реИрдХрд▓реНрдкрд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирд┐рд░реНрдзрд╛рд░рдг рдХрд░реЗрдВ:

// Option configures a Server.
type Option func(s *Server)

рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣ рдПрдХ рдмрдбрд╝реЗ рд╕реБрдзрд╛рд░ рдХреА рддрд░рд╣ рдкреНрд░рддреАрдд рдирд╣реАрдВ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдПрдХ рдкреНрд░рдХрд╛рд░ рдирд╛рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХреЛрдб рдЕрдзрд┐рдХ рдкрдардиреАрдп рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ:

func Timeout(timeout time.Duration) func(*Server) { /*...*/ }

// reads: a new server accepts an address
//      and a set of functions that accepts the server itself
func NewServer(addr string, opts ...func(s *Server)) *Server

// VS

func Timeout(timeout time.Duration) Option { /*...*/ }

// reads: a new server accepts an address and a set of options
func NewServer(addr string, opts ...Option) *Server

рд╡рд┐рдХрд▓реНрдк рдкреНрд░рдХрд╛рд░ рд╣реЛрдиреЗ рдХрд╛ рдПрдХ рдФрд░ рд▓рд╛рдн рдпрд╣ рд╣реИ рдХрд┐ рдЧреЛрдбреЛрдХ рд╕реНрдерд╛рди рд╡рд┐рдХрд▓реНрдк рдкреНрд░рдХрд╛рд░ рдХреЗ рддрд╣рдд рдХрд╛рд░реНрдп рдХрд░рддрд╛ рд╣реИ:

рдЫрд╡рд┐

рд╡рд┐рдХрд▓реНрдк рдкреНрд░рдХрд╛рд░ рд╕реВрдЪреА


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

defaultOptions := []Option{Timeout(5 * time.Second)}

server1 := NewServer(":8080", append(defaultOptions, MaxConnections(10))...)

server2 := NewServer(":8080", append(defaultOptions, RateLimit(10, time.Minute))...)

server3 := NewServer(":8080", append(defaultOptions, Timeout(10 * time.Second))...)

рдпрд╣ рдмрд╣реБрдд рд╣реА рдкрдардиреАрдп рдХреЛрдб рдирд╣реАрдВ рд╣реИ, рд╡рд┐рд╢реЗрд╖ рд░реВрдк рд╕реЗ рдпрд╣ рджреЗрдЦрддреЗ рд╣реБрдП рдХрд┐ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдмрд┐рдВрджреБ рдЕрдиреБрдХреВрд▓ рдПрдкреАрдЖрдИ рдмрдирд╛рдирд╛ рд╣реИред рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдЗрд╕реЗ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рд╣реИред рд╣рдореЗрдВ рдмрд╕ рд╡рд┐рдХрд▓реНрдк рдХреЗ рд╕рд╛рде рд╕реАрдзреЗ [] рд╡рд┐рдХрд▓реНрдк рдХреЛ рд╕реНрд▓рд╛рдЗрд╕ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:

// Options turns a list of Option instances into an Option.
func Options(opts ...Option) Option {
    return func(s *Server) {
        for _, opt := range opts {
            opt(s)
        }
    }
}

рд╡рд┐рдХрд▓реНрдк рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд╕рд╛рде рд╕реНрд▓рд╛рдЗрд╕ рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рдж, рдЙрдкрд░реЛрдХреНрдд рдХреЛрдб рдмрди рдЬрд╛рддрд╛ рд╣реИ:

defaultOptions := Options(Timeout(5 * time.Second))

server1 := NewServer(":8080", defaultOptions, MaxConnections(10))

server2 := NewServer(":8080", defaultOptions, RateLimit(10, time.Minute))

server3 := NewServer(":8080", defaultOptions, Timeout(10 * time.Second))

рд╕рд╛рде / рд╕реЗрдЯ рд╡рд┐рдХрд▓реНрдк рдХреЗ рдЙрдкрд╕рд░реНрдЧ


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

type Logger interface {
    Info(msg string)
    Error(msg string)
}

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

func WithLogger(logger Logger) Option {
    return func(s *Server) {
        s.logger = logger
    }
}

// reads: create a new server that listens on :8080 with a logger
NewServer(":8080", WithLogger(logger))

рдПрдХ рдЬрдЯрд┐рд▓ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдПрдХ рдФрд░ рдЖрдо рдЙрджрд╛рд╣рд░рдг рдореВрд▓реНрдпреЛрдВ рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рд╣реИ:

type Server struct {
    // ...

    whitelistIPs []string
}

func WithWhitelistedIP(ip string) Option {
    return func(s *Server) {
        s.whitelistIPs = append(s.whitelistIPs, ip)
    }
}

NewServer(":8080", WithWhitelistedIP("10.0.0.0/8"), WithWhitelistedIP("172.16.0.0/12"))

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

func SetWhitelistedIP(ip string) Option {
    return func(s *Server) {
        s.whitelistIPs = []string{ip}
    }
}

NewServer(
    ":8080",
    WithWhitelistedIP("10.0.0.0/8"),
    WithWhitelistedIP("172.16.0.0/12"),
    SetWhitelistedIP("192.168.0.0/16"), // overwrites any previous values
)

рдкреНрд░реАрд╕реЗрдЯ рдЯреЗрдореНрдкреНрд▓реЗрдЯ


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

// PublicPreset configures a Server for public usage.
func PublicPreset() Option {
    return Options(
        WithTimeout(10 * time.Second),
        MaxConnections(10),
    )
}

// InternalPreset configures a Server for internal usage.
func InternalPreset() Option {
    return Options(
        WithTimeout(20 * time.Second),
        WithWhitelistedIP("10.0.0.0/8"),
    )
}

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

рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкреНрд░рдХрд╛рд░ рдорд╛рди рдмрдирд╛рдо рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдкреНрд░реАрд╕реЗрдЯ рдорд╛рди


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

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

рдЗрди рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдорд╛рди рд╕реЗрдЯ рдХрд░рдирд╛ (рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ) рдлреЙрд▓рдмреИрдХ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рддрд░реАрдХрд╛ рд╣реИ:

func NewServer(addr string, opts ...func(*Server)) *Server {
    server := &Server {
        addr:   addr,
        logger: noopLogger{},
    }

    // apply the list of options to Server
    for _, opt := range opts {
        opt(server)
    }

    return server
}

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

func NewServer(addr string, opts ...func(*Server)) *Server {
    server := &Server {
        addr:   addr,
    }

    // what are the defaults?
    opts = append([]Option{DefaultPreset()}, opts...)

    // apply the list of options to Server
    for _, opt := range opts {
        opt(server)
    }

    return server
}

рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╕рдВрд░рдЪрдирд╛ рд╡рд┐рдХрд▓реНрдк


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

type Config struct {
    Timeout time.Duration
}

type Option func(c *Config)

type Server struct {
    // ...

    config Config
}

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

config := Config{
    Timeout: 10 * time.Second
    // ...
    // lots of other options
}

NewServer(":8080", WithConfig(config))

рдЗрд╕ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рдЙрдкрдпреЛрдЧ рдорд╛рдорд▓рд╛ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдорд╛рди рд╕реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ:

config := Config{
    Timeout: 10 * time.Second
    // ...
    // lots of other options
}

NewServer(":8080", WithConfig(config), WithTimeout(20 * time.Second))

рдЙрдиреНрдирдд рдЯреЗрдореНрдкрд▓реЗрдЯ


рджрд░реНрдЬрдиреЛрдВ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдк рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрд╛рдж, рдЖрдк рдЖрд╢реНрдЪрд░реНрдпрдЪрдХрд┐рдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдХреНрдпрд╛ рдРрд╕рд╛ рдХрд░рдиреЗ рдХрд╛ рдПрдХ рдмреЗрд╣рддрд░ рддрд░реАрдХрд╛ рд╣реИред рдЙрдкрдпреЛрдЧ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рджреАрд░реНрдШрдХрд╛рд▓рд┐рдХ рд╕рдорд░реНрдерди рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рд╣рдо рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

type Timeout time.Duration

NewServer(":8080", Timeout(time.Minute))

(рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рд╕рдорд╛рди рд░рд╣рддрд╛ рд╣реИ)

рдпрд╣ рдкрддрд╛ рдЪрд▓рд╛ рд╣реИ рдХрд┐ рд╡рд┐рдХрд▓реНрдк рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдмрджрд▓рдХрд░, рд╣рдо рдЖрд╕рд╛рдиреА рд╕реЗ рдРрд╕рд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

// Option configures a Server.
type Option interface {
    // apply is unexported,
    // so only the current package can implement this interface.
    apply(s *Server)
}

рдПрдХ рд╡реИрдХрд▓реНрдкрд┐рдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рд░реВрдк рдореЗрдВ рдУрд╡рд░рд░рд╛рдЗрдб рдХрд░рдиреЗ рд╕реЗ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рдХрдИ рдирдП рддрд░реАрдХреЛрдВ рдХреЗ рд▓рд┐рдП рджрд░рд╡рд╛рдЬрд╛ рдЦреБрд▓рддрд╛ рд╣реИ:

рд╡рд┐рднрд┐рдиреНрди рдирд┐рд░реНрдорд┐рдд рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдПрдХ рд░реИрдкрд░ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдмрд┐рдирд╛ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

// Timeout configures a maximum length of idle connection in Server.
type Timeout time.Duration

func (t Timeout) apply(s *Server) {
    s.timeout = time.Duration(t)
}

рд╡рд┐рдХрд▓реНрдкреЛрдВ рдФрд░ рд╡рд┐рдиреНрдпрд╛рд╕ рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреА рд╕реВрдЪреА (рдкрд┐рдЫрд▓реЗ рдЕрдиреБрднрд╛рдЧ рджреЗрдЦреЗрдВ) рдХреЛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:

// Options turns a list of Option instances into an Option.
type Options []Option

func (o Options) apply(s *Server) {
    for _, opt := range o {
        o.apply(s)
    }
}

type Config struct {
    Timeout time.Duration
}

func (c Config) apply(s *Server) {
    s.config = c
}

рдореЗрд░рд╛ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдкрд╕рдВрджреАрджрд╛ рдХрдИ рдирд┐рд░реНрдорд╛рдгрдХрд░реНрддрд╛рдУрдВ рдореЗрдВ рд╡рд┐рдХрд▓реНрдк рдХрд╛ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рд╣реИ:

// ServerOption configures a Server.
type ServerOption interface {
    applyServer(s *Server)
}

// ClientOption configures a Client.
type ClientOption interface {
    applyClient(c *Client)
}

// Option configures a Server or a Client.
type Option interface {
    ServerOption
    ClientOption
}

func WithLogger(logger Logger) Option {
    return withLogger{logger}
}

type withLogger struct {
    logger Logger
}

func (o withLogger) applyServer(s *Server) {
    s.logger = o.logger
}

func (o withLogger) applyClient(c *Client) {
    c.logger = o.logger
}

NewServer(":8080", WithLogger(logger))
NewClient("http://localhost:8080", WithLogger(logger))

рд╕рд╛рд░рд╛рдВрд╢


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

All Articles