Function implementing interface - go

I want to know what is happening here.
There is the interface for a http handler:
type Handler interface {
ServeHTTP(*Conn, *Request)
}
This implementation I think I understand.
type Counter int
func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
fmt.Fprintf(c, "counter = %d\n", ctr);
ctr++;
}
From my understanding it is that the type "Counter" implements the interface since it has a method that has the required signature. So far so good. Then this example is given:
func notFound(c *Conn, req *Request) {
c.SetHeader("Content-Type", "text/plain;", "charset=utf-8");
c.WriteHeader(StatusNotFound);
c.WriteString("404 page not found\n");
}
// Now we define a type to implement ServeHTTP:
type HandlerFunc func(*Conn, *Request)
func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) {
f(c, req) // the receiver's a func; call it
}
// Convert function to attach method, implement the interface:
var Handle404 = HandlerFunc(notFound);
Can somebody elaborate on why or how these various functions fit together?

This:
type Handler interface {
ServeHTTP(*Conn, *Request)
}
says that any type which satisfies the Handler interface must have a ServeHTTP method. The above would be inside the package http.
type Counter int
func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
fmt.Fprintf(c, "counter = %d\n", ctr);
ctr++;
}
This puts a method on the Counter type which corresponds to ServeHTTP. This is an example which is separate from the following.
From my understanding it is that the
type "Counter" implements the
interface since it has a method that
has the required signature.
That's right.
The following function by itself won't work as a Handler:
func notFound(c *Conn, req *Request) {
c.SetHeader("Content-Type", "text/plain;", "charset=utf-8");
c.WriteHeader(StatusNotFound);
c.WriteString("404 page not found\n");
}
The rest of this stuff is just fitting the above so that it can be a Handler.
In the following, a HandlerFunc is a function which takes two arguments, pointer to Conn and pointer to Request, and returns nothing. In other words, any function which takes these arguments and returns nothing can be a HandlerFunc.
// Now we define a type to implement ServeHTTP:
type HandlerFunc func(*Conn, *Request)
Here ServeHTTP is a method added to the type HandlerFunc:
func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) {
f(c, req) // the receiver's a func; call it
}
All it does is to call the function itself (f) with the arguments given.
// Convert function to attach method, implement the interface:
var Handle404 = HandlerFunc(notFound);
In the above line, notFound has been finagled into being acceptable for the interface for Handler by artificially creating a type instance out of the function itself and making the function into the ServeHTTP method for the instance. Now Handle404 can be used with the Handler interface. It's basically a kind of trick.

What exactly don't you understand about the second half? It's the same pattern as above. Instead of defining the Counter type as an int, they define a function called notFound. They then create a type of function called HandlerFunc that takes two parameters, a connection and a request. they then create a new method called ServeHTTP, that gets bound to the HandlerFunc type. Handle404 is simply an instance of this class that uses the notFound function.

Related

How does httprouterhttp.HandlerFunc() works?

