golang building a simple server is pretty simple, here are three ways to rewrite it from the ground up internally

  • The first program uses the default DefaultServeMux and default Server structure.
  • The second will use a custom handler
  • The third will use a custom Server structure

In terms of execution efficiency, the third one is the fastest to execute, after all, it’s unencapsulated.

golang http server

The program below starts a web server at your localhost port 8080. It has one route, namely the / route. If you open the url in the browser, it will output “version 1”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"io"
"log"
"net/http"
)
func main() {
// Set routing rules
http.HandleFunc("/", Tmp)

//Use the default DefaultServeMux.
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal(err)
}
}

func Tmp(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "version 1")
}

This is the most common way to create a server without thinking too much about it!

golang http server

Routes

You can create more than one route. Mux is used to control access to the route by implementing a Handler registration into Mux.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

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

type myHandler struct{}

func (*myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "URL: "+r.URL.String())
}

func Tmp(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "version 2")
}


func main(){
mux := http.NewServeMux()

// Register routes and register handlers in this form.
mux.Handle("/",&myHandler{})

mux.HandleFunc("/tmp", Tmp)

//http.ListenAndServe uses the default server structure.
err := http.ListenAndServe(":8080", mux)
if err != nil {
log.Fatal(err)
}
}

golang http router

Listening and implementing http services with a custom server. In the examle below we define a route like mux["/tmp"].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package main

import (
"io"
"log"
"net/http"
"time"
)

//Define a map to implement routing table.
var mux map[string]func(http.ResponseWriter , *http.Request)

func main(){
server := http.Server{
Addr: ":8080",
Handler: &myHandler{},
ReadTimeout: 5*time.Second,
}

mux = make(map[string]func(http.ResponseWriter, *http.Request))
mux["/tmp"] = Tmp
err := server.ListenAndServe()
if err != nil {
log.Fatal(err)
}
}

type myHandler struct{}

func (*myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
// Implement route forwarding
if h, ok := mux[r.URL.String()];ok{
//Implement route forwarding with this handler, the corresponding route calls the corresponding func.
h(w, r)
return
}
io.WriteString(w, "URL: "+r.URL.String())
}

func Tmp(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "version 3")
}

The above three ways are actually the unpacking of the encapsulation, using a custom way to rewrite the underlying structure, you can better understand the net/http package.