Another strong component of Go is the standard library. It is structured much like the Unix/Linux operating system. There are lots of small components that can be combined together for more complex tasks. There are also indespensible, modern primitives such as the ability to create a networking server.
Create a web-server that exposes a typical AppNexus "status" endpoint. The web-server will support the following route
GET /status
In addition to supporting this route, all other routes that do not have both this HTTP method and
this path will return a 404
status code with some descriptive text that the route requested could
not be found.
The status route that we define will return a simple 1-line response with the format:
status: {UP, DOWN}
The {...}
bit means just one of the listed values is used. For example: status: UP
could be a complete
response. This return status can be static or random, your choise. The next section will give you some goals
for making it dynamic, so don't go crazy until you get this working first.
Now that we have a web-server, let's add an asynchronous process that computes a "reliability" percentage.
If that percentage drops below 75%, then we'll consider the application UNSTABLE
and if it drops below
50% then we'll say the service is DOWN
.
The response format will change to:
status: {UP, DOWN, UNSTABLE}
reliability: XX percent
Note the addition of the UNSTABLE
state as well as the second line which returns our reliabiity score as
a percentage (between 0 and 100).
In addition, we will also add two new endpoints as well:
POST /status/manual-down
POST /status/un-manual-down
The manual-down
route allows you to override any automatic detection of up/down to put the service
in a DOWN
state. The un-manual-down
removes this override but does not force the service into
an UP
status.
Hello, World web-server
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Println("%s: %s", r.Method, r.URL.Path)
fmt.Fprintf(w, "Hello, World")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
Return 404 NOT FOUND
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Route not found")
}
func main() {
// all requests starting with "/" are sent to handler
// so essentially, this is our "root" handler where all
// requests flow
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
Generate Random Float Values playground
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
for i := 0; i < 10; i++ {
fmt.Println(rand.Float64())
}
}
Update Shared Struct with Mutexes playground
package main
import (
"fmt"
"sync"
"time"
)
type Counter struct {
sync.Mutex
A int
}
func update(counter *Counter) {
for i := 0; i < 100; i++ {
counter.Lock()
counter.A += 1
counter.Unlock()
}
}
func main() {
cnt := &Counter { A: 0 }
go update(cnt)
update(cnt)
time.Sleep(1000)
fmt.Println(cnt.A)
}