├── README.md ├── code ├── arrays.go ├── maps.go ├── packages.go ├── slices.go ├── slices2.go ├── structs.go └── variables.go ├── intro-to-go-workshop.slide ├── labs ├── README.md └── docs │ ├── cross_compiling.md │ ├── csv2json_cli.md │ ├── csv2json_package.md │ ├── csv2json_package_exercise_answers.md │ ├── csv2json_package_tests.md │ ├── csv2json_server.md │ ├── csv2json_server_tests.md │ ├── docker.md │ ├── godep.md │ ├── godoc.md │ ├── hello_world.md │ ├── installing_go.md │ └── pinger.md └── speed_tour.md /README.md: -------------------------------------------------------------------------------- 1 | # Intro to Go Workshop 2 | 3 | ## Requirements 4 | 5 | - [Git](http://git-scm.com) 6 | - [Mercurial](http://mercurial.selenic.com) 7 | 8 | ### Install Git and Mercurial 9 | 10 | apt-get install git mercurial 11 | 12 | ### Configure Git 13 | 14 | git config --global user.name "Kelsey Hightower" 15 | git config --global user.email kelsey.hightower@gmail.com 16 | 17 | ### Set Environment Variables 18 | 19 | export docker_host=$docker_host_from_slide 20 | export username=kelseyhightower 21 | 22 | ## Speed Tour 23 | 24 | - [Speed Tour](speed_tour.md) 25 | 26 | ## Hands on Labs 27 | 28 | - [Hands on Labs](labs) 29 | -------------------------------------------------------------------------------- /code/arrays.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | locations := [3]string{ 7 | "Long Beach", 8 | "Atlanta", 9 | "Portland", 10 | } 11 | fmt.Printf("Number of locations: %d", len(locations)) 12 | } 13 | -------------------------------------------------------------------------------- /code/maps.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | ) 7 | 8 | func main() { 9 | m := make(map[string]string) 10 | m["name"] = "Kelsey" 11 | 12 | name, ok := m["name"] 13 | if !ok { 14 | log.Fatal("Name does not exist") 15 | } 16 | fmt.Println(name) 17 | 18 | for k, v := range m { 19 | fmt.Printf("Key: %s Value: %s", k, v) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /code/packages.go: -------------------------------------------------------------------------------- 1 | import( 2 | "fmt" 3 | "log" 4 | 5 | "github.com/kelseyhightower/targz" 6 | ) 7 | -------------------------------------------------------------------------------- /code/slices.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var locations = []string{ 6 | "Atlanta", 7 | "Portland", 8 | "New York", 9 | } 10 | 11 | func main() { 12 | for _, name := range locations { 13 | fmt.Printf("Name: %s\n", name) 14 | } 15 | middle := locations[1:2] 16 | fmt.Printf("%s\n", middle) 17 | } 18 | -------------------------------------------------------------------------------- /code/slices2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | ints := make([]int, 0) 7 | for i := 0; i <= 100; i++ { 8 | ints = append(ints, i) 9 | } 10 | fmt.Printf("%#v", ints) 11 | } 12 | -------------------------------------------------------------------------------- /code/structs.go: -------------------------------------------------------------------------------- 1 | // START 0 OMIT 2 | package main 3 | 4 | import "fmt" 5 | 6 | type Person struct { 7 | name string 8 | Location string 9 | } 10 | // END 0 OMIT 11 | // START 1 OMIT 12 | func NewPerson(name string) *Person { 13 | p := Person{ 14 | name: name, 15 | } 16 | return &p 17 | } 18 | 19 | func (p *Person) Name() string { 20 | return p.name 21 | } 22 | 23 | func (p *Person) SetName(name string) { 24 | p.name = name 25 | } 26 | 27 | func main() { 28 | p := NewPerson("Kelsey") 29 | fmt.Printf("Name: %s\n", p.Name()) 30 | p.Location = "Portland" 31 | fmt.Printf("Location: %s\n", p.Location) 32 | } 33 | // END 1 OMIT 34 | -------------------------------------------------------------------------------- /code/variables.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | var ( 6 | name string 7 | Location = "Portland" 8 | ) 9 | 10 | func main() { 11 | name = "Kelsey Hightower" 12 | distro := "CoreOS" 13 | fmt.Printf("Name: %s\nLocation: %s\nDistro: %s\n", name, Location, distro) 14 | } 15 | -------------------------------------------------------------------------------- /intro-to-go-workshop.slide: -------------------------------------------------------------------------------- 1 | Intro to Go Workshop 2 | Epicodus 3 | 10:00 3 May 2014 4 | Tags: go 5 | 6 | Kelsey Hightower 7 | Gopher 8 | kelsey.hightower@gmail.com 9 | @kelseyhightower 10 | 11 | * Wifi 12 | 13 | SSID 14 | 15 | epicodus 16 | Password 17 | 18 | stayfocused 19 | 20 | * Workshop Online 21 | 22 | https://github.com/kelseyhightower/intro-to-go-workshop 23 | 24 | * Speed Tour 25 | 26 | * Speed Tour 27 | 28 | Packages 29 | 30 | .code code/packages.go 31 | 32 | * Speed Tour 33 | 34 | Variables 35 | 36 | .play code/variables.go 37 | 38 | * Speed Tour 39 | 40 | Arrays 41 | 42 | .play code/arrays.go 43 | 44 | * Speed Tour 45 | 46 | Slices 47 | 48 | .play code/slices.go 49 | 50 | * Speed Tour 51 | 52 | Slices 53 | 54 | .play code/slices2.go 55 | 56 | * Speed Tour 57 | 58 | Maps 59 | 60 | .play code/maps.go 61 | 62 | * Speed Tour 63 | 64 | Structs 65 | 66 | .code code/structs.go /START 0 OMIT/,/END 0 OMIT/ 67 | 68 | * Speed Tour 69 | 70 | Structs 71 | 72 | .play code/structs.go /START 1 OMIT/,/END 1 OMIT/ 73 | 74 | * Hands on Exercises 75 | 76 | * Hands on Exercises 77 | 78 | Configure Git 79 | 80 | git config --global user.name "Kelsey Hightower" 81 | git config --global user.email kelsey.hightower@gmail.com 82 | 83 | Set Environment Variables 84 | 85 | export docker_host=173.255.117.47 86 | export username = kelseyhightower 87 | -------------------------------------------------------------------------------- /labs/README.md: -------------------------------------------------------------------------------- 1 | # Hands on Exercises 2 | 3 | - [Installing Go](docs/installing_go.md) 4 | - [Hello World](docs/hello_world.md) 5 | - [Code Walkthrough](docs/pinger.md) 6 | - [Documenting with GoDoc](docs/godoc.md) 7 | - [Package to convert CSV to JSON](docs/csv2json_package.md) 8 | - [Testing csv2json ](docs/csv2json_package_tests.md) 9 | - [CLI tool to convert CSV to JSON](docs/csv2json_cli.md) 10 | - [Managing Dependencies with Godep](docs/godep.md) 11 | - [HTTP API to convert CSV to JSON](docs/csv2json_server.md) 12 | - [Testing csv2json-server](docs/csv2json_server_tests.md) 13 | - [Cross Compiling](docs/cross_compiling.md) 14 | - [Deploy with Docker](docs/docker.md) 15 | -------------------------------------------------------------------------------- /labs/docs/cross_compiling.md: -------------------------------------------------------------------------------- 1 | # Cross Compiling 2 | 3 | ## Requirements 4 | 5 | - gcc 6 | 7 | ## Build the Tool Chains 8 | 9 | #### Change Directory 10 | 11 | cd /usr/local/go/src 12 | 13 | #### Run 14 | 15 | for os in linux windows darwin; do GOOS=${os} GOARCH=amd64 CGO_ENABLED=0 ./make.bash —no-clean; done 16 | 17 | **NOTE**: Make sure to not include the OS you are actually running in this list or you will end up with 18 | a build of Go that has CGO disabled. So if you are running on OSX, for exampple, this should be: 19 | 20 | for os in linux windows; do GOOS=${os} GOARCH=amd64 CGO_ENABLED=0 ./make.bash —no-clean; done 21 | 22 | ## Cross Compile csv2json_server 23 | 24 | #### Change Directory 25 | 26 | cd ${GOPATH}/src/github.com/${username}/csv2json-server 27 | 28 | #### Run 29 | 30 | GOOS=darwin GOARCH=amd64 go build -o csv2json-server main.go 31 | 32 | #### Inspect 33 | 34 | file csv2json-server 35 | 36 | ## Exercise 37 | 38 | ### Cross Compile for linux, windows, and darwin 39 | -------------------------------------------------------------------------------- /labs/docs/csv2json_cli.md: -------------------------------------------------------------------------------- 1 | # csv2json-cli 2 | 3 | CLI tool to convert CSV to JSON 4 | 5 | #### Create 6 | 7 | mkdir ${GOPATH}/src/github.com/${username}/csv2json-cli 8 | 9 | #### Change Directory 10 | 11 | cd ${GOPATH}/src/github.com/${username}/csv2json-cli 12 | 13 | #### Edit 14 | 15 | main.go 16 | 17 | - 18 | 19 | package main 20 | 21 | import ( 22 | "flag" 23 | "fmt" 24 | "log" 25 | "os" 26 | 27 | "github.com/kelseyhightower/csv2json" 28 | ) 29 | 30 | var ( 31 | infile string 32 | columns = []string{"Name","Date","Title"} 33 | ) 34 | 35 | func init() { 36 | flag.StringVar(&infile, "infile", "", "input file") 37 | } 38 | 39 | func main() { 40 | flag.Parse() 41 | if infile == "" { 42 | log.Fatal("Input file required") 43 | } 44 | f, err := os.Open(infile) 45 | if err != nil { 46 | log.Fatal(err) 47 | } 48 | defer f.Close() 49 | jsonData, err := csv2json.Convert(f, columns) 50 | if err != nil { 51 | log.Fatal(err) 52 | } 53 | fmt.Println(string(jsonData)) 54 | } 55 | 56 | #### Edit 57 | 58 | ${HOME}/famous-gophers.csv 59 | 60 | - 61 | 62 | Mac, 1947, The Goofy Gophers 63 | Tosh, 1947, The Goofy Gophers 64 | Samuel J. Gopher, 1966, Winnie the Pooh 65 | Chief Running Board, 1968, Go Go Gophers 66 | Ruffled Feathers, 1968, Go Go Gophers 67 | 68 | #### Build 69 | 70 | go build -o csv2json . 71 | 72 | #### Run 73 | 74 | ./csv2json -infile ${HOME}/famous-gophers.csv 75 | 76 | #### Version 77 | 78 | git init . 79 | git add main.go 80 | git commit -m "first commit" 81 | 82 | -------------------------------------------------------------------------------- /labs/docs/csv2json_package.md: -------------------------------------------------------------------------------- 1 | # csv2json 2 | 3 | Package to convert CSV to JSON 4 | 5 | #### Create 6 | 7 | mkdir ${GOPATH}/src/github.com/${username}/csv2json 8 | 9 | #### Change Directory 10 | 11 | cd ${GOPATH}/src/github.com/${username}/csv2json 12 | 13 | #### Edit 14 | 15 | csv2json.go 16 | 17 | - 18 | 19 | package csv2json 20 | 21 | import ( 22 | "encoding/csv" 23 | "encoding/json" 24 | "io" 25 | ) 26 | 27 | func Convert(r io.Reader, columns []string) ([]byte, error) { 28 | rows := make([]map[string]string, 0) 29 | csvReader := csv.NewReader(r) 30 | csvReader.TrimLeadingSpace = true 31 | for { 32 | record, err := csvReader.Read() 33 | if err == io.EOF { 34 | break 35 | } 36 | if err != nil { 37 | return nil, err 38 | } 39 | row := make(map[string]string) 40 | for i, n := range columns { 41 | row[n] = record[i] 42 | } 43 | rows = append(rows, row) 44 | } 45 | data, err := json.MarshalIndent(&rows, "", " ") 46 | if err != nil { 47 | return nil, err 48 | } 49 | return data, nil 50 | } 51 | 52 | #### Build 53 | 54 | go install . 55 | 56 | #### Inspect 57 | 58 | file ${GOPATH}/pkg/linux_amd64/github.com/${username}/csv2json.a 59 | 60 | #### Version 61 | 62 | git init . 63 | git add . 64 | git commit -m "first commit" 65 | -------------------------------------------------------------------------------- /labs/docs/csv2json_package_exercise_answers.md: -------------------------------------------------------------------------------- 1 | # Exercise Answers 2 | 3 | ## Write an additional test 4 | 5 | #### Change Directory 6 | 7 | cd ${GOPATH}/src/github.com/${username}/csv2json 8 | 9 | #### Edit 10 | 11 | csv2json_test.go 12 | 13 | - 14 | 15 | package csv2json 16 | 17 | import ( 18 | "bytes" 19 | "io/ioutil" 20 | "os" 21 | "testing" 22 | ) 23 | 24 | var columns = []string{"name", "email", "phone"} 25 | var want = `[ 26 | { 27 | "email": "ken@google.com", 28 | "name": "Ken Thompson", 29 | "phone": "555-5550" 30 | }, 31 | { 32 | "email": "rob@google.com", 33 | "name": "Rob Pike", 34 | "phone": "555-5551" 35 | }, 36 | { 37 | "email": "robert@google.com", 38 | "name": "Robert Griesemer", 39 | "phone": "555-5552" 40 | } 41 | ]` 42 | 43 | var input = ` 44 | Ken Thompson, ken@google.com, 555-5550 45 | Rob Pike, rob@google.com, 555-5551 46 | Robert Griesemer, robert@google.com, 555-5552 47 | ` 48 | 49 | func TestConvertWithBuffer(t *testing.T) { 50 | var b bytes.Buffer 51 | _, err := b.WriteString(input) 52 | if err != nil { 53 | t.Error(err) 54 | } 55 | got, err := Convert(bytes.NewReader(b.Bytes()), columns) 56 | if err != nil { 57 | t.Error(err) 58 | } 59 | if string(got) != want { 60 | t.Errorf("TestConvertWithBuffer(f, %s) = %s; want %s", 61 | columns, string(got), want) 62 | } 63 | } 64 | 65 | func TestConvertWithFile(t *testing.T) { 66 | tf, err := ioutil.TempFile("", "") 67 | if err != nil { 68 | t.Error(err) 69 | } 70 | defer os.Remove(tf.Name()) 71 | 72 | err = ioutil.WriteFile(tf.Name(), []byte(input), 0644) 73 | if err != nil { 74 | t.Error(err) 75 | } 76 | 77 | f, err := os.Open(tf.Name()) 78 | if err != nil { 79 | t.Error(err) 80 | } 81 | defer f.Close() 82 | 83 | got, err := Convert(f, columns) 84 | if err != nil { 85 | t.Error(err) 86 | } 87 | if string(got) != want { 88 | t.Errorf("TestConvertWithFile(f, %s) = %s; want %s", columns, string(got), want) 89 | } 90 | } 91 | 92 | #### Version 93 | 94 | git add csv2json_test.go 95 | git commit -m "add more tests" 96 | -------------------------------------------------------------------------------- /labs/docs/csv2json_package_tests.md: -------------------------------------------------------------------------------- 1 | # Testing the csv2json package 2 | 3 | #### Change Directory 4 | 5 | cd ${GOPATH}/src/github.com/${username}/csv2json 6 | 7 | #### Edit 8 | 9 | csv2json_test.go 10 | 11 | - 12 | 13 | package csv2json 14 | 15 | import ( 16 | "bytes" 17 | "testing" 18 | ) 19 | 20 | var columns = []string{"name", "email", "phone"} 21 | var want = `[ 22 | { 23 | "email": "ken@google.com", 24 | "name": "Ken Thompson", 25 | "phone": "555-5550" 26 | }, 27 | { 28 | "email": "rob@google.com", 29 | "name": "Rob Pike", 30 | "phone": "555-5551" 31 | }, 32 | { 33 | "email": "robert@google.com", 34 | "name": "Robert Griesemer", 35 | "phone": "555-5552" 36 | } 37 | ]` 38 | 39 | var input = ` 40 | Ken Thompson, ken@google.com, 555-5550 41 | Rob Pike, rob@google.com, 555-5551 42 | Robert Griesemer, robert@google.com, 555-5552 43 | ` 44 | 45 | func TestConvertWithBuffer(t *testing.T) { 46 | var b bytes.Buffer 47 | _, err := b.WriteString(input) 48 | if err != nil { 49 | t.Error(err) 50 | } 51 | got, err := Convert(bytes.NewReader(b.Bytes()), columns) 52 | if err != nil { 53 | t.Error(err) 54 | } 55 | if string(got) != want { 56 | t.Errorf("TestConvertWithBuffer(f, %s) = %s; want %s", 57 | columns, string(got), want) 58 | } 59 | } 60 | 61 | #### Run 62 | 63 | go test 64 | 65 | 66 | Run with the -v flag for verbose output: 67 | 68 | go test -v 69 | 70 | #### Version 71 | 72 | git add csv2json_test.go 73 | git commit -m "add tests" 74 | 75 | ## Exercise 76 | 77 | ### Write an additional test 78 | 79 | Create an additional test named TestConvertWithFile. 80 | 81 | #### Hint 82 | 83 | func TestConvertWithFile(t *testing.T) { 84 | tf, err := ioutil.TempFile("", "") 85 | if err != nil { 86 | t.Error(err) 87 | } 88 | defer os.Remove(tf.Name()) 89 | 90 | err = ioutil.WriteFile(tf.Name(), []byte(input), 0644) 91 | if err != nil { 92 | t.Error(err) 93 | } 94 | 95 | f, err := os.Open(tf.Name()) 96 | if err != nil { 97 | t.Error(err) 98 | } 99 | defer f.Close() 100 | 101 | // Test your results 102 | } 103 | 104 | -------------------------------------------------------------------------------- /labs/docs/csv2json_server.md: -------------------------------------------------------------------------------- 1 | # csv2json-server 2 | 3 | HTTP API to convert CSV to JSON 4 | 5 | #### Create 6 | 7 | mkdir ${GOPATH}/src/github.com/${username}/csv2json-server 8 | 9 | #### Change Directory 10 | 11 | cd ${GOPATH}/src/github.com/${username}/csv2json-server 12 | 13 | #### Edit 14 | 15 | main.go 16 | 17 | - 18 | 19 | package main 20 | 21 | import ( 22 | "log" 23 | "net/http" 24 | 25 | "github.com/kelseyhightower/csv2json" 26 | ) 27 | 28 | var ( 29 | columns = []string{"Name", "Date", "Title"} 30 | ) 31 | 32 | func csv2JsonServer(w http.ResponseWriter, req *http.Request) { 33 | jsonData, err := csv2json.Convert(req.Body, columns) 34 | defer req.Body.Close() 35 | if err != nil { 36 | http.Error(w, "Could not convert csv to json", 503) 37 | } 38 | w.Write(jsonData) 39 | } 40 | 41 | func main() { 42 | http.HandleFunc("/csv2json", csv2JsonServer) 43 | err := http.ListenAndServe(":8080", nil) 44 | if err != nil { 45 | log.Fatal("ListenAndServe: ", err) 46 | } 47 | } 48 | 49 | #### Build 50 | 51 | go build -o csv2json-server . 52 | 53 | #### Run 54 | 55 | ./csv2json-server 56 | 57 | Test with curl: 58 | 59 | curl -X POST http://localhost:8080/csv2json --data-binary @${HOME}/famous-gophers.csv 60 | 61 | #### Version 62 | 63 | git init . 64 | git add main.go 65 | git commit -m "first commit" 66 | 67 | #### Vendor 68 | 69 | godep save 70 | git add Godeps 71 | git commit -m "Manage dependencies with godep" 72 | 73 | ## Exercise 74 | 75 | ### Improve logging 76 | 77 | #### Hint 78 | 79 | import ( 80 | "log" 81 | ) 82 | -------------------------------------------------------------------------------- /labs/docs/csv2json_server_tests.md: -------------------------------------------------------------------------------- 1 | # Testing csv2json-server 2 | 3 | #### Change Directory 4 | 5 | cd ${GOPATH}/src/github.com/${username}/csv2json-server 6 | 7 | #### Edit 8 | 9 | api_test.go 10 | 11 | - 12 | 13 | package main 14 | 15 | import ( 16 | "bytes" 17 | "testing" 18 | "net/http" 19 | "net/http/httptest" 20 | ) 21 | 22 | type httpTestResponse struct { 23 | statusCode int 24 | body string 25 | } 26 | 27 | var csv2JsonServerPostBodyTest = ` 28 | Mac, 1947, The Goofy Gophers 29 | Tosh, 1947, The Goofy Gophers 30 | Samuel J. Gopher, 1966, Winnie the Pooh 31 | Chief Running Board, 1968, Go Go Gophers 32 | Ruffled Feathers, 1968, Go Go Gophers 33 | ` 34 | 35 | var csv2JsonServerWantBodyTest = `[ 36 | { 37 | "Date": "1947", 38 | "Name": "Mac", 39 | "Title": "The Goofy Gophers" 40 | }, 41 | { 42 | "Date": "1947", 43 | "Name": "Tosh", 44 | "Title": "The Goofy Gophers" 45 | }, 46 | { 47 | "Date": "1966", 48 | "Name": "Samuel J. Gopher", 49 | "Title": "Winnie the Pooh" 50 | }, 51 | { 52 | "Date": "1968", 53 | "Name": "Chief Running Board", 54 | "Title": "Go Go Gophers" 55 | }, 56 | { 57 | "Date": "1968", 58 | "Name": "Ruffled Feathers", 59 | "Title": "Go Go Gophers" 60 | } 61 | ]` 62 | 63 | func TestCsv2JsonServer(t *testing.T) { 64 | body := bytes.NewBufferString(csv2JsonServerPostBodyTest) 65 | req, err := http.NewRequest("POST", "http://example.com/csv2json", body) 66 | if err != nil { 67 | t.Error(err) 68 | } 69 | w := httptest.NewRecorder() 70 | csv2JsonServer(w, req) 71 | 72 | want := httpTestResponse{http.StatusOK, csv2JsonServerWantBodyTest} 73 | got := httpTestResponse{w.Code, w.Body.String()} 74 | if got != want { 75 | t.Errorf("Want: %#v, got %#v", want, got) 76 | } 77 | } 78 | 79 | #### Run 80 | 81 | go test -v 82 | 83 | Run using godep 84 | 85 | godep go test -v 86 | 87 | #### Version 88 | 89 | git add api_test.go 90 | git commit -m "add api tests" 91 | 92 | -------------------------------------------------------------------------------- /labs/docs/docker.md: -------------------------------------------------------------------------------- 1 | # Deploy with Docker 2 | 3 | ## Install Docker 4 | 5 | Installation Instructions: http://docs.docker.io/en/latest/installation 6 | 7 | #### Change Directory 8 | 9 | cd ${HOME} 10 | 11 | #### Download 12 | 13 | curl -o docker https://get.docker.io/builds/Linux/x86_64/docker-latest 14 | 15 | #### Install 16 | 17 | chmod +x docker 18 | sudo cp docker /usr/local/bin/ 19 | 20 | #### Configure 21 | 22 | export DOCKER_HOST=tcp://${docker_host}:4243 23 | 24 | 25 | ## Create a Dockerfile 26 | 27 | #### Change Directory 28 | 29 | cd ${GOPATH}/src/github.com/${username}/csv2json-server 30 | 31 | #### Edit 32 | 33 | Dockerfile 34 | 35 | - 36 | 37 | # csv2json-server 38 | # 39 | # VERSION 0.0.1 40 | 41 | FROM ubuntu 42 | EXPOSE 8080 43 | ADD csv2json-server /usr/local/bin/csv2json-server 44 | ENTRYPOINT ["/usr/local/bin/csv2json-server"] 45 | 46 | #### Build 47 | 48 | GOOS=linux go build -o csv2json-server . 49 | 50 | ## Build the Docker Image 51 | 52 | #### Run 53 | 54 | docker build -t ${username}/csv2json-server . 55 | 56 | #### Inspect 57 | 58 | docker images 59 | 60 | ## Run the Docker Image 61 | 62 | #### Run 63 | 64 | docker run -d -P ${username}/csv2json-server 65 | 66 | ## Testing with curl 67 | 68 | #### Inspect 69 | 70 | docker port ${container} 8080 71 | 72 | #### Run 73 | 74 | curl -X POST http://${docker_host}:${port}/csv2json --data-binary @${HOME}/famous-gophers.csv 75 | 76 | -------------------------------------------------------------------------------- /labs/docs/godep.md: -------------------------------------------------------------------------------- 1 | # Managing Dependencies with Godep 2 | 3 | ## Install Godep 4 | 5 | #### Change Directory 6 | 7 | cd ${HOME} 8 | 9 | #### Run 10 | 11 | go get github.com/tools/godep 12 | 13 | ## Save Dependencies 14 | 15 | #### Change Directory 16 | 17 | cd ${GOPATH}/src/github.com/${username}/csv2json-cli 18 | 19 | #### Inspect 20 | 21 | go list -json 22 | 23 | #### Vendor 24 | 25 | godep save 26 | 27 | #### Inspect 28 | 29 | cat Godeps/Godeps.json 30 | 31 | #### Inspect 32 | 33 | ls -R Godeps 34 | 35 | #### Version 36 | 37 | git add Godeps 38 | git commit -m "Manage dependencies with Godep" 39 | 40 | 41 | ## Building with Godep 42 | 43 | #### Run 44 | 45 | godep go build -o csv2json . 46 | 47 | ## Testing with Godep 48 | 49 | #### Run 50 | 51 | godep go test 52 | -------------------------------------------------------------------------------- /labs/docs/godoc.md: -------------------------------------------------------------------------------- 1 | # Documenting with GoDoc 2 | 3 | ## Clone the Pinger Repo 4 | 5 | #### Change Directory 6 | 7 | cd ${GOPATH}/src 8 | 9 | #### Run 10 | 11 | git clone https://github.com/kelseyhightower/pinger.git 12 | 13 | ## Add Comments 14 | 15 | #### Change Directory 16 | 17 | cd ${GOPATH}/src/pinger 18 | 19 | #### Edit 20 | 21 | ping/pinger.go 22 | 23 | - 24 | 25 | package ping 26 | 27 | import ( 28 | "fmt" 29 | "net/http" 30 | "time" 31 | ) 32 | 33 | // Objects implementing the Pinger interface can be used to contact 34 | // a particular website and return roundtrip results. 35 | type Pinger interface { 36 | Ping() (*Result, error) 37 | } 38 | 39 | // Result represents the results of a website ping. 40 | type Result struct { 41 | Url string 42 | Duration time.Duration 43 | } 44 | 45 | // Target represents a target website. 46 | type Target struct { 47 | url string 48 | } 49 | 50 | // NewTarget returns a *Target 51 | func NewTarget(url string) *Target { 52 | return &Target{url} 53 | } 54 | 55 | // Ping makes an HTTP GET request to a target identified by t.url 56 | // and records total roundtrip duration. 57 | func (t *Target) Ping() (*Result, error) { 58 | startTime := time.Now() 59 | res, err := http.Get(t.url) 60 | duration := time.Since(startTime) 61 | 62 | if err != nil { 63 | return nil, err 64 | } 65 | defer res.Body.Close() 66 | 67 | if res.StatusCode != http.StatusOK { 68 | return nil, fmt.Errorf("ping error from %s bad status: %d", t.url, res.StatusCode) 69 | } 70 | return &Result{t.url, duration}, nil 71 | } 72 | 73 | #### Edit 74 | 75 | ping/doc.go 76 | 77 | - 78 | 79 | // Package ping provides Pinger. 80 | package ping 81 | 82 | #### Edit 83 | 84 | ping/example_test.go 85 | 86 | - 87 | 88 | package ping_test 89 | 90 | import ( 91 | "fmt" 92 | 93 | . "pinger/ping" 94 | ) 95 | 96 | func ExampleNewTarget() { 97 | t := NewTarget("http://google.com") 98 | res, err := t.Ping() 99 | if err != nil { 100 | fmt.Print(err) 101 | } 102 | fmt.Printf("%s - %s", res.Url, res.Duration) 103 | } 104 | 105 | #### Run 106 | 107 | godoc -http=":6060" 108 | 109 | #### Visit 110 | 111 | http://localhost:6060/pkg 112 | -------------------------------------------------------------------------------- /labs/docs/hello_world.md: -------------------------------------------------------------------------------- 1 | # Hello World 2 | 3 | #### Create 4 | 5 | mkdir ${GOPATH}/src/hello 6 | 7 | #### Change Directory 8 | 9 | cd ${GOPATH}/src/hello 10 | 11 | #### Edit 12 | 13 | main.go 14 | 15 | - 16 | 17 | package main 18 | 19 | import ( 20 | "fmt" 21 | ) 22 | 23 | func main() { 24 | fmt.Println("Hello World") 25 | } 26 | 27 | #### Build 28 | 29 | go build -o hello . 30 | 31 | #### Run 32 | 33 | ./hello 34 | -------------------------------------------------------------------------------- /labs/docs/installing_go.md: -------------------------------------------------------------------------------- 1 | # Installing Go 2 | 3 | ## Installation 4 | 5 | #### Change Directory 6 | 7 | cd ${HOME} 8 | 9 | ### Install a binary distribution 10 | 11 | #### Run 12 | 13 | wget https://go.googlecode.com/files/go1.2.linux-amd64.tar.gz 14 | tar -xvf go1.2.linux-amd64.tar.gz -C /usr/local 15 | 16 | ## Setup the Workspace 17 | 18 | ### GOPATH 19 | 20 | #### Edit 21 | 22 | ${HOME}/.bashrc 23 | 24 | - 25 | 26 | export GOPATH="${HOME}/go" 27 | export PATH="/usr/local/go/bin:${GOPATH}/bin:$PATH" 28 | 29 | #### Activate: 30 | 31 | source ${HOME}/.bashrc 32 | 33 | ### Workspace Directories 34 | 35 | #### Create the directories on Unix 36 | 37 | mkdir -p ${GOPATH}/src 38 | mkdir -p ${GOPATH}/pkg 39 | mkdir -p ${GOPATH}/bin 40 | mkdir -p ${GOPATH}/src/github.com/${username} 41 | 42 | ### Check the Go Environment 43 | 44 | go env 45 | 46 | - 47 | 48 | GOARCH="amd64" 49 | GOBIN="" 50 | GOCHAR="6" 51 | GOEXE="" 52 | GOHOSTARCH="amd64" 53 | GOHOSTOS="darwin" 54 | GOOS="darwin" 55 | GOPATH="/Users/kelseyhightower/go" 56 | GORACE="" 57 | GOROOT="/usr/local/go" 58 | GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64" 59 | TERM="dumb" 60 | CC="clang" 61 | GOGCCFLAGS="-g -O2 -fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fno-common" 62 | CXX="clang++" 63 | CGO_ENABLED="1" 64 | -------------------------------------------------------------------------------- /labs/docs/pinger.md: -------------------------------------------------------------------------------- 1 | # pinger 2 | 3 | Log response times from a list of websites 4 | 5 | #### Create 6 | 7 | mkdir ${GOPATH}/src/pinger 8 | mkdir ${GOPATH}/src/pinger/ping 9 | 10 | #### Change Directory 11 | 12 | cd ${GOPATH}/src/pinger 13 | 14 | #### Edit 15 | 16 | main.go 17 | 18 | - 19 | 20 | package main 21 | 22 | import ( 23 | "sync" 24 | 25 | "pinger/ping" 26 | ) 27 | 28 | func main() { 29 | targets := []string{ 30 | "http://google.com", 31 | "http://puppetlabs.com", 32 | "http://newrelic.com", 33 | } 34 | work := make(chan ping.Pinger) 35 | result := make(chan *ping.Result) 36 | 37 | var wg sync.WaitGroup 38 | wg.Add(2) 39 | go pinger(work, result, &wg) 40 | go printer(result, &wg) 41 | 42 | for _, t := range targets { 43 | work <- ping.NewTarget(t) 44 | } 45 | close(work) 46 | wg.Wait() 47 | } 48 | 49 | #### Edit 50 | 51 | pinger.go 52 | 53 | - 54 | 55 | package main 56 | 57 | import ( 58 | "log" 59 | "sync" 60 | 61 | "pinger/ping" 62 | ) 63 | 64 | func pinger(work chan ping.Pinger, result chan *ping.Result, wg *sync.WaitGroup) { 65 | for { 66 | w, ok := <-work 67 | if !ok { 68 | break 69 | } 70 | res, err := w.Ping() 71 | if err != nil { 72 | log.Printf("pinger: %s", err) 73 | continue 74 | } 75 | result <- res 76 | } 77 | close(result) 78 | wg.Done() 79 | } 80 | 81 | func printer(result chan *ping.Result, wg *sync.WaitGroup) { 82 | for { 83 | res, ok := <-result 84 | if !ok { 85 | break 86 | } 87 | log.Printf("ping %s %s", res.Url, res.Duration) 88 | } 89 | wg.Done() 90 | } 91 | 92 | #### Edit 93 | 94 | ping/pinger.go 95 | 96 | - 97 | package ping 98 | 99 | import ( 100 | "fmt" 101 | "net/http" 102 | "time" 103 | ) 104 | 105 | type Pinger interface { 106 | Ping() (*Result, error) 107 | } 108 | 109 | type Result struct { 110 | Url string 111 | Duration time.Duration 112 | } 113 | 114 | type Target struct { 115 | url string 116 | } 117 | 118 | func NewTarget(url string) *Target { 119 | return &Target{url} 120 | } 121 | 122 | func (t *Target) Ping() (*Result, error) { 123 | startTime := time.Now() 124 | res, err := http.Get(t.url) 125 | duration := time.Since(startTime) 126 | 127 | if err != nil { 128 | return nil, err 129 | } 130 | defer res.Body.Close() 131 | 132 | if res.StatusCode != http.StatusOK { 133 | return nil, fmt.Errorf("ping error from %s bad status: %d", t.url, res.StatusCode) 134 | } 135 | return &Result{t.url, duration}, nil 136 | } 137 | 138 | #### Build 139 | 140 | go build -o pinger . 141 | 142 | #### Run 143 | 144 | ./pinger 145 | -------------------------------------------------------------------------------- /speed_tour.md: -------------------------------------------------------------------------------- 1 | # Speed Tour 2 | 3 | ## Packages 4 | 5 | import( 6 | "fmt" 7 | "log" 8 | 9 | "github.com/kelseyhightower/targz" 10 | ) 11 | 12 | ## Variables 13 | 14 | var ( 15 | name string 16 | Location = "Portland" 17 | ) 18 | 19 | func main() { 20 | name = "Kelsey Hightower" 21 | distro := "CoreOS" 22 | fmt.Printf("Name: %s\nLocation: %s\nDistro: %s\n", name, Location, distro) 23 | } 24 | 25 | 26 | ## Arrays 27 | 28 | func main() { 29 | locations := [3]string{ 30 | "Long Beach", 31 | "Atlanta", 32 | "Portland", 33 | } 34 | fmt.Printf("Number of locations: %d", len(locations)) 35 | } 36 | 37 | ## Slices 38 | 39 | func main() { 40 | locations := []string{ 41 | "Long Beach", 42 | "Atlanta", 43 | "Portland", 44 | "New York", 45 | "Denver", 46 | "Dallas", 47 | } 48 | for _, name := range locations { 49 | fmt.Printf("Name: %s\n", name) 50 | } 51 | 52 | middleTwo := locations[2:4] 53 | fmt.Printf("%#v", middleTwo) 54 | 55 | ints := make([]int, 0) 56 | for i := 0; i <= 100; i++ { 57 | ints = append(ints, i) 58 | } 59 | fmt.Printf("%#v", ints) 60 | } 61 | 62 | 63 | ## Maps 64 | 65 | func main() { 66 | m := make(map[string]string) 67 | m["name"] = "Kelsey" 68 | 69 | name, ok := m["name"] 70 | if !ok { 71 | log.Fatal("Name does not exist") 72 | } 73 | fmt.Println(name) 74 | 75 | for k, v := range m { 76 | fmt.Printf("Key: %s Value: %s", k, v) 77 | } 78 | } 79 | 80 | ## Functions 81 | 82 | func ping(url string) bool { 83 | resp, err := http.Get(string) 84 | if err != nil { 85 | return false 86 | } 87 | if resp.StatusCode != http.StatusOK { 88 | return false 89 | } 90 | return true 91 | } 92 | 93 | ## Structs 94 | 95 | type Person struct { 96 | name string 97 | Location string 98 | } 99 | 100 | func NewPerson(name string) *Person { 101 | p := Person{ 102 | name: name, 103 | } 104 | return &p 105 | } 106 | 107 | func (p *Person) Name() string { 108 | return p.name 109 | } 110 | 111 | func (p *Person) SetName(name string) { 112 | p.name = name 113 | } 114 | 115 | func main() { 116 | p := NewPerson("Kelsey") 117 | fmt.Printf("Name: %s\n", p.Name()) 118 | 119 | p.Location = "Portland" 120 | fmt.Printf("Location: %s\n", p.Location) 121 | } 122 | 123 | ## Channels and Goroutines 124 | 125 | func doubler(input, output chan int) { 126 | for { 127 | i := <-input 128 | output <- i * 2 129 | } 130 | } 131 | 132 | func printer(output chan int) { 133 | for { 134 | fmt.Printf("%d\n", <-output) 135 | } 136 | } 137 | 138 | func main() { 139 | input := make(chan int) 140 | output := make(chan int) 141 | 142 | go doubler(input, output) 143 | go printer(output) 144 | 145 | for i := 0; i <= 10; i++ { 146 | input <- i 147 | } 148 | time.Sleep(time.Duration(1) * time.Second) 149 | } 150 | --------------------------------------------------------------------------------