Skip to content

Commit

Permalink
added http wc assets and kata
Browse files Browse the repository at this point in the history
  • Loading branch information
davecheney committed Dec 9, 2016
1 parent bb5c8cf commit 76ef541
Show file tree
Hide file tree
Showing 11 changed files with 82,515 additions and 22 deletions.
3,736 changes: 3,736 additions & 0 deletions books/alice.txt

Large diffs are not rendered by default.

4,236 changes: 4,236 additions & 0 deletions books/christmas-carol.txt

Large diffs are not rendered by default.

15,973 changes: 15,973 additions & 0 deletions books/dracula.txt

Large diffs are not rendered by default.

22,659 changes: 22,659 additions & 0 deletions books/moby.txt

Large diffs are not rendered by default.

13,427 changes: 13,427 additions & 0 deletions books/pride-and-prejudice.txt

Large diffs are not rendered by default.

13,052 changes: 13,052 additions & 0 deletions books/sherlock.txt

Large diffs are not rendered by default.

9,209 changes: 9,209 additions & 0 deletions books/tom-sawyer.txt

Large diffs are not rendered by default.

120 changes: 98 additions & 22 deletions introduction-to-go.slide
Expand Up @@ -1637,6 +1637,94 @@ The format of the JSON tag is documented on the [[https://golang.org/pkg/encodin

The code for this kata is in `$GOPATH/src/katas/jsonenc`

* Writing http servers

Go's [[https://golang.org/pkg/net/http][`net/http`]] library can be used to write production web applications.

Writing web servers in Go can be as simple as a few lines. Here is an example:

.play -edit src/http/http1.go

* Writing http servers (cont.)

This is a simple HTTP handler

func index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "This is the index page")
}

it takes two pameters

- `w`, a `http.ResponseWriter` which is used to send data to the client
- `r`, a `http.Request` which contains the uri, query parameters, and request body.

mux := http.NewServeMux()

`http.NewServeMux` returns a `ServeMux`, what we usually call a HTTP router.

* Writing http servers (cont.)

mux.HandleFunc("/", index)

Registers our `index` function, with the top level route, `"/"`.

http.ListenAndServe(":8000", mux)

Opens a socket on port 8080 and sends and requests to our `mux` (our router).

`http.ListenAndServe` won't return unless something happens to that listening socket (wifi drops, cable unplugs)

* go get

`go`get` is a simple wrapper around `git` that knows how fetch packages from GitHub (and a few other places).

If a package's import path follows the `go`get` convention, `go`get` knows how to fetch the source code and download it to your `$GOPATH`.

`go`get` isn't a complete dependency manager like rubygems or npm, etc, but it good enough for writing many applications.

We'll use `go`get` to fetch the source for `gorilla/mux`, a more advanced HTTP router

% go get github.com/gorilla/mux
% ls $GOPATH/src/github.com/gorilla/mux
LICENSE context_gorilla.go context_native_test.go mux_test.go
README.md context_gorilla_test.go doc.go old_test.go
bench_test.go context_native.go mux.go regexp.go
route.go

* Using gorilla/mux

The standard HTTP router, `http.ServeMux` is quite basic, so we'll upgrade to the `gorilla/mux` http router.

.play -edit src/http/http2.go

* Line counting HTTP service

Let's write a HTTP service that counts the lines in a book via http.

Features:

- When the client requests `/books/{book}` we look up the book and return the number of lines counted.
- The response to the client should be in JSON format and include the number of lines and the title of the book.
- Book directory is configurable.

% ./httpwc ../../../books/ &
[1] 17554
% curl http://localhost:8080/books/moby.txt
{"title":"moby.txt","lines":"22659"}

The code for this kata is in `$GOPATH/src/katas/httpwc`

* Time for a break

* Concurrency

* Go

* Channels

* Select


* Packages and applications

- how to write a package
Expand All @@ -1663,23 +1751,6 @@ _Notes_
- Comments directly preceed the thing they apply to, don't put an extra newline in between the comment and the symbol
- You should comment both Public and private symbols, but godoc will only show you the documents


