If you ever have the need to combine a plain HTTP webserver with a gRPC server on the same port, then you can use cmux to do so.

You can do something like:

package main
import (
func main() {
// Create the listener
l, err := net.Listen("tcp", ":8080")
if err != nil {
// Create a new cmux instance
m := cmux.New(l)
// Create a grpc listener first
grpcListener := m.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"))
// All the rest is assumed to be HTTP
httpListener := m.Match(cmux.Any())
// Create the servers
grpcServer := grpc.NewServer()
httpServer := &http.Server{}
// Use an error group to start all of them
g := errgroup.Group{}
g.Go(func() error {
return grpcServer.Serve(grpcListener)
g.Go(func() error {
return httpServer.Serve(httpListener)
g.Go(func() error {
return m.Serve()
// Wait for them and check for errors
err = g.Wait()
if err != nil {

This also demonstrates how the errgroup module can be used. The Wait method blocks until all function calls from the Go method have returned, then returns the first non-nil error (if any) from them.

PS: the example itself doesn't actually do something useful as we didn't register any gRPC functions neither did I define HTTP handlers.