Skip to content

Instantly share code, notes, and snippets.

@JohnMurray
Created August 10, 2017 21:28
Show Gist options
  • Save JohnMurray/2f9552c920bc6b10bd9787f4f72163a6 to your computer and use it in GitHub Desktop.
Save JohnMurray/2f9552c920bc6b10bd9787f4f72163a6 to your computer and use it in GitHub Desktop.
Challenge 2 of Go lunch-and-learn

Web Server

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.

Goal

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.

Stretch Goal

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.

Cheet Sheet

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)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment