Golang http client and server Tutorial

Most of the time when you are writing a software with golang you will need to write code for http client or server. This tutorial will help you to understand how to work with http in golang.

Http Client

Golang come with greate http standard library that we can easily use right away. So here is an example to write golang http client.

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

func main() {
	url := "https://poetrydb.org/title/spring/title"
	response, err := http.Get(url)
	if err != nil {
		log.Fatalf("err %q\n", err)
	}
	defer response.Body.Close()

	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		log.Fatalf("err %q\n", err)
	}

	text := string(body[:])
	fmt.Println(text)
}

Here's the detail about the code.

  • net/http is the standard library to work with http in golang/.
  • log.Fatalf("err %q\n", err) we use log fatal to stop the program if the error happen since we don't want to go to the next proses, in real world you might don't need to stop the proses using log fatal, you might need return err.
  • http.Get return two data response and err, the response is represent the data like status code, body etc
  • response.Body does not have string value, it return io.ReadCloser interface so we need to use ioutil.ReadAll(response.Body) to convert the response to byte from there we can turn that data to string or file as whatever we need.

If you need to do a post request you can use this.

func postRequest(url string) error {
	body, err := json.Marshal(map[string]interface{}{
		"title": "Some",
		"id":    123,
	})
	if err != nil {
		return err
	}

	payloadBodyRaw := bytes.NewReader(body)
	_, err = http.Post(url, "application/json", payloadBodyRaw)

	if err != nil {
		return err
	}
	return nil
}

Let's breakdown :

  • encoding/json is the package to convert a data to json string or the other way around
  • bytes.NewReader(body) we use this to convert our string to bytes reader data
  • _, err = http.Post(url, "application/json", payloadBodyRaw) and then this code is to triger request to be send to the server.

Http Server

Writing http server is also easy, here's an example of the http service.

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
)

func main() {
	mux := http.NewServeMux()
	mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
		enc := json.NewEncoder(writer)
		err := enc.Encode(map[string]interface{}{
			"title": "Some",
			"id":    123,
		})
		if err != nil {
			msg := fmt.Sprintf("err: %s", err.Error())
			_, _ = writer.Write([]byte(msg))
			return
		}
	})
	err := http.ListenAndServe(":8000", mux)
	if err != nil {
		log.Fatalf("error starting the server: %q", err)
	}
}

Let's breakdown the code :

  • mux := http.NewServeMux() standard library to work with route and handler
  • mux.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) we use this to register the handler
  • err := http.ListenAndServe(":8000", mux) run the http server until it done doing all the process.
  • and the other just the error management.

See full source code here.