I am learning Go and at the moment trying to understand what and how actually julienschmidt's httprouterhttp router works. Especially how the router.HandlerFunc() works.
Go's http package:
http.Handler: Handler is an Interface. Any type which has the same method signature i.e., ServeHTTP(w,r) implements a Handler.
http.Handle: http.Handle is a function which has two parameters. 1) String to match request path, 2)Handler, to call its ServeHTTP() method.
http.HandlerFunc: A custom function type with function signature (ResponseWriter, *Request) and its own ServeHTTP(w,r) method, which satisfies as a http.Handler interface.
Now if I need to use a function eg. Bar(ResponseWriter, *Request) which satisfies to be a HandlerFunc, inside http.Handle, I type caste/covert the function to http.HandlerFunc and then use it inside the http.Handle. Like so:
func Bar(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("My bar func response"))
}
...
mf := http.HandlerFunc(Bar)
http.Handle("/path", mf)
Looking at the http.HandleFunc source code, this is how http.HandleFunc() works. It expects a function which as the signature of (w ResponseWriter, r *Request) and type caste the function.
Like so:
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
if handler == nil {
panic("http: nil handler")
}
mux.Handle(pattern, HandlerFunc(handler))
}
julienschmidt's httprouterhttp
Looking at the source code of router.HandlerFunc()
func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
r.Handler(method, path, handler)
}
Instead of expecting a function with appropriate signature (ResponseWriter, *Request) like the http.HandleFunc(), it expects a http.HandlerFunc.
Also without type casting/converting the function to a HandlerFunc type, it just pass the function to another function router.Handler(method, path string, handler http.Handler), which again expects a Handler.
So I can execute this code without any problem:
router.HandlerFunc(http.MethodPost, "/path", Bar) // Bar is not type casted/converted to a HandlerFunc
I can understand type casting the Bar to a HandlerFunc and then pass it to router.HandlerFunc().
Could you please clear some of my doubts:
How does without type casting the Bar() to a HandlerFunc satisfies as a HandlerFunc type to the router.HandlerFunc()?
If the router.Handler() expects a http.Handler type, how come Bar() without type casting to the http.HandlerFunc satisfies a a Handler to the router.Handler()?
What am I missing?
"How does without type casting the Bar() to a HandlerFunc satisfies as a HandlerFunc type to the router.HandlerFunc()?"
The expression
router.HandlerFunc(http.MethodPost, "/path", Bar)
complies with the rules of Assignability:
V and T have identical underlying types and at least one of V or T is not a named type.
The Bar function's type and the http.HandlerFunc type have identical underlying types, and Bar's type is not named. Because of that you can pass (assign) Bar as the handler argument to httprouter.Router.HandlerFunc without an explicit conversion.
"If the router.Handler() expects a http.Handler type, how come Bar() without type casting to the http.HandlerFunc satisfies a a Handler to the router.Handler()?"
In the following method definition
func (r *Router) HandlerFunc(method, path string, handler http.HandlerFunc) {
r.Handler(method, path, handler)
}
there is no Bar, there's only the handler argument whose type is http.HandlerFunc and that type does implement the http.Handler interface. So the statement r.Handler(method, path, handler) is perfectly legitimate.
"What am I missing?"
See above.
Look at definition of HandlerFunc
type HandlerFunc func(ResponseWriter, *Request)
And the signature of your function
(w http.ResponseWriter, r *http.Request)
You don't need conversion here.

How can I make type assertions against an anonymous function?

