Creating an HTTP server in Go
June 18, 2024
Introduction
This tutorial would show you how to create a basic http server in Go lang. For this we’ll need Go 1.22 as it offers built-in enhanced routing that would save us time in thinking what framework should we use.
Folder Structure
go.mod
go.work
main.go
- handlers/
home.go
articles.go
Initilizing Project
Create project.
$ mkdir http-server; cd http-server;
Initialize project.
$ go mod init http-server;
$ go work init .; # enable workspaces
Creating the router
NewServeMux
would return a ServeMux
that would serve us our router for the application.
Let’s create barebone http server first to try it out.
package main
import (
"fmt"
"log"
"net/http"
)
func HomeRoute(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello World!")
}
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/{$}", HomeRoute) // <--- `/{$}` only matches `/`
err := http.ListenAndServe(":3000", mux)
if err != nil {
log.Fatalln("Cannot run the server", err)
}
}
Method Specific Route
To filter specific request method to a route, we could use a prefix to identify the target request method.
- mux.HandleFunc("/{$}", HomeRoute)
+ mux.HandleFunc("GET /{$}", HomeRoute)
Learn more about ServeMux patterns
Testing the application…
GET method has response
$ curl localhost:3000
Hello World!
POST method throws an error
$ curl -XPOST localhost:3000
Method Not Allowed
Getting Path Value
One of the biggest game changer introduced in Go 1.22 is the ability to read url paths.
func ArticlesRoute(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Reading article", r.PathValue("article"))
}
Register the path:
mux.HandleFunc("/articles/{article}", ArticlesRoute)
What do we have now?
package main
import (
"fmt"
"log"
"net/http"
)
func HomeRoute(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello World!")
}
+ func ArticlesRoute(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintln(w, "Reading article", r.PathValue("article"))
+ }
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /{$}", HomeRoute)
+ mux.HandleFunc("/articles/{article}", ArticlesRoute)
err := http.ListenAndServe(":3000", mux)
if err != nil {
log.Fatalln("Cannot run the server", err)
}
}
Testing the new route
$ curl localhost:3000/articles/hello-world
Reading article hello-world
Organizing our project
To better organize our code, we’ll create a new module.
mkdir handlers;
Then move our route to each separate module inside handlers
// ./handlers/home.go
package handlers
import (
"fmt"
"net/http"
)
func HomeRoute(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello World!")
}
// ./handlers/articles.go
package handlers
import (
"fmt"
"net/http"
)
func ArticlesRoute(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Reading article", r.PathValue("article"))
}
Update our main.go
to read the handlers
submodule.
package main
import (
"http-server/handlers"
"log"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /{$}", handlers.HomeRoute)
mux.HandleFunc("/articles/{article}", handlers.ArticlesRoute)
err := http.ListenAndServe(":3000", mux)
if err != nil {
log.Fatalln("Cannot run the server", err)
}
}
Conclusion
Here we have learned about how to create a basic HTTP server using Go and how to utilize. Hoping that this tutorial helped kickstart your dream project in Go.
To see the full project in this tutorial click here.