How does http.HandlerFunc work? Explain the function-type adapter pattern.
Question 106MediumGo 1.22 to 1.25
A function type can have methods, so a plain function can be adapted to satisfy a single-method interface without writing a struct:
// net/http
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) }
// Usage: the conversion HandlerFunc(hello) is what makes hello a Handler
func hello(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "hi") }
var h http.Handler = http.HandlerFunc(hello)
// Middleware returning closures adapted to Handler
func Logging(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
log.Printf("%s %s %v", r.Method, r.URL.Path, time.Since(start))
})
}
The same pattern appears in several places:
sort.Slice, which is the less-interface version.- gRPC's
UnaryHandler. - The functional-options pattern (
type Option func(*Config)). - Test doubles:
type ReaderFunc func([]byte) (int, error)with aReadmethod lets you fake anio.Readerinline.
The interviewer wants to see that you understand the conversion HandlerFunc(hello) is necessary. hello by itself has no methods. The conversion gives it the method set of HandlerFunc. http.HandleFunc does that conversion for you.
More on Interfaces, Methods & Embedding
- Q104How do constraint interfaces in generics differ from ordinary interfaces?
- Q105Do methods carry over with
type B Avstype B = Avs embedding? What does this mean forsync.Mutex? - Q107What happens when you call a value-receiver method through an interface that holds a nil pointer?
- Q108Can you modify a struct stored inside an interface? What does this print?
- Q109How do you write a generic function that needs to call a pointer-receiver method on
T? (thePT interface{ *T; M() }pattern) - Q110How do you "seal" an interface so other packages cannot implement it? Can the seal be bypassed?