I'm writing an HTTP service in Go using Gorilla. I'm newish to Go (<1yr experience), but ramping up fairly quickly.
I have a function I use to register my handlers:
func (s *Server) RegisterHandler(path string, handler http.HandlerFunc, methods ...string) {
if len(methods) == 0 {
s.Router.Handle(path, handler).Methods(http.MethodGet)
} else {
s.Router.Handle(path, handler).Methods(methods...)
}
}
I have some code that registers named functions as handlers:
func (s *Server) RegisterDefaultHandlers() {
s.RegisterHandler("/ping", Ping)
}
func Ping(w http.ResponseWriter, request *http.Request) {
responders.RespondOk(w)
}
I also have unit test code that registers anonymous functions as handlers:
s.RegisterHandler("/testPath", func(w http.ResponseWriter, r *http.Request) {
// whatever the test calls for
}, http.MethodPost)
This all works great -- just establishing my starting point.
Today, I find myself banging my head against Go's type system. I am defining some custom handler types, for example:
type UserAwareHandlerFunc func(http.ResponseWriter, *http.Request, models.User)
And I'm also introducing a function to allow me to register such handlers, and to wrap all handlers in context.ClearHandler. If this works, I'll also wrap everything with another function that sets a few things on my logging context. What I have so far:
func (s *Server) RegisterHandler(path string, handler interface{}, methods ...string) {
wrappedHandler := wrappers.ApplyWrappers(handler)
if len(methods) == 0 {
s.Router.Handle(path, wrappedHandler).Methods(http.MethodGet)
} else {
s.Router.Handle(path, wrappedHandler).Methods(methods...)
}
}
func ApplyWrappers(handler interface{}) http.Handler {
var result http.Handler
if userAwareHandler, ok := handler.(UserAwareHandlerFunc); ok {
result = UserAware(userAwareHandler)
} else if handlerFunc, ok := handler.(http.HandlerFunc); ok {
result = handlerFunc
} else if handlerObj, ok := handler.(http.Handler); ok {
result = handlerObj
} else {
log.Fatalf("handler %+v (type %s) is not a recognized handler type.", handler, reflect.TypeOf(handler))
}
// to avoid memory leaks, ensure that all request data is cleared by the end of the request lifetime
// for all handlers -- see https://stackoverflow.com/a/48203334
result = context.ClearHandler(result)
return result
}
func UserAware(handler UserAwareHandlerFunc) http.Handler {
return func(w http.ResponseWriter, r *http.Request) {
user := ... // get user from session
handler(w, r, user)
}
}
With these changes, I can no longer register named or anonymous functions; the type assertions in ApplyWrappers all fail. I have to declare and define a typed variable, then pass that in.
Named functions have two feasible approaches:
var Ping http.HandlerFunc = func(w http.ResponseWriter, request *http.Request) {
responders.RespondOk(w)
}
func Ping2(w http.ResponseWriter, request *http.Request) {
responders.RespondOk(w)
}
func (s *Server) RegisterDefaultHandlers() {
s.RegisterHandler("/ping", Ping)
var pingHandler2 http.HandlerFunc = Ping2
s.RegisterHandler("/ping2", pingHandler2)
}
For anonymous functions, I can do:
var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) {
...
}
s.RegisterHandler("/testPath", handler, http.MethodPost)
The whole point of what I've built here is to consolidate boilerplate into one place, keeping my many tests and handlers as streamlined as possible. The need to declare a typed variable is working against that goal. So my question is this: is there some special type magic I could use (preferably in RegisterHandler and/or ApplyWrappers) that would restore the ability to pass named and/or anonymous functions to RegisterHandler?
EDIT: thanks so much for the quick answers. Problem solved:
func ApplyWrappers(handler interface{}) http.Handler {
var result http.Handler
if userAwareHandler, ok := handler.(UserAwareHandlerFunc); ok {
result = UserAware(userAwareHandler)
} else if anonymousFunc, ok := handler.(func(http.ResponseWriter,*http.Request)); ok {
result = http.HandlerFunc(anonymousFunc)
} else if handlerObj, ok := handler.(http.Handler); ok {
result = handlerObj
} else {
log.Fatalf("handler %+v (type %s) is not a recognized handler type.", handler, reflect.TypeOf(handler))
}
// to avoid memory leaks, ensure that all request data is cleared by the end of the request lifetime
// for all handlers -- see https://stackoverflow.com/a/48203334
result = context.ClearHandler(result)
return result
}
It's working now, but I still have questions:
If I understand correctly, the "duck typing" behavior that I was looking for here would have been fine if I were dealing with interfaces rather than functions. What drives the distinction? Is duck-typing of functions something I could reasonably hope to see in a future version of the language?
I can cast the anonymous function to a HandlerFunc. It's weird to me that casting and type assertions don't share semantics. Can someone explain?
EDIT 2: I've now seen the bit of the language spec that says that defined types (i.e. ones with names) are never identical to any other type, even if the underlying type is the same, and as such will never work in a type assertion (unless it's an interface). So now I'm left wondering:
Why are the semantics different between interfaces and other types?
Why are the semantics different for named and un-named types?
I find both to be unintuitive and inconvenient. Am I alone here? I'm wondering if anyone knows why these decisions were made when the language was designed (perhaps it's particularly difficult to implement without bloating the compiler or its output, etc.), and if anyone is aware of plans to address either situation.
http.HandlerFunc is a specific type. The Ping function is NOT of that type, although it can be converted to that type since they both have the same underlying type.
If handler is an anonymous function then you need to use an anonymous function in the type assertion:
f, ok := handler.(func(http.ResponseWriter,*http.Request))
https://golang.org/ref/spec#Type_assertions
if T is not an interface type, x.(T) asserts that the dynamic type of x is identical to the type T
If T is an interface type, x.(T) asserts that the dynamic type of x implements the interface T.