* Conclusion

* Conclusion

Thank you very much for participating today, I hope that you enjoyed yourself and are encouraged to learn more about Go.

I would like to recommend several online resources:

.link https://tour.golang.org/welcome/1 tour.golang.org
.link https://gobyexample.com/ Go by example

I would like to recommend two books:

.link https://www.amazon.co.jp/exec/obidos/ASIN/4621300253 プログラミング言語Go
.link https://www.amazon.co.jp/exec/obidos/ASIN/477418392X/ みんなのGo言語【現場で使える実践テクニック】

* Out of scope

Stuff that is out of scope for a one day event
Expand Down Expand Up @@ -1740,14 +1811,19 @@ Most of you will be comfortable with a _function_scoped_ variable shadowing a _p

But a _block_scoped_ variable shadowing a _function_scoped_ variable may be surprising.

* Empty Interface
* Conclusion

* Conclusion

* Go install
Thank you very much for participating today, I hope that you enjoyed yourself and are encouraged to learn more about Go.

* Sorting
I would like to recommend several online resources:

maps in Go are not storted.
.link https://tour.golang.org/welcome/1 tour.golang.org
.link https://gobyexample.com/ Go by example

- introduces sort, reflect
I would like to recommend two books:

.link https://www.amazon.co.jp/exec/obidos/ASIN/4621300253 プログラミング言語Go
.link https://www.amazon.co.jp/exec/obidos/ASIN/477418392X/ みんなのGo言語【現場で使える実践テクニック】

16 changes: 16 additions & 0 deletions src/http/http1.go
@@ -0,0 +1,16 @@
package main

import (
"fmt"
"net/http"
)

func index(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "This is the index page")
}

func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", index)
http.ListenAndServe(":8000", mux)
}
20 changes: 20 additions & 0 deletions src/http/http2.go
@@ -0,0 +1,20 @@
package main

import (
"fmt"
"net/http"

"github.com/gorilla/mux"
)

func greet(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
name := vars["name"]
fmt.Fprintf(w, "今日は %s", name)
}

func main() {
r := mux.NewRouter()
r.HandleFunc("/greet/{name}", greet)
http.ListenAndServe(":8000", r)
}
89 changes: 89 additions & 0 deletions src/katas/httpwc/answer.go
@@ -0,0 +1,89 @@
package main

import (
"bufio"
"encoding/json"
"log"
"net/http"
"os"
"path/filepath"

"github.com/gorilla/mux"
)

var booksdir string

type JSONResult struct {
Title string `json:"title"`
Lines int `json:"lines,string"`
}

func bookController(w http.ResponseWriter, r *http.Request) {
// get the name of the book
vars := mux.Vars(r)
book, ok := vars["book"]
if !ok {
http.Error(w, "no book specified", 404)
return
}

// turn the name of the book into a file path
path := filepath.Join(booksdir, book)

// count the lines in the book
lines, err := countLines(path)

// if there was an error, report it back to the client and return
if err != nil {
http.Error(w, err.Error(), 500)
return
}

// create our JSON result value
res := &JSONResult{
Title: book,
Lines: lines,
}

// create a JSON encoded using w to write JSON back to the client
enc := json.NewEncoder(w)
enc.Encode(res)
}

func countLines(path string) (int, error) {
f, err := os.Open(path)
if err != nil {
return 0, err
}
defer f.Close()

sc := bufio.NewScanner(f)
var lines int
for sc.Scan() {
lines++
}
err = sc.Err()
return lines, err
}

func main() {
// check that os.Args[1] has the books directory
if len(os.Args) < 2 {
log.Fatal("usage: %s /path/to/books", os.Args[0])
}

// record the books directory
booksdir = os.Args[1]

// set up our router
r := mux.NewRouter()

// register /books/{book} handler
r.HandleFunc("/books/{book}", bookController)

// listen and serve for ever
err := http.ListenAndServe(":8080", r)
if err != nil {
log.Fatal(err)
}
}

0 comments on commit 76ef541

Please sign in to comment.