Web servers are what makes the online world work and in this tutorial, you’ll dive headfirst into creating your own Go HTTP web server in a step-by-step manner.

Go is an extremely versatile programming language. You can do system programming in Go or even create highly interactive web applications. Due to its wide variety of applications, Go is seeing a lot of industry adoption over the years.

Let’s dive into the task of creating a simple web server in Go. In the next sections, we will learn how to set up a simple Go web server for beginners.

1 – A Brief Intro to Go

For creating your own Go HTTP web server, it’s crucial to grasp the pivotal role that Go plays in modern web development.

At its core, Go is engineered for efficiency and speed. This makes it a top choice for building highly concurrent web applications.

Also, over the years, Go has attracted a thriving community supported by a rich standard library.

In case this is your first foray into Go, I recommend going through this post on starting with Go where I explain how you can set it up for your development machine. I also talk about setting up a Go development environment for easy usage.

2 – Creating an HTTP Web Server with Go

With Go installed and ready on your system, it’s time to start creating our web server that can handle HTTP requests.

But what is a web server?

A web server acts as the gateway between your laptop or mobile device and an application running somewhere on the internet. From an application’s perspective, a web server handles incoming requests from millions of users like you and I and responds with the data needed.

To get started, create a project directory and execute the below command:

$ go mod init webserver

This command will create a file named go.mod within the project directory.

module webserver

go 1.20

Next, you can create a file main.go with the below code:

package main

import (

func handleRequest(w http.ResponseWriter, r *http.Request) {
	path := r.URL.Path

	message := fmt.Sprintf("You requested: %s", path)

	fmt.Fprintf(w, message)

func main() {

	http.HandleFunc("/", handleRequest)

	fmt.Println("Server is listening on port 8080...")

	http.ListenAndServe(":8080", nil)

Let’s understand what is going on over here in more detail:

  • At the very beginning, we import the net/http package that contains all the functionality necessary to create a basic web server in Go.
  • The handleRequest function takes two parameters – w http.ResponseWriter for sending the responses and r *http.Request for the incoming request object.
  • For demo purpose, we extract the r.URL.path property of the request object. This is basically the part of the URL that follows the domain.
  • Next, we generate a response message that includes the path. For example, “You requested: /test”.
  • Moving on, we use the fmt.Fprintf() function to write the message to the response writer. This function takes the response writer instance and the message as input.
  • In the main() function of the program, the first line http.HandleFunc() sets up an HTTP route or endpoint and the function that should handle the request. It specifies when a user accesses the root URL of the web server, the following function should be executed.
  • In this case, it’s the handleRequest() function.
  • Lastly, we call the ListenAndServe() method on the http object to start the webserver on port 8080.

3 – Additional Points

Few important points to discuss about the code we just wrote:


In the statement http.ListenAndServe(":8080", nil), we specify a colon before the port number. This indicates that the server should bind to all available network interfaces on the specific port.

In simple terms, we are telling our Go HTTP Web Server to listen on port 8080 for incoming requests from any available network interface on the local machine. For example, requests coming from http://localhost:8080 or in your web browser.


The nil in ListenAndServe is used as the value for the handler parameter for processing incoming HTTP requests.

In this case, passing nil indicates you want to use the default HTTP server mux provided by the http package.


The ‘*’ (asterisk) in *http.Request indicates that http.Request is a pointer to a struct type.

  • Pointers are good for the overall efficiency of handling the request. An HTTP request can contain a lot of data including headers, URL information and a request body. If you pass the entire request data by value, it would create a copy of all that data every time you passed it to a function.
  • It is also possible to modify the HTTP request data during the request lifecycle. Using a pointer allows us to work with the same request object throughout the lifecycle.


That’s all for this post.

In this post, we completed a step-by-step tutorial on creating an HTTP Webserver in Go from scratch.

It also involved exploring the fundamentals of Go, setting up a dev environment and getting into the concepts of web servers. Moreover, you learned about the importance of pointers in http.Request and the default server handler.

In the next post, you can learn how to handle routing in a Go web server.

If you have any queries about this post, please feel free to mention them in the comments section below.

Categories: BlogGolang

Saurabh Dashora

Saurabh is a Software Architect with over 12 years of experience. He has worked on large-scale distributed systems across various domains and organizations. He is also a passionate Technical Writer and loves sharing knowledge in the community.


Leave a Reply

Your email address will not be published. Required fields are marked *