panic: Last argument needs to be of type http.HandlerFunc

I have this helper function, which is compiling fine:
func Middleware(adapters ...interface{}) http.HandlerFunc {
log.Info("length of adapters:", len(adapters))
if len(adapters) < 1 {
panic("Adapters need to have length > 0.");
}
h, ok := (adapters[len(adapters)-1]).(http.HandlerFunc)
if ok == false {
panic("Last argument needs to be of type http.HandlerFunc") // ERROR HERE
}
adapters = adapters[:len(adapters)-1]
for _, adapt := range adapters {
h = (adapt.(AdapterFunc))(h)
}
return h
}
I am calling it like so:
router.HandleFunc("/share", h.makeGetMany(v)).Methods("GET")
func (h Handler) makeGetMany(v Injection) http.HandlerFunc {
return mw.Middleware(
mw.Allow("admin"),
func(w http.ResponseWriter, r *http.Request) {
log.Println("now we are sending response.");
json.NewEncoder(w).Encode(v.Share)
},
)
}
the problem is that I am getting this error and I cannot figure out why:
panic: Last argument needs to be of type http.HandlerFunc
goroutine 1 [running]:
huru/mw.Middleware(0xc420083d40, 0x2, 0x2, 0xc42011f3c0)
/home/oleg/codes/huru/api/src/huru/mw/middleware.go:301 +0x187
huru/routes/share.Handler.makeGetMany(0xc4200ae1e0, 0x10)
/home/oleg/codes/huru/api/src/huru/routes/share/share.go:62 +0x108
it does confirm that the length of the adapters slice is 2:
length of adapters:2
anyone know why that type assertion would fail in this case? Makes no sense. Maybe I am not actually retrieving the last argument of the slice or something? Is there a better way to pop the last argument off the slice?
You need to wrap the 2nd argument of mw.Middleware() statement into http.Handler type by using http.HandlerFunc().
func (h Handler) makeGetMany(v Injection) http.HandlerFunc {
return mw.Middleware(
mw.Allow("admin"),
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("now we are sending response.");
json.NewEncoder(w).Encode(v.Share)
}),
)
}
In the http package,
ListenAndServe has the following signiture
func ListenAndServe(addr string, handler Handler) error
where the Handler (i.e., http.Handler) is an interface
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
For one web application, there is only one ListenAndServe call, thus only onehandler, which needs to deal with all the access points such as /url1, /url2, etc. If we write the handler from scratch, the implementation could be a custom struct that wraps around a database handle. Its ServeHTTP method checks the access point, and writes the corresponding content to the ResponseWriter, which is quite tedious and mingled.
That's the motivation of ServeMux, which is the router in your code. It has a ServeHTTP method so it satisfies the http.Handler interface and can be used for ListenAndServe. In addition, it has the HandleFunc method to deal with the individual access point
func (mux *ServeMux) HandleFunc(pattern string,
handler func(ResponseWriter, *Request))
Note here the handler is not a http.Handler, i.e., it doesn't have ServeHTTP method. It doesn't have to because the mux already has ServeHTTP and its ServeHTTP method can dispatch the individual access point request to the corresponding handlers.
Note it also has a Handle method, which requires the argument to satisfy the http.Handler interface. It's slightly less convenient to use compared to the HandleFunc method.
func (mux *ServeMux) Handle(pattern string, handler Handler)
Now back to your question, since you call router.HandleFunc, its input doesn't have to be http.Handler. So an alternative solution is to use func(ResponseWriter, *Request) as the return type for your middleware and makeGetMany method. (the type assertion in the middleware also needs to be updated, probably a lot more code needs to be updated as well)
#xpare's solution is to do type conversion so that all the function signatures match up, i.e., convert func(ResponseWriter, *Request) to http.HandlerFunc. It is also interesting to see how it works. From the implementation
// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
you can see that it basically defines a ServeHTTP method to call itself.

Cannot use some type in function call

Currently, I'm having two files in two packages.
File somepkg/something.go
package somepkg
// ----------------------------------------------------------------------------
// Interfaces
// ----------------------------------------------------------------------------
type SomeThing interface {
// some other methods
Handle(handler *Handler)
}
type SomeThingImpl struct {
handlers []Handler
}
type Handler interface {
IncomingCall(request *IncomingRequest)
}
// ----------------------------------------------------------------------------
// SomeThingImpl implementation
// ----------------------------------------------------------------------------
func NewSomeThing() SomeThing {
u := new(SomethingImpl)
// some more operations with u
return u
}
func (l *SomeThingImpl) Handle(handler *Handler) {
fmt.Printf("handler: %s", handler)
}
File main.go
package main
import (
"fmt"
)
type MyHandler struct {}
func (h *MyHandler) IncomingCall(request *somepkg.IncomingRequest) {
fmt.Printf("Handler!")
}
func main() {
mySomeThing := somepkg.NewSomeThing()
handler := new(MyHandler)
// works so far.
mySomeThing.Handle(handler) // <-- here the compilation error occurs
}
trying to run go build yields the following compilation error:
{...}\main.go:20: cannot use handler (type *MyHandler) as type *somepkg.Handler in argument to mySomething.Handle:
*somepkg.Handler is pointer to interface, not interface
whereas main.go:20 refers to the line above where I'm calling mySomeThing.Handle(handler).
Actually, both MyHandler and somepkg.Handler seem to be pointers. Both of them implement the same methods.
Why does the compiler not consider these types to be compatible ?
You have this method;
func (l *SomeThingImpl) Handle(handler *Handler) {
fmt.Printf("handler: %s", handler)
}
Defined to take an interface pointer which is likely not what you want. What you're actually looking for is to have *MyHandler implement the Handler interface rather than MyHandler (or both could) so that you can pass your reference type into the method.
//new method sig
Handle(handler Handler)
// my preferred syntax for assignment here
handler := &MyHandler{}
// works just fine
mySomeThing.Handle(handler)
If you really want to keep the method sig how you have it, to make your code work you just need to do mySomeThing.Handle(&handler) but I'm doubtful that's actually what you want to do.
btw; In your code *MyHandler is already implementing the interface due to this method func (h *MyHandler) IncomingCall(request *somepkg.IncomingRequest) haveing *MyHandler as the receiving type as apposed to func (h MyHandler) which would make it so only MyHandler implements the Handler interface. Some little Go nuance with recievers and interfaces there.
Never use a pointer to an interface (well, unless you know exactly why you would want to do so)
In order to pass that into the defined function, you would need to create the *somepkg.Handler explicitly (but don't really do this)
var handler somepkg.Handler = new(MyHandler)
mySomeThing.Handle(&handler)
If you define Handle as
Handle(handler Handler)
any type that satisfies the somepkg.Handler interface can be passed in directly.

Difference between http.Handle and http.HandleFunc?

The Go docs have the following example for the http package:
http.Handle("/foo", fooHandler)
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
I'm having sort of a difficulty understanding the difference between Handle and HandleFunc and why two are needed. Can somebody try to explain to a new Gopher in clear words?
Basically, the HTTP server's "mux" has a map of path -> handler interface
Interfaces are used here, I assume, to allow you to implement complex path handlers that have state.
For example the file server from the standard package is a struct that contains the root dir for file service and implements the handler interface.
That said, for simple stuff, a func is easier and more clear. So they added a special generator so you can easily pass in a func.
Take a look at: server.go
from line: 1216 (as of today)
1216 type HandlerFunc func(ResponseWriter, *Request)
1217
1218 // ServeHTTP calls f(w, r).
1219 func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
1220 f(w, r)
1221 }
What they are doing is implementing the interface on a custom type (which happens to match the api of the interface) that just calls itself.
In simple terms:
Problem: I want to create an object (type) that responds to HTTP requests.
Solution: Use http.Handle for that. It accepts an http.Handler as the second argument.
http.Handler is an interface and should implement ServeHTTP from the http package.
Problem: I want a function to respond to my HTTP request.
Solution: Use http.HandleFunc for that. It accepts an http.HandlerFunc as the second argument.
http.HandlerFunc is a function type and should implement ServeHTTP from the http package.
No, it's different. Let's examine:
func Handle(pattern string, handler Handler) {
DefaultServeMux.Handle(pattern, handler)
}
Handle expects us to pass a Handler. Handler is an interface
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
if any type implements ServeHTTP(ResponseWriter, *Request) for example:
myCustomHandler then we can pass it like Handle(pattern string, myCustomHandler).
In the second scenario:
HandleFunc(pattern string, func(w ResponseWriter, r *Request) {
// do some stuff
}
HandleFunc expects a function where Handle expects a Handler interface.
So, if you just want to pass a function then you can use http.HandleFunc(..). Like #David showed that behind the scenes it implements Handler interface by calling ServeHTTP.
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
Handler functions are merely convenient ways of creating handlers.
While both of them can be used to create handlers, but because, using handler functions is cleaner and it does the job just as well, why use handlers at all? It all boils down to design. If you have an existing interface or if you want a type that can also be used as a handler, simply add a ServeHTTP method to that interface and you’ll get a handler that you can assign to a URL. It can also allow you to
build web applications that are more modular.
Using Handle
package main
import (
"fmt"
"net/http"
)
type HelloHandler struct{}
func (h *HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello!")
}
type WorldHandler struct{}
func (h *WorldHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "World!")
}
func main() {
hello := HelloHandler{}
world := WorldHandler{}
http.Handle("/hello", &hello)
http.Handle("/world", &world)
http.ListenAndServe(":8080", nil)
}
Using HandleFunc
package main
import (
"fmt"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello!")
}
func world(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "World!")
}
func main() {
http.HandleFunc("/hello", hello)
http.HandleFunc("/world", world)
http.ListenAndServe(":8080", nil)
}
Additional information:
http.Handler is an interface with method ServeHTTP(),
// net/http/server.go
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
And here's a ServeHTTP information,
// net/http/server.go
ServeHTTP(w http.ResponseWriter, r *http.Request)
// where,
// http.ResponseWriter is a writer interface, and,
// http.Request is a structure with request details.
Now lets look at HandlerFunc,
// net/http/server.go
// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request){
f(w, r)
}
That means, http.HandlerFunc is a type that has ServeHTTP method implemented.
http.HandlerFunc(someFunc)
// where,
// 1. someFunc() must have a signature,
func someFunc(w http.ResponseWriter, r *http.Request)
// 2. That means, http.HandlerFunc(someFunc) is just a type casting of type http.HandlerFunc on a someFunc() and not a function call.
Now lets go to the http.Handle(),
// net/http/server.go
// Handle registers the handler for the given pattern
// in the DefaultServeMux.
// The documentation for ServeMux explains how patterns are matched.
func Handle(pattern string, handler Handler) {
DefaultServeMux.Handle(pattern, handler)
}
By looking at above snippet, you may have noticed that,
2nd argument accepts a Handler interface, that means, you can create any type and implement a ServeHTTP() method for it to satisfy this. Refer below example for proof.
type MyHandler struct{}
func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello World!")
}
func main() {
handler := MyHandler{}
http.Handle("/hello", &handler)
http.ListenAndServe()
}

Resources