├── templates ├── slide.tmpl ├── code.tmpl └── layout.tmpl ├── 14-cli ├── TODO ├── 01-invocation │ └── example1 │ │ └── child.go ├── 02-streams │ ├── example1 │ │ └── parent.go │ └── example2 │ │ └── pipeline.go ├── 03-flow │ ├── example1 │ │ └── parent.go │ └── readme.md └── 04-patterns │ └── readme.md ├── 10-testing ├── 05-profiling │ └── curl.sh ├── 03-caching │ ├── figure1.png │ ├── caching_test.go │ └── caching.go ├── 02-prediction │ ├── figure1.png │ ├── figure2.png │ └── prediction_test.go ├── 01-testing │ ├── example4 │ │ ├── example4.go │ │ └── handlers │ │ │ ├── handlers.go │ │ │ ├── handlers_example_test.go │ │ │ └── handlers_test.go │ ├── example1 │ │ └── example1_test.go │ └── example2 │ │ └── example2_test.go ├── readme.md ├── exercises │ ├── template1 │ │ └── bench_test.go │ └── exercise1 │ │ └── bench_test.go └── 04-godebug │ └── godebug.go ├── 00-slides ├── day1 │ ├── quick │ │ ├── helloHTTP │ │ │ ├── helloHTTP │ │ │ └── helloHTTP.go │ │ └── hello │ │ │ └── hello.go │ └── opening │ │ ├── slide4.md │ │ └── slide1.md ├── readme.md ├── day_3_training.md ├── day_2_training.md └── day_1_training.md ├── 01-language_syntax ├── 01-variables │ ├── example1 │ │ ├── example1 │ │ └── example1.go │ ├── exercises │ │ ├── exercise1 │ │ │ ├── exercise1 │ │ │ └── exercise1.go │ │ └── template1 │ │ │ ├── template1 │ │ │ └── template1.go │ └── readme.md ├── 02-struct_types │ ├── example1 │ │ ├── example1 │ │ └── example1.go │ ├── example2 │ │ ├── example2 │ │ └── example2.go │ ├── advanced │ │ └── example1 │ │ │ └── example1 │ ├── exercises │ │ ├── exercise1 │ │ │ ├── exercise1 │ │ │ └── exercise1.go │ │ └── template1 │ │ │ └── template1.go │ └── readme.md ├── 04-constants │ ├── example2 │ │ └── example2.go │ ├── exercises │ │ ├── template1 │ │ │ └── template1.go │ │ └── exercise1 │ │ │ └── exercise1.go │ ├── readme.md │ └── example1 │ │ └── example1.go ├── 03-pointers │ ├── example1 │ │ └── example1.go │ ├── exercises │ │ ├── template1 │ │ │ └── template1.go │ │ ├── template2 │ │ │ └── template2.go │ │ ├── exercise1 │ │ │ └── exercise1.go │ │ └── exercise2 │ │ │ └── exercise2.go │ ├── example2 │ │ └── example2.go │ ├── advanced │ │ └── example1 │ │ │ └── example1.go │ └── example3 │ │ └── example3.go ├── 05-type_conversions │ ├── example1 │ │ └── example1.go │ └── exercises │ │ ├── template1 │ │ └── template1.go │ │ └── exercise1 │ │ └── exercise1.go └── 06-functions │ ├── exercises │ ├── template1 │ │ └── template1.go │ └── exercise1 │ │ └── exercise1.go │ ├── example3 │ └── example3.go │ ├── example1 │ └── example1.go │ ├── example2 │ └── example2.go │ └── advanced │ └── example1 │ └── example1.go ├── assets ├── css │ └── main.css └── js │ └── main.js ├── 08-concurrency_channels ├── 03-channels │ ├── documentation │ │ ├── buffered.png │ │ ├── unbuffered.png │ │ └── channels.md │ ├── exercises │ │ ├── template2 │ │ │ └── template2.go │ │ ├── template1 │ │ │ └── template1.go │ │ ├── exercise1 │ │ │ └── exercise1.go │ │ └── exercise2 │ │ │ └── exercise2.go │ └── example2 │ │ └── example2.go ├── 01-goroutines │ ├── documentation │ │ ├── parallel.png │ │ ├── scheduler.png │ │ └── scheduler.md │ ├── example2 │ │ └── example2.go │ ├── exercises │ │ ├── template1 │ │ │ └── template1.go │ │ └── exercise1 │ │ │ └── exercise1.go │ ├── example3 │ │ └── example3.go │ └── example1 │ │ └── example1.go └── 02-race_conditions │ ├── documentation │ ├── race_condition.png │ └── race_condition.md │ ├── example2 │ └── example2.go │ ├── exercises │ ├── template1 │ │ └── template1.go │ └── exercise1 │ │ └── exercise1.go │ ├── example3 │ └── example3.go │ └── example4 │ └── example4.go ├── 13-http ├── example3 │ ├── public │ │ └── README │ └── template │ │ └── index.html ├── api │ ├── models │ │ └── models.go │ ├── tests │ │ └── tests.go │ ├── middleware │ │ └── request_logger.go │ ├── routes │ │ └── routes.go │ ├── main.go │ └── views │ │ └── index.html ├── example2 │ └── main.go ├── example1 │ └── main.go └── readme.md ├── 11-standard_library ├── 02-encoding │ ├── exercises │ │ ├── exercise1 │ │ │ ├── data.json │ │ │ └── exercise1.go │ │ └── template1 │ │ │ └── template1.go │ ├── example4 │ │ └── example4.go │ └── readme.md ├── 03-writers_readers │ ├── example1 │ │ └── example1.go │ ├── exercises │ │ ├── template1 │ │ │ └── template1.go │ │ └── exercise1 │ │ │ └── exercise1.go │ └── example2 │ │ └── example2.go ├── readme.md └── 01-logging │ ├── readme.md │ ├── example1 │ └── example1.go │ └── exercises │ ├── template1 │ └── template1.go │ └── exercise1 │ └── exercise1.go ├── 04-packaging_exporting ├── example1 │ ├── counters │ │ └── counters.go │ └── example1.go ├── example2 │ ├── counters │ │ └── counters.go │ └── example2.go ├── example4 │ ├── animals │ │ └── animals.go │ └── example4.go ├── example5 │ ├── animals │ │ └── animals.go │ └── example5.go ├── example3 │ ├── counters │ │ └── counters.go │ └── example3.go └── exercises │ ├── template1 │ ├── toy │ │ └── toy.go │ └── template1.go │ └── exercise1 │ ├── toy │ └── toy.go │ └── exercise1.go ├── editors └── sublime.json ├── 02-array_slices_maps ├── 03-maps │ ├── exercises │ │ ├── template1 │ │ │ └── template1.go │ │ └── exercise1 │ │ │ └── exercise1.go │ ├── example3 │ │ └── example3.go │ ├── example2 │ │ └── example2.go │ ├── advanced │ │ └── example1 │ │ │ └── example1.go │ ├── example1 │ │ └── example1.go │ └── readme.md ├── 01-arrays │ ├── example3 │ │ └── example3.go │ ├── example2 │ │ └── example2.go │ ├── exercises │ │ ├── template1 │ │ │ └── template1.go │ │ └── exercise1 │ │ │ └── exercise1.go │ ├── example1 │ │ └── example1.go │ └── readme.md └── 02-slices │ ├── example1 │ └── example1.go │ ├── example2 │ └── example2.go │ ├── example6 │ └── example6.go │ ├── example5 │ └── example5.go │ ├── exercises │ ├── template1 │ │ └── template1.go │ └── exercise1 │ │ └── exercise1.go │ ├── example4 │ └── example4.go │ ├── advanced │ └── example1 │ │ └── example1.go │ └── example3 │ └── example3.go ├── 09-concurrency_patterns ├── chat │ └── main │ │ └── main.go ├── readme.md └── task │ ├── task.go │ └── main │ └── main.go ├── 03-methods_interfaces_embedding ├── 02-interfaces │ ├── example3 │ │ └── example3.go │ ├── example1 │ │ └── example1.go │ └── example2 │ │ └── example2.go ├── 01-methods │ ├── exercises │ │ ├── template1 │ │ │ └── template1.go │ │ └── exercise1 │ │ │ └── exercise1.go │ ├── example2 │ │ └── example2.go │ ├── example1 │ │ └── example1.go │ ├── advanced │ │ └── example1 │ │ │ └── example1.go │ └── readme.md └── 03-embedding │ ├── example1 │ └── example1.go │ ├── example2 │ └── example2.go │ └── example3 │ └── example3.go ├── 07-error_handling ├── example5 │ └── example5.go ├── example1 │ └── example1.go ├── example2 │ └── example2.go └── exercises │ ├── template2 │ └── template2.go │ └── template1 │ └── template1.go ├── 05-using_pointers ├── exercises │ ├── template1 │ │ └── template1.go │ └── exercise1 │ │ └── exercise1.go └── example1 │ └── example1.go ├── 12-reflection ├── example1 │ └── example1.go ├── exercises │ └── template1 │ │ └── template1.go └── readme.md ├── 06-composition └── readme.md └── main.go /templates/slide.tmpl: -------------------------------------------------------------------------------- 1 | {{ . }} 2 | -------------------------------------------------------------------------------- /14-cli/TODO: -------------------------------------------------------------------------------- 1 | - Flexibility through programmability: the user is in control 2 | -------------------------------------------------------------------------------- /templates/code.tmpl: -------------------------------------------------------------------------------- 1 |
{{ . }}
2 | -------------------------------------------------------------------------------- /10-testing/05-profiling/curl.sh: -------------------------------------------------------------------------------- 1 | while true; do curl http://localhost:6060/english; done -------------------------------------------------------------------------------- /10-testing/03-caching/figure1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/10-testing/03-caching/figure1.png -------------------------------------------------------------------------------- /10-testing/02-prediction/figure1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/10-testing/02-prediction/figure1.png -------------------------------------------------------------------------------- /10-testing/02-prediction/figure2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/10-testing/02-prediction/figure2.png -------------------------------------------------------------------------------- /00-slides/day1/quick/helloHTTP/helloHTTP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/00-slides/day1/quick/helloHTTP/helloHTTP -------------------------------------------------------------------------------- /01-language_syntax/01-variables/example1/example1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/01-language_syntax/01-variables/example1/example1 -------------------------------------------------------------------------------- /01-language_syntax/02-struct_types/example1/example1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/01-language_syntax/02-struct_types/example1/example1 -------------------------------------------------------------------------------- /01-language_syntax/02-struct_types/example2/example2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/01-language_syntax/02-struct_types/example2/example2 -------------------------------------------------------------------------------- /01-language_syntax/01-variables/exercises/exercise1/exercise1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/01-language_syntax/01-variables/exercises/exercise1/exercise1 -------------------------------------------------------------------------------- /01-language_syntax/01-variables/exercises/template1/template1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/01-language_syntax/01-variables/exercises/template1/template1 -------------------------------------------------------------------------------- /01-language_syntax/02-struct_types/advanced/example1/example1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/01-language_syntax/02-struct_types/advanced/example1/example1 -------------------------------------------------------------------------------- /assets/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 80px; 3 | } 4 | 5 | .navbar-brand img { 6 | display: inline; 7 | margin: 0 10px 0 0; 8 | height: 100%; 9 | } 10 | -------------------------------------------------------------------------------- /08-concurrency_channels/03-channels/documentation/buffered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/08-concurrency_channels/03-channels/documentation/buffered.png -------------------------------------------------------------------------------- /01-language_syntax/02-struct_types/exercises/exercise1/exercise1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/01-language_syntax/02-struct_types/exercises/exercise1/exercise1 -------------------------------------------------------------------------------- /08-concurrency_channels/01-goroutines/documentation/parallel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/08-concurrency_channels/01-goroutines/documentation/parallel.png -------------------------------------------------------------------------------- /08-concurrency_channels/01-goroutines/documentation/scheduler.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/08-concurrency_channels/01-goroutines/documentation/scheduler.png -------------------------------------------------------------------------------- /08-concurrency_channels/03-channels/documentation/unbuffered.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/08-concurrency_channels/03-channels/documentation/unbuffered.png -------------------------------------------------------------------------------- /13-http/example3/public/README: -------------------------------------------------------------------------------- 1 | Put files here for additional assets. 2 | 3 | index.html and anything in a path starting with /api/ 4 | will be ignored (we're handling those in specially in routes). 5 | -------------------------------------------------------------------------------- /08-concurrency_channels/02-race_conditions/documentation/race_condition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/astaxie/gotraining-1/HEAD/08-concurrency_channels/02-race_conditions/documentation/race_condition.png -------------------------------------------------------------------------------- /assets/js/main.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | // Initialize highligh.js 3 | hljs.initHighlightingOnLoad(); 4 | 5 | // Add bootstrap classes on tables 6 | $("table").addClass("table table-bordered"); 7 | 8 | })() 9 | -------------------------------------------------------------------------------- /11-standard_library/02-encoding/exercises/exercise1/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name":"Bill", 4 | "email":"bill@ardanstudios.com" 5 | }, 6 | { 7 | "name":"Jill", 8 | "email":"jil@yahoo.com" 9 | }, 10 | { 11 | "name":"Peter", 12 | "email":"peter@gmail.com" 13 | } 14 | ] -------------------------------------------------------------------------------- /04-packaging_exporting/example1/counters/counters.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Package counters provides alert counter support. 5 | package counters 6 | 7 | // AlertCounter is an exported named type that 8 | // contains an integer counter for alerts. 9 | type AlertCounter int 10 | -------------------------------------------------------------------------------- /04-packaging_exporting/example2/counters/counters.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Package counters provides alert counter support. 5 | package counters 6 | 7 | // alertCounter is an unexported named type that 8 | // contains an integer counter for alerts. 9 | type alertCounter int 10 | -------------------------------------------------------------------------------- /04-packaging_exporting/example4/animals/animals.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Package animals provides support. 5 | package animals 6 | 7 | // Dog represents information about dogs. 8 | type Dog struct { 9 | Name string 10 | BarkStrength int 11 | age int 12 | } 13 | -------------------------------------------------------------------------------- /13-http/api/models/models.go: -------------------------------------------------------------------------------- 1 | // Package models contains data structures and associated behavior 2 | package models 3 | 4 | import "gopkg.in/bluesuncorp/validator.v6" 5 | 6 | var validate *validator.Validate 7 | 8 | func init() { 9 | config := validator.Config{ 10 | TagName: "validate", 11 | ValidationFuncs: validator.BakedInValidators, 12 | } 13 | 14 | validate = validator.New(config) 15 | } 16 | -------------------------------------------------------------------------------- /00-slides/day1/quick/hello/hello.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/JdC_UYCWAR 5 | 6 | // Sample program to show off Go and check programming environment. 7 | package main 8 | 9 | import "fmt" 10 | 11 | // main is the entry point for the application. 12 | func main() { 13 | // Display Hello World. 14 | fmt.Println("你好世界") 15 | } 16 | -------------------------------------------------------------------------------- /14-cli/01-invocation/example1/child.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | func main() { 9 | // os.Args[0] is the program name 10 | fmt.Printf("Arguments: %q\n", os.Args) 11 | 12 | // os.Getenv returns the value part of name=value 13 | fmt.Printf("Parent Shell: %q\n", os.Getenv("SHELL")) 14 | 15 | fmt.Println("Environment:") 16 | 17 | // Environ returns a slice of "name=value" strings 18 | for _, pair := range os.Environ() { 19 | fmt.Printf("\t%q\n", pair) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /04-packaging_exporting/example5/animals/animals.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Package animals provides support for animals. 5 | package animals 6 | 7 | // animal represents information about all animals. 8 | type animal struct { 9 | Name string 10 | Age int 11 | } 12 | 13 | // Dog represents information about dogs. 14 | type Dog struct { 15 | animal // The embedded type is unexported. 16 | BarkStrength int 17 | } 18 | -------------------------------------------------------------------------------- /04-packaging_exporting/example3/counters/counters.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Package counters provides alert counter support. 5 | package counters 6 | 7 | // alertCounter is an unexported named type that 8 | // contains an integer counter for alerts. 9 | type alertCounter int 10 | 11 | // New creates and returns values of the unexported type alertCounter. 12 | func New(value int) alertCounter { 13 | return alertCounter(value) 14 | } 15 | -------------------------------------------------------------------------------- /14-cli/02-streams/example1/parent.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | ) 8 | 9 | func main() { 10 | // os.Args[0] is _this_ program's name 11 | args := os.Args[1:] 12 | if len(args) < 1 { 13 | // nothing to do 14 | return 15 | } 16 | 17 | cmd := exec.Command(args[0], args[1:]...) 18 | 19 | // These streams are closed if we don't set them 20 | cmd.Stdin = os.Stdin 21 | cmd.Stdout = os.Stdout 22 | cmd.Stderr = os.Stderr 23 | 24 | err := cmd.Run() 25 | if err != nil { 26 | fmt.Println(err) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /00-slides/day1/opening/slide4.md: -------------------------------------------------------------------------------- 1 | ## Hello World 2 | 3 | Let's make sure of local development environment is working. 4 | 5 | ### Code Samples 6 | 7 | [Hello World](../quick/hello/hello.go) ([Go Playground](http://play.golang.org/p/JdC_UYCWAR)) 8 | 9 | [Hello World Web](../quick/helloHTTP/helloHTTP.go) ([Go Playground](http://play.golang.org/p/c44Q5OiX5z)) 10 | 11 | #### [Previous Slide](slide3.md) | [Start Training](../../readme.md) 12 | ___ 13 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /13-http/api/tests/tests.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "io" 5 | "net/http" 6 | "net/url" 7 | ) 8 | 9 | // Succeed is the Unicode codepoint for a check mark. 10 | const Succeed = "\u2713" 11 | 12 | // Failed is the Unicode codepoint for an X mark. 13 | const Failed = "\u2717" 14 | 15 | // NewRequest used to setup a request for mocking API calls with httptreemux. 16 | func NewRequest(method, path string, body io.Reader) *http.Request { 17 | r, _ := http.NewRequest(method, path, body) 18 | u, _ := url.Parse(path) 19 | r.URL = u 20 | r.RequestURI = path 21 | return r 22 | } 23 | -------------------------------------------------------------------------------- /10-testing/01-testing/example4/example4.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Sample program that implements a simple web service. 5 | package main 6 | 7 | import ( 8 | "log" 9 | "net/http" 10 | 11 | "github.com/gobridge/gotraining/10-testing/01-testing/example4/handlers" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | handlers.Routes() 17 | 18 | log.Println("listener : Started : Listening on: http://localhost:4000") 19 | http.ListenAndServe(":4000", nil) 20 | } 21 | -------------------------------------------------------------------------------- /editors/sublime.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": {"GOPATH":"/Users/bill/Spaces/Go/Projects"}, 3 | "on_save": 4 | [{ 5 | "cmd": "gs9o_open", "args": { 6 | "run": ["clear"], 7 | "focus_view": false 8 | } 9 | }, 10 | { 11 | "cmd": "gs9o_open", "args": { 12 | "run": ["sh", "go build"], 13 | "focus_view": false 14 | } 15 | }, 16 | { 17 | "cmd": "gs9o_open", "args": { 18 | "run": ["sh", "go vet"], 19 | "focus_view": false 20 | } 21 | }, 22 | { 23 | "cmd": "gs9o_open", "args": { 24 | "run": ["golint", "."], 25 | "focus_view": false 26 | } 27 | }] 28 | } -------------------------------------------------------------------------------- /04-packaging_exporting/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Sample program to show how to access an exported identifier. 5 | package main 6 | 7 | import ( 8 | "fmt" 9 | 10 | "github.com/gobridge/gotraining/04-packaging_exporting/example1/counters" 11 | ) 12 | 13 | // main is the entry point for the application. 14 | func main() { 15 | // Create a variable of the exported type and initialize the value to 10. 16 | counter := counters.AlertCounter(10) 17 | 18 | fmt.Printf("Counter: %d\n", counter) 19 | } 20 | -------------------------------------------------------------------------------- /00-slides/readme.md: -------------------------------------------------------------------------------- 1 | ## Go Training Classes 2 | Please choose the class and timeframe you are taking. 3 | 4 | *Note: This material has been designed to be taught in a classroom environment. The code is well commented but missing some of the contextual concepts and ideas that will be covered in class.* 5 | 6 | #### Slides 7 | 8 | [Opening Slide Deck](day1/opening/slide1.md) 9 | 10 | #### Hardcore Go 11 | 12 | [Day One](day_1_training.md) | 13 | [Day Two](day_2_training.md) | 14 | [Day Three](day_3_training.md) 15 | ___ 16 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /08-concurrency_channels/02-race_conditions/documentation/race_condition.md: -------------------------------------------------------------------------------- 1 | ## Scheduler - Race Conditions - Concurrency and Channels 2 | 3 | ### Diagram of the race condition from the example code. 4 | 5 | ![Ardan Labs](race_condition.png) 6 | 7 | ___ 8 | [![Ardan Labs](../../../00-slides/images/ggt_logo.png)](http://www.ardanlabs.com) 9 | [![Ardan Studios](../../../00-slides/images/ardan_logo.png)](http://www.ardanstudios.com) 10 | [![GoingGo Blog](../../../00-slides/images/ggb_logo.png)](http://www.goinggo.net) 11 | ___ 12 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /02-array_slices_maps/03-maps/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/-JBSUoux-v 5 | 6 | // Declare and make a map of integer values with a string as the key. Populate the 7 | // map with five values and iterate over the map to display the key/value pairs. 8 | package main 9 | 10 | // Add imports. 11 | 12 | // main is the entry point for the application. 13 | func main() { 14 | // Declare and make a map of integer type values. 15 | 16 | // Initialize some data into the map. 17 | 18 | // Display each key/value pair. 19 | } 20 | -------------------------------------------------------------------------------- /08-concurrency_channels/01-goroutines/documentation/scheduler.md: -------------------------------------------------------------------------------- 1 | ## Scheduler - Goroutines - Concurrency and Channels 2 | 3 | ### Diagram of how the scheduler works. 4 | 5 | ![Ardan Labs](scheduler.png) 6 | 7 | ### Difference between concurrency and parallelism. 8 | 9 | ![Ardan Labs](parallel.png) 10 | 11 | ___ 12 | [![Ardan Labs](../../../00-slides/images/ggt_logo.png)](http://www.ardanlabs.com) 13 | [![Ardan Studios](../../../00-slides/images/ardan_logo.png)](http://www.ardanstudios.com) 14 | [![GoingGo Blog](../../../00-slides/images/ggb_logo.png)](http://www.goinggo.net) 15 | ___ 16 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /08-concurrency_channels/03-channels/documentation/channels.md: -------------------------------------------------------------------------------- 1 | ## Scheduler - Channels - Concurrency and Channels 2 | 3 | ### Diagram of how an unbuffered channel works. 4 | 5 | ![Ardan Labs](unbuffered.png) 6 | 7 | ### Diagram of how a buffered channel works. 8 | 9 | ![Ardan Labs](buffered.png) 10 | 11 | ___ 12 | [![Ardan Labs](../../../00-slides/images/ggt_logo.png)](http://www.ardanlabs.com) 13 | [![Ardan Studios](../../../00-slides/images/ardan_logo.png)](http://www.ardanstudios.com) 14 | [![GoingGo Blog](../../../00-slides/images/ggb_logo.png)](http://www.goinggo.net) 15 | ___ 16 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /04-packaging_exporting/example3/example3.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Sample program to show how the program can access a value 5 | // of an unexported identifier from another package. 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/gobridge/gotraining/04-packaging_exporting/example3/counters" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Create a variable of the unexported type using the exported 17 | // New function from the package counters. 18 | counter := counters.New(10) 19 | 20 | fmt.Printf("Counter: %d\n", counter) 21 | } 22 | -------------------------------------------------------------------------------- /14-cli/03-flow/example1/parent.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | ) 8 | 9 | func fail(err error) { 10 | // output errors to stderr 11 | fmt.Fprintln(os.Stderr, err) 12 | // exit with non-zero status to indicate command failure 13 | os.Exit(1) 14 | } 15 | 16 | func main() { 17 | // os.Args[0] is _this_ program's name 18 | args := os.Args[1:] 19 | if len(args) < 1 { 20 | // nothing to do 21 | return 22 | } 23 | 24 | cmd := exec.Command(args[0], args[1:]...) 25 | 26 | // These streams are closed if we don't set them 27 | cmd.Stdin = os.Stdin 28 | cmd.Stdout = os.Stdout 29 | cmd.Stderr = os.Stderr 30 | 31 | err := cmd.Run() 32 | if err != nil { 33 | fail(err) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /09-concurrency_patterns/chat/main/main.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // This example is provided with help by Gabriel Aszalos. 5 | 6 | // This sample program demonstrates how to create a simple chat system. 7 | package main 8 | 9 | import ( 10 | "log" 11 | "os" 12 | "os/signal" 13 | 14 | "github.com/gobridge/gotraining/09-concurrency_patterns/chat" 15 | ) 16 | 17 | func main() { 18 | cr := chat.New() 19 | 20 | sigChan := make(chan os.Signal, 1) 21 | signal.Notify(sigChan, os.Interrupt) 22 | <-sigChan 23 | 24 | log.Println("Shutting Down Started") 25 | cr.Close() 26 | log.Println("Shutting Down Completed") 27 | } 28 | -------------------------------------------------------------------------------- /01-language_syntax/04-constants/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/ExxRWe6jUz 5 | 6 | // Sample program to show how constants do have a parallel type system. 7 | package main 8 | 9 | import "fmt" 10 | 11 | const ( 12 | // Max integer value on 64 bit architecture. 13 | maxInt = 9223372036854775807 14 | 15 | // Much larger value than int64. 16 | bigger = 9223372036854775808543522345 17 | 18 | // Will NOT compile 19 | // biggerInt int64 = 9223372036854775808543522345 20 | ) 21 | 22 | // main is the entry point for the application. 23 | func main() { 24 | fmt.Println("Will Compile") 25 | } 26 | -------------------------------------------------------------------------------- /10-testing/03-caching/caching_test.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/opI__KHj9a 5 | 6 | // go test -run=XXX -bench=. 7 | 8 | // Tests to show how why CPU caches matter. 9 | package caching 10 | 11 | import "testing" 12 | 13 | // BenchmarkRowTraverse capture the time it takes to perform 14 | // a row traversal. 15 | func BenchmarkRowTraverse(b *testing.B) { 16 | for i := 0; i < b.N; i++ { 17 | rowTraverse() 18 | } 19 | } 20 | 21 | // BenchmarkColTraverse capture the time it takes to perform 22 | // a column traversal. 23 | func BenchmarkColTraverse(b *testing.B) { 24 | for i := 0; i < b.N; i++ { 25 | colTraverse() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /04-packaging_exporting/example5/example5.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Sample program to show how to create values from exported types with 5 | // embedded unexported types. 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/gobridge/gotraining/04-packaging_exporting/example5/animals" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | /// Create a value of type Dog from the animals package. 17 | dog := animals.Dog{ 18 | BarkStrength: 10, 19 | } 20 | 21 | // Set the exported fields from the unexported animal inner type. 22 | dog.Name = "Chole" 23 | dog.Age = 1 24 | 25 | fmt.Printf("Dog: %#v\n", dog) 26 | } 27 | -------------------------------------------------------------------------------- /04-packaging_exporting/example4/example4.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Sample program to show how unexported fields from an exported struct 5 | // type can't be accessed directly. 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/gobridge/gotraining/04-packaging_exporting/example4/animals" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Create a value of type Dog from the animals package. 17 | dog := animals.Dog{ 18 | Name: "Chole", 19 | BarkStrength: 10, 20 | age: 5, 21 | } 22 | 23 | // ./example4.go:20: unknown animals.Dog field 'age' in struct literal 24 | 25 | fmt.Printf("Dog: %#v\n", dog) 26 | } 27 | -------------------------------------------------------------------------------- /02-array_slices_maps/01-arrays/example3/example3.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/s4BSgxz0Y3 5 | 6 | // Sample program to show how the behavior of the for range and 7 | // how memory for an array is contiguous. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Declare an array of 5 strings initialized with values. 17 | five := [5]string{"Annie", "Betty", "Charley", "Doug", "Edward"} 18 | 19 | // Iterate over the array displaying the value and 20 | // address of each element. 21 | for i, v := range five { 22 | fmt.Printf("Value[%s] Address[%p] IndexAddr[%p]\n", v, &v, &five[i]) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /04-packaging_exporting/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Sample program to show how the program can't access an 5 | // unexported identifier from another package. 6 | package main 7 | 8 | import ( 9 | "fmt" 10 | 11 | "github.com/gobridge/gotraining/04-packaging_exporting/example2/counters" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Create a variable of the unexported type and initialize the value to 10. 17 | counter := counters.alertCounter(10) 18 | 19 | // ./example2.go:17: cannot refer to unexported name counters.alertCounter 20 | // ./example2.go:17: undefined: counters.alertCounter 21 | 22 | fmt.Printf("Counter: %d\n", counter) 23 | } 24 | -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/02-interfaces/example3/example3.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/yaUWLZjidB 5 | 6 | // Sample program to show how you can't always get the address of a value. 7 | package main 8 | 9 | import "fmt" 10 | 11 | // duration is a named type with a base type of int. 12 | type duration int 13 | 14 | // format pretty-prints the duration value. 15 | func (d *duration) pretty() { 16 | fmt.Println("Duration:", *d) 17 | } 18 | 19 | // main is the entry point for the application. 20 | func main() { 21 | duration(42).pretty() 22 | 23 | // ./example3.go:21: cannot call pointer method on duration(42) 24 | // ./example3.go:21: cannot take the address of duration(42) 25 | } 26 | -------------------------------------------------------------------------------- /13-http/example2/main.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/Qmj_C5PEs1 5 | 6 | // Sample program to show how you can use the FileServer handle with 7 | // this service as a single call to ListenAndServe. 8 | package main 9 | 10 | import "net/http" 11 | 12 | func main() { 13 | // Since the http.Handler interface is so universal and ubiquitous, you can 14 | // encapsulate some really neat pieces of functionality in a single 15 | // http.Handler. You can mount http.Handlers to routers, middleware, filters, 16 | // and other server constructs. 17 | // 18 | // In this example we will create a file server in one line of code 19 | http.ListenAndServe(":4000", http.FileServer(http.Dir("."))) 20 | } 21 | -------------------------------------------------------------------------------- /13-http/api/middleware/request_logger.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "log" 5 | "time" 6 | 7 | "github.com/gobridge/gotraining/13-http/api/app" 8 | ) 9 | 10 | // RequestLogger writes some information about the request to the logs in 11 | // the format: SESSIONID : (200) GET /foo -> IP ADDR (latency) 12 | func RequestLogger(h app.Handler) app.Handler { 13 | return func(c *app.Context) error { 14 | log.Printf("%v : middleware : RequestLogger : Started", c.SessionID) 15 | 16 | start := time.Now() 17 | err := h(c) 18 | 19 | log.Printf("%v : (%d) %s %s -> %s (%s)", 20 | c.SessionID, 21 | c.Status, c.Request.Method, c.Request.URL.Path, 22 | c.Request.RemoteAddr, time.Since(start), 23 | ) 24 | 25 | log.Printf("%v : middleware : RequestLogger : Completed", c.SessionID) 26 | 27 | return err 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /10-testing/01-testing/example4/handlers/handlers.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Package handlers provides the endpoints for the web service. 5 | package handlers 6 | 7 | import ( 8 | "encoding/json" 9 | "net/http" 10 | ) 11 | 12 | // Routes sets the routes for the web service. 13 | func Routes() { 14 | http.HandleFunc("/sendjson", SendJSON) 15 | } 16 | 17 | // SendJSON returns a simple JSON document. 18 | func SendJSON(rw http.ResponseWriter, r *http.Request) { 19 | u := struct { 20 | Name string 21 | Email string 22 | }{ 23 | Name: "Bill", 24 | Email: "bill@ardanstudios.com", 25 | } 26 | 27 | rw.Header().Set("Content-Type", "application/json") 28 | rw.WriteHeader(200) 29 | json.NewEncoder(rw).Encode(&u) 30 | } 31 | -------------------------------------------------------------------------------- /02-array_slices_maps/02-slices/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/fWJR3Kln4Y 5 | 6 | // Sample program to show how the capacity of the slice 7 | // is not available for use. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Create a slice with a length of 5 elements. 17 | slice := make([]string, 5) 18 | slice[0] = "Apple" 19 | slice[1] = "Orange" 20 | slice[2] = "Banana" 21 | slice[3] = "Grape" 22 | slice[4] = "Plum" 23 | 24 | // You can't access an index of a slice beyond its length. 25 | slice[5] = "Runtime error" 26 | 27 | // Error: panic: runtime error: index out of range 28 | 29 | fmt.Println(slice) 30 | } 31 | -------------------------------------------------------------------------------- /10-testing/01-testing/example4/handlers/handlers_example_test.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Sample to show how to write a basic example. 5 | package handlers_test 6 | 7 | import ( 8 | "encoding/json" 9 | "fmt" 10 | "log" 11 | "net/http" 12 | "net/http/httptest" 13 | ) 14 | 15 | // ExampleSendJSON provides a basic example example. 16 | func ExampleSendJSON() { 17 | r, _ := http.NewRequest("GET", "/sendjson", nil) 18 | w := httptest.NewRecorder() 19 | http.DefaultServeMux.ServeHTTP(w, r) 20 | 21 | var u struct { 22 | Name string 23 | Email string 24 | } 25 | 26 | if err := json.NewDecoder(w.Body).Decode(&u); err != nil { 27 | log.Println("ERROR:", err) 28 | } 29 | 30 | fmt.Println(u) 31 | // Output: 32 | // {Bill bill@ardanstudios.com} 33 | } 34 | -------------------------------------------------------------------------------- /01-language_syntax/02-struct_types/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/_xxuE1Ep6U 5 | 6 | // Sample program to show how to declare and initialize anonymous 7 | // struct types. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Declare a variable of an anonymous type and init 17 | // using a struct literal. 18 | e := struct { 19 | flag bool 20 | counter int16 21 | pi float32 22 | }{ 23 | flag: true, 24 | counter: 10, 25 | pi: 3.141592, 26 | } 27 | 28 | // Display the values. 29 | fmt.Printf("%+v\n", e) 30 | fmt.Println("Flag", e.flag) 31 | fmt.Println("Counter", e.counter) 32 | fmt.Println("Pi", e.pi) 33 | } 34 | -------------------------------------------------------------------------------- /07-error_handling/example5/example5.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/czXpjvWWTT 5 | 6 | // Sample program to show see if the class can find the bug. 7 | package main 8 | 9 | import ( 10 | "log" 11 | ) 12 | 13 | // customError is just an empty struct. 14 | type customError struct{} 15 | 16 | // Error implements the error interface. 17 | func (c *customError) Error() string { 18 | return "Find the bug." 19 | } 20 | 21 | // fail returns nil values for both return types. 22 | func fail() ([]byte, *customError) { 23 | return nil, nil 24 | } 25 | 26 | // main is the entry point for the application. 27 | func main() { 28 | var err error 29 | if _, err = fail(); err != nil { 30 | log.Fatal("Why did this fail?") 31 | } 32 | 33 | log.Println("No Error") 34 | } 35 | -------------------------------------------------------------------------------- /01-language_syntax/04-constants/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/qG3-9yn5_6 5 | 6 | // Declare an untyped and typed constant and display their values. 7 | // 8 | // Multiply two literal constants into a typed variable and display the value. 9 | package main 10 | 11 | // Add imports. 12 | 13 | // Declare a constant named server of kind string and assign a value. 14 | 15 | // Declare a constant named port of type integer and assign a value. 16 | 17 | // main is the entry point for the application. 18 | func main() { 19 | // Display the value of both server and port. 20 | 21 | // Divide a constant of kind integer and kind floating point and 22 | // assign the result to a variable. 23 | 24 | // Display the value of the variable. 25 | } 26 | -------------------------------------------------------------------------------- /02-array_slices_maps/01-arrays/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/LVD43cYBNS 5 | 6 | // Sample program to show how arrays of different sizes are 7 | // not of the same type. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Declare an array of 5 integers that is initialized 17 | // to its zero value. 18 | var five [5]int 19 | 20 | // Declare an array of 4 integers that is initialized 21 | // with some values. 22 | four := [4]int{10, 20, 30, 40} 23 | 24 | // Assign one array to the other 25 | five = four 26 | 27 | // ./example2.go:20: cannot use four (type [4]int) as type [5]int in assignment 28 | 29 | fmt.Println(four) 30 | fmt.Println(five) 31 | } 32 | -------------------------------------------------------------------------------- /02-array_slices_maps/01-arrays/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/ggjjRPzhAB 5 | 6 | // Declare an array of 5 strings with each element initialized to its zero value. 7 | // 8 | // Declare a second array of 5 strings and initialize this array with literal string 9 | // values. Assign the second array to the first and display the results of the first array. 10 | package main 11 | 12 | // Add imports. 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Declare an array of 5 strings set to its zero value. 17 | 18 | // Declare an array of 5 strings and pre-populate it with names. 19 | 20 | // Assign the populated array to the array of zero values. 21 | 22 | // Iterate over the first array declared. 23 | } 24 | -------------------------------------------------------------------------------- /01-language_syntax/03-pointers/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/nNnsK6hWdP 5 | 6 | // Sample program to show the basic concept of pass by value. 7 | package main 8 | 9 | // main is the entry point for the application. 10 | func main() { 11 | // Declare variable of type int with a value of 10. 12 | count := 10 13 | 14 | // Display the "value of" and "address of" count. 15 | println("Before:", count, &count) 16 | 17 | // Pass the "value of" the variable count. 18 | increment(count) 19 | 20 | println("After: ", count, &count) 21 | } 22 | 23 | // increment declares count as a variable whose value is 24 | // always an integer. 25 | func increment(inc int) { 26 | // Increment the "value of" inc. 27 | inc++ 28 | println("Inc: ", inc, &inc) 29 | } 30 | -------------------------------------------------------------------------------- /01-language_syntax/04-constants/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/d2gkKxEftw 5 | 6 | // Declare an untyped and typed constant and display their values. 7 | // 8 | // Multiply two literal constants into a typed variable and display the value. 9 | package main 10 | 11 | import "fmt" 12 | 13 | // server is the IP address for connecting. 14 | const server = "124.53.24.123" 15 | 16 | // port is the port to make that connection. 17 | const port int16 = 9000 18 | 19 | // main is the entry point for the application. 20 | func main() { 21 | // Display the server information. 22 | fmt.Println(server) 23 | fmt.Println(port) 24 | 25 | // Calculate the number of minutes in 5320 seconds. 26 | minutes := 5320 / 60.0 27 | fmt.Println(minutes) 28 | } 29 | -------------------------------------------------------------------------------- /01-language_syntax/02-struct_types/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/ItPe2EEy9X 5 | 6 | // Declare a struct type to maintain information about a user (name, email and age). 7 | // Create a value of this type, initialize with values and display each field. 8 | // 9 | // Declare and initialize an anonymous struct type with the same three fields. Display the value. 10 | package main 11 | 12 | // Add imports. 13 | 14 | // Add user type and provide comment. 15 | 16 | // main is the entry point for the application. 17 | func main() { 18 | // Declare variable of type user and init using a struct literal. 19 | 20 | // Display the field values. 21 | 22 | // Declare a variable using an anonymous struct. 23 | 24 | // Display the field values. 25 | } 26 | -------------------------------------------------------------------------------- /02-array_slices_maps/03-maps/example3/example3.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/1JmxvWLAET 5 | 6 | // Sample program to show how only types that can have 7 | // equality defined on them can be a map key. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // user defines a user in the program. 15 | type user struct { 16 | name string 17 | email string 18 | } 19 | 20 | // users define a set of users. 21 | type users []user 22 | 23 | // main is the entry point for the application. 24 | func main() { 25 | // Declare and make a map uses a slice of users as the key. 26 | u := make(map[users]int) 27 | 28 | // ./example3.go:26: invalid map key type users 29 | 30 | // Iterate over the map. 31 | for key, value := range u { 32 | fmt.Println(key, value) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /14-cli/02-streams/example2/pipeline.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/exec" 7 | ) 8 | 9 | func main() { 10 | c1 := exec.Command("df", "-h") 11 | c2 := exec.Command("sort") 12 | 13 | r, err := c1.StdoutPipe() 14 | if err != nil { 15 | fmt.Println("failed to create pipe:", err) 16 | return 17 | } 18 | defer r.Close() 19 | 20 | c1.Stdin = os.Stdin 21 | c1.Stderr = os.Stderr 22 | 23 | // the stdout of c1 feeds the stdin of c2 24 | c2.Stdin = r 25 | c2.Stdout = os.Stdout 26 | c2.Stderr = os.Stderr 27 | 28 | err = c1.Start() 29 | if err != nil { 30 | fmt.Println("process #1 failed to start:", err) 31 | } 32 | 33 | // we Wait on c1 to clean up its process entry when done 34 | // (otherwise, it'll remain as a zombie process until this process exits) 35 | defer c1.Wait() 36 | 37 | err = c2.Run() 38 | if err != nil { 39 | fmt.Println("process #2 failed:", err) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /13-http/api/routes/routes.go: -------------------------------------------------------------------------------- 1 | package routes 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gobridge/gotraining/13-http/api/app" 7 | "github.com/gobridge/gotraining/13-http/api/handlers" 8 | ) 9 | 10 | // API returns a handler for a set of routes. 11 | func API() http.Handler { 12 | a := app.New() 13 | 14 | // Setup the file server to serve up static content such as 15 | // the index.html page. 16 | a.TreeMux.NotFoundHandler = http.FileServer(http.Dir("views")).ServeHTTP 17 | 18 | // Initialize the routes for the API binding the route to the 19 | // handler code for each specified verb. 20 | a.Handle("GET", "/v1/users", handlers.Users.List) 21 | a.Handle("POST", "/v1/users", handlers.Users.Create) 22 | a.Handle("GET", "/v1/users/:id", handlers.Users.Retrieve) 23 | a.Handle("PUT", "/v1/users/:id", handlers.Users.Update) 24 | a.Handle("DELETE", "/v1/users/:id", handlers.Users.Delete) 25 | 26 | return a 27 | } 28 | -------------------------------------------------------------------------------- /02-array_slices_maps/03-maps/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/hC1o26x7Q5 5 | 6 | // Sample program to show how to declare and initialize a map 7 | // using a map literal. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // user defines a user in the program. 15 | type user struct { 16 | name string 17 | email string 18 | } 19 | 20 | // main is the entry point for the application. 21 | func main() { 22 | // Declare and initialize the map with values. 23 | users := map[string]user{ 24 | "Rob": user{"Roy", "Rob"}, 25 | "Ford": user{"Henry", "Ford"}, 26 | "Mouse": user{"Mickey", "Mouse"}, 27 | "Jackson": user{"Michael", "Jackson"}, 28 | } 29 | 30 | // Iterate over the map. 31 | for key, value := range users { 32 | fmt.Println(key, value) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /00-slides/day_3_training.md: -------------------------------------------------------------------------------- 1 | ## Go Training - Day 3 2 | On this day we continue go deeper into Go. We learn about concurrency patterns, testing, benchmarking, debugging, logging, encoding, io, and reflection. 3 | 4 | *Note: This material has been designed to be taught in a classroom environment. The code is well commented but missing some of the contextual concepts and ideas that will be covered in class.* 5 | 6 | #### Concurrency Patterns 7 | [Concurrency Patterns](../09-concurrency_patterns/readme.md) 8 | 9 | #### Testing, Prediction, Godebug and Profiling 10 | [Testing and Debugging](../10-testing/readme.md) 11 | 12 | #### Logging, Encoding and IO 13 | [Standard Library](../11-standard_library/readme.md) 14 | 15 | #### Reflection 16 | [Reflection](../12-reflection/readme.md) 17 | 18 | #### HTTP 19 | [HTTP](../13-http/readme.md) 20 | ___ 21 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /10-testing/readme.md: -------------------------------------------------------------------------------- 1 | ## Testing and Debugging 2 | 3 | Go has support for both testing and debugging. This includes profiling and benchmarking Go programs. 4 | 5 | ## Package Review 6 | 7 | [Testing](../10-testing/01-testing/readme.md) 8 | 9 | [Prediction](../10-testing/02-prediction/readme.md) 10 | 11 | [Caching](../10-testing/03-caching/readme.md) 12 | 13 | [Godebug](../10-testing/04-godebug/readme.md) 14 | 15 | [Profiling](../10-testing/05-profiling/readme.md) 16 | 17 | ## Exercises 18 | 19 | ### Exercise 1 20 | Write three benchmark tests for converting an integer into a string. First use the fmt.Sprintf function, then the strconv.FormatInt function and finally the strconv.Itoa. Identify which function performs the best. 21 | 22 | [Template](exercises/template1/bench_test.go) | 23 | [Answer](exercises/exercise1/bench_test.go) 24 | ___ 25 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /02-array_slices_maps/03-maps/advanced/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/pQsoB02pDl 5 | 6 | // Sample program to show how to compose maps of maps. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | // Data defines a key/value store. 14 | type Data map[string]string 15 | 16 | // main is the entry point for the application. 17 | func main() { 18 | // Declare and make a map of Data type values. 19 | users := make(map[string]Data) 20 | 21 | // Initialize some data into our map of maps. 22 | users["clients"] = Data{"123": "Henry", "654": "Joan"} 23 | users["admins"] = Data{"398": "Bill", "076": "Steve"} 24 | 25 | // Iterate over the map of maps. 26 | for key, data := range users { 27 | fmt.Println(key) 28 | for key, value := range data { 29 | fmt.Println("\t", key, value) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /02-array_slices_maps/03-maps/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/8K-IZgJFSg 5 | 6 | // Declare and make a map of integer values with a string as the key. Populate the 7 | // map with five values and iterate over the map to display the key/value pairs. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Declare and make a map of integer type values. 17 | departments := make(map[string]int) 18 | 19 | // Initialize some data into the map. 20 | departments["IT"] = 20 21 | departments["Marketing"] = 15 22 | departments["Executives"] = 5 23 | departments["Sales"] = 50 24 | departments["Security"] = 8 25 | 26 | // Display each key/value pair. 27 | for key, value := range departments { 28 | fmt.Printf("Dept: %s People: %d\n", key, value) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /00-slides/day1/opening/slide1.md: -------------------------------------------------------------------------------- 1 | ## Special Features Of Go 2 | 3 | I may be biased, but I truly believe Go is an amazing language. It balances the efficiency of a lower level systems language with the most important features of a high-level modern language. This creates a programming environment that allows you to be incredibly productive, performant and fully in control; in Go you can write less code and do so much more. Here are some other special features about the language: 4 | 5 | #### * Comes with a robust standard library. 6 | 7 | #### * Works on a multitude of platforms. 8 | 9 | #### * Code is statically compiled so deployment is trivial. 10 | 11 | #### * The documentation is exemplary and complete, yet concise. 12 | 13 | #### * Comes with a tool to test, profile and benchmark your code. 14 | 15 | #### * Can interact with C libraries via cgo. 16 | 17 | #### [Next Slide](slide2.md) 18 | ___ 19 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 20 | -------------------------------------------------------------------------------- /02-array_slices_maps/01-arrays/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/Pa3mrTCcpB 5 | 6 | // Declare an array of 5 strings with each element initialized to its zero value. 7 | // 8 | // Declare a second array of 5 strings and initialize this array with literal string 9 | // values. Assign the second array to the first and display the results of the first array. 10 | package main 11 | 12 | import "fmt" 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Declare string arrays to hold names. 17 | var names [5]string 18 | 19 | // Declare an array pre-populated with friend's names. 20 | friends := [5]string{"Joe", "Ed", "Jim", "Erick", "Bill"} 21 | 22 | // Assign the array of friends to the names array. 23 | names = friends 24 | 25 | // Display each name in names. 26 | for _, name := range names { 27 | fmt.Println(name) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /04-packaging_exporting/exercises/template1/toy/toy.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Package toy contains support for managing toy inventory. 5 | package toy 6 | 7 | // Declare a struct type named Toy with four fields. Name string, 8 | // Weight int, onHand int and sold int. 9 | 10 | // Declare a function named New that accepts values for the 11 | // exported fields. Return a pointer of type Toy that is initialized 12 | // with the parameters. 13 | 14 | // Declare a method named OnHand with a pointer receiver that 15 | // returns the current on hand count. 16 | 17 | // Declare a method named UpdateOnHand with a pointer receiver that 18 | // updates and returns the current on hand count. 19 | 20 | // Declare a method named Sold with a pointer receiver that 21 | // returns the current sold count. 22 | 23 | // Declare a method named UpdateSold with a pointer receiver that 24 | // updates and returns the current sold count. 25 | -------------------------------------------------------------------------------- /02-array_slices_maps/02-slices/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/d1kRkbZ-iV 5 | 6 | // Sample program to show the components of a slice. It has a 7 | // length, capacity and the underlying array. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Create a slice with a length of 5 elements and a capacity of 8. 17 | slice := make([]string, 5, 8) 18 | slice[0] = "Apple" 19 | slice[1] = "Orange" 20 | slice[2] = "Banana" 21 | slice[3] = "Grape" 22 | slice[4] = "Plum" 23 | 24 | inspectSlice(slice) 25 | } 26 | 27 | // inspectSlice exposes the slice header for review. 28 | func inspectSlice(slice []string) { 29 | fmt.Printf("Length[%d] Capacity[%d]\n", len(slice), cap(slice)) 30 | for i, v := range slice { 31 | fmt.Printf("[%d] %p %s\n", 32 | i, 33 | &slice[i], 34 | v) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /01-language_syntax/03-pointers/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/asM7GXfJNk 5 | 6 | // Declare and initialize a variable of type int with the value of 20. Display 7 | // the _address of_ and _value of_ the variable. 8 | // 9 | // Declare and initialize a pointer variable of type int that points to the last 10 | // variable you just created. Display the _address of_ , _value of_ and the 11 | // _value that the pointer points to_. 12 | package main 13 | 14 | // Add imports. 15 | 16 | // main is the entry point for the application. 17 | func main() { 18 | // Declare an integer variable with the value of 20. 19 | 20 | // Display the address of and value of the variable. 21 | 22 | // Declare a pointer variable of type int. Assign the 23 | // address of the integer variable above. 24 | 25 | // Display the address of, value of and the value the pointer 26 | // points to. 27 | } 28 | -------------------------------------------------------------------------------- /01-language_syntax/01-variables/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/1xUWjHMB3I 5 | 6 | // Declare three variables that are initialized to their zero value and three 7 | // declared with a literal value. Declare variables of type string, int and 8 | // bool. Display the values of those variables. 9 | // 10 | // Declare a new variable of type float32 and initialize the variable by 11 | // converting the literal value of Pi (3.14). 12 | package main 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Declare variables that are set to their zero value. 17 | 18 | // Display the value of those variables. 19 | 20 | // Declare variables and initialize. 21 | // Using the short variable declaration operator. 22 | 23 | // Display the value of those variables. 24 | 25 | // Perform a type conversion. 26 | 27 | // Display the value of that variable. 28 | } 29 | -------------------------------------------------------------------------------- /02-array_slices_maps/02-slices/example6/example6.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/cK3y_qYUgd 5 | 6 | // Sample program to show how to declare and use variadic functions. 7 | package main 8 | 9 | import "fmt" 10 | 11 | // user is a struct type that declares user information. 12 | type user struct { 13 | id int 14 | name string 15 | } 16 | 17 | // main is the entry point for the application. 18 | func main() { 19 | // Declare and initialize a value of type user. 20 | u1 := user{ 21 | id: 1432, 22 | name: "Betty", 23 | } 24 | 25 | // Declare and initialize a value of type user. 26 | u2 := user{ 27 | id: 4367, 28 | name: "Janet", 29 | } 30 | 31 | // Display both user values. 32 | display(u1, u2) 33 | } 34 | 35 | // display can accept and display multiple values of user types. 36 | func display(users ...user) { 37 | for i := 0; i < len(users); i++ { 38 | fmt.Printf("%+v\n", users[i]) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /10-testing/exercises/template1/bench_test.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | /* 5 | http://golang.org/cmd/go/#hdr-Description_of_testing_flags 6 | go test -run=XXX -bench=. 7 | go test -run=XXX -bench=BenchmarkSprintf 8 | go test -run=XXX -bench=BenchmarkFormat 9 | go test -run=XXX -bench=BenchmarkAtoi 10 | */ 11 | 12 | // Write three benchmark tests for converting an integer into a string. First using the 13 | // fmt.Sprintf function, then the strconv.FormatInt function and then strconv.Itoa. 14 | // Identify which function performs the best. 15 | package main 16 | 17 | // Add imports. 18 | 19 | // BenchmarkSprintf provides performance numbers for the fmt.Sprintf function. 20 | // fmt.Sprintf("%d", number) 21 | 22 | // BenchmarkFormat provides performance numbers for the strconv.FormatInt function. 23 | // strconv.FormatInt(number, 10) 24 | 25 | // BenchmarkItoa provides performance numbers for the strconv.Itoa function. 26 | // strconv.Itoa(number) 27 | -------------------------------------------------------------------------------- /01-language_syntax/05-type_conversions/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/mhKlxSyuxr 5 | 6 | // Sample program to show how to declare and use a named type. 7 | package main 8 | 9 | import "fmt" 10 | 11 | // Duration is a named type that represents a duration 12 | // of time in Nanosecond. 13 | type Duration int64 14 | 15 | func main() { 16 | // Declare a variable of type Duration. 17 | var duration Duration 18 | fmt.Println(duration) 19 | 20 | // Declare a variable of type int64 and assign a value. 21 | nanosecond := int64(10) 22 | 23 | // Attempted to assign a variable of type int64 (base type of Duration) to 24 | // a variable of type Duration. 25 | // duration = nanosecond 26 | 27 | // ./example1.go:22: cannot use nanosecond (type int64) as type Duration in assignment 28 | 29 | // Convert a value of type int64 to type Duration. 30 | duration = Duration(nanosecond) 31 | fmt.Println(duration) 32 | } 33 | -------------------------------------------------------------------------------- /01-language_syntax/02-struct_types/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/-oeDmu2et8 5 | 6 | // Sample program to show how to declare and initialize struct types. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | // example represents a type with different fields. 14 | type example struct { 15 | flag bool 16 | counter int16 17 | pi float32 18 | } 19 | 20 | // main is the entry point for the application. 21 | func main() { 22 | // Declare a variable of type example set to its 23 | // zero value. 24 | var e1 example 25 | 26 | // Display the value. 27 | fmt.Printf("%+v\n", e1) 28 | 29 | // Declare a variable of type example and init using 30 | // a struct literal. 31 | e2 := example{ 32 | flag: true, 33 | counter: 10, 34 | pi: 3.141592, 35 | } 36 | 37 | // Display the field values. 38 | fmt.Println("Flag", e2.flag) 39 | fmt.Println("Counter", e2.counter) 40 | fmt.Println("Pi", e2.pi) 41 | } 42 | -------------------------------------------------------------------------------- /01-language_syntax/03-pointers/exercises/template2/template2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/b6-FNFOToO 5 | 6 | // Declare a struct type and create a value of this type. Declare a function 7 | // that can change the value of some field in this struct type. Display the 8 | // value before and after the call to your function. 9 | package main 10 | 11 | // Add imports. 12 | 13 | // Declare a type named user. 14 | 15 | // Create a function that changes the value of one of the user fields. 16 | func funcName( /* add pointer parameter, add value parameter */ ) { 17 | // Use the pointer to change the value that the 18 | // pointer points to. 19 | } 20 | 21 | // main is the entry point for the application. 22 | func main() { 23 | // Create a variable of type user and initialize each field. 24 | 25 | // Display the value of the variable. 26 | 27 | // Share the variable with the function you declared above. 28 | 29 | // Display the value of the variable. 30 | } 31 | -------------------------------------------------------------------------------- /02-array_slices_maps/01-arrays/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/DGr8Zp9L_w 5 | 6 | // Sample program to show how to declare and iterate over 7 | // arrays of different types. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Declare an array of five strings that is initialized 17 | // to its zero value. 18 | var strings [5]string 19 | strings[0] = "Apple" 20 | strings[1] = "Orange" 21 | strings[2] = "Banana" 22 | strings[3] = "Grape" 23 | strings[4] = "Plum" 24 | 25 | // Iterate over the array of strings. 26 | for i, fruit := range strings { 27 | fmt.Println(i, fruit) 28 | } 29 | 30 | // Declare an array of 4 integers that is initialized 31 | // with some values. 32 | numbers := [4]int{10, 20, 30, 40} 33 | 34 | // Iterate over the array of numbers. 35 | for i := 0; i < len(numbers); i++ { 36 | fmt.Println(i, numbers[i]) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /13-http/example3/template/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sample Form 5 | 15 | 16 | 17 |

Add User

18 |
19 | 20 | 21 | 22 | 23 |
24 |
25 |

Existing Users

26 | {{if .Users}} 27 | 28 | 29 | 30 | 31 | 32 | {{range .Users}} 33 | 34 | {{end}} 35 | 36 |
NameEmailPhone
{{.Name}}{{.Email}}{{.Phone}}
37 | {{else}} 38 |

(no users)

39 | {{end}} 40 | 41 | 42 | -------------------------------------------------------------------------------- /10-testing/04-godebug/godebug.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/sKLLsUa5hH 5 | 6 | // export GODEBUG=schedtrace=1000 7 | // export GODEBUG=schedtrace=1000,scheddetail=1 8 | 9 | // Sample program to review scheduler stats. 10 | package main 11 | 12 | import ( 13 | "sync" 14 | "time" 15 | ) 16 | 17 | // Create a waitgroup. 18 | var wg sync.WaitGroup 19 | 20 | // main is the entry point for the application. 21 | func main() { 22 | // We are going to create 10 goroutines. 23 | wg.Add(10) 24 | 25 | // Create those 10 goroutines. 26 | for i := 0; i < 10; i++ { 27 | go goroutine() 28 | } 29 | 30 | // Wait for all the goroutines to complete. 31 | wg.Wait() 32 | 33 | // Wait to see the global runqueue deplete. 34 | time.Sleep(3 * time.Second) 35 | } 36 | 37 | // goroutine does some CPU bound work. 38 | func goroutine() { 39 | time.Sleep(time.Second) 40 | 41 | var count int 42 | for i := 0; i < 1e10; i++ { 43 | count++ 44 | } 45 | 46 | wg.Done() 47 | } 48 | -------------------------------------------------------------------------------- /02-array_slices_maps/02-slices/example5/example5.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/6CAkumo0HI 5 | 6 | // Sample program to show how strings have a UTF-8 encoded byte array. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "unicode/utf8" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Declare a string with both chinese and english characters. 17 | s := "世界 means world" 18 | 19 | // UTFMax is 4 -- up to 4 bytes per encoded rune. 20 | var buf [utf8.UTFMax]byte 21 | 22 | // Iterate over each character in the string. 23 | for i, r := range s { 24 | // Capture the number of bytes for this character. 25 | k := utf8.RuneLen(r) 26 | 27 | // Calculate the slice offset to slice the character out. 28 | j := i + k 29 | 30 | // Copy of character from the string to our buffer. 31 | copy(buf[:], s[i:j]) 32 | 33 | // Display the details. 34 | fmt.Printf("%2d: %q; codepoint: %#6x; encoded bytes: %#v\n", i, r, r, buf[:k]) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /11-standard_library/03-writers_readers/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/jlTo1IV1RQ 5 | 6 | // The io.Reader and io.Writer interfaces allow you to compose all of these different bits together. 7 | 8 | // Sample program to show how different functions from the 9 | // standard library use the io.Writer interface. 10 | package main 11 | 12 | import ( 13 | "bytes" 14 | "fmt" 15 | "os" 16 | ) 17 | 18 | // main is the entry point for the application. 19 | func main() { 20 | // Create a Buffer value and write a string to the buffer. 21 | // Using the Write method that implements io.Writer. 22 | var b bytes.Buffer 23 | b.Write([]byte("Hello ")) 24 | 25 | // Use Fprintf to concatenate a string to the Buffer. 26 | // Passing the address of a bytes.Buffer value for io.Writer. 27 | fmt.Fprintf(&b, "World!") 28 | 29 | // Write the content of the Buffer to the stdout device. 30 | // Passing the address of a os.File value for io.Writer. 31 | b.WriteTo(os.Stdout) 32 | } 33 | -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/01-methods/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/Rj0QfwVPhX 5 | 6 | // Declare a struct that represents a baseball player. Include name, atBats and hits. 7 | // Declare a method that calculates a players batting average. The formula is Hits / AtBats. 8 | // Declare a slice of this type and initialize the slice with several players. Iterate over 9 | // the slice displaying the players name and batting average. 10 | package main 11 | 12 | // Add imports. 13 | 14 | // Declare a struct that represents a ball player. 15 | // Include field called name, atBats and hits. 16 | 17 | // Declare a method that calculates the batting average for a batter. 18 | func ( /* receiver */ ) average() /* return type */ { 19 | } 20 | 21 | // main is the entry point for the application. 22 | func main() { 23 | // Create a slice of players and populate each player 24 | // with field values. 25 | 26 | // Display the batting average for each player in the slice. 27 | } 28 | -------------------------------------------------------------------------------- /09-concurrency_patterns/readme.md: -------------------------------------------------------------------------------- 1 | ## Concurrency Patterns 2 | There are lots of different patterns we can create with goroutines and channels. Two interesting patterns are resource pooling and concurrent searching. 3 | 4 | ## Notes 5 | 6 | * The work code provides a pattern for giving work to a set number of goroutines without losing the guarantee. 7 | * The resource pooling code provides a pattern for managing resources that goroutines may need to acquire and release. 8 | * The search code provides a pattern for using multiple goroutines to perform concurrent work. 9 | 10 | ## Links 11 | 12 | https://github.com/gobridge/concurrency-patterns 13 | 14 | http://blog.golang.org/pipelines 15 | 16 | https://talks.golang.org/2012/concurrency.slide#1 17 | 18 | https://blog.golang.org/context 19 | 20 | http://blog.golang.org/advanced-go-concurrency-patterns 21 | 22 | http://talks.golang.org/2012/chat.slide 23 | 24 | ## Code Review 25 | 26 | [Task](task) 27 | 28 | [Pooling](pool) 29 | 30 | [Chat](chat) 31 | ___ 32 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 33 | -------------------------------------------------------------------------------- /10-testing/02-prediction/prediction_test.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/hwZqjJNdbm 5 | 6 | // go build -gcflags -m 7 | 8 | // Package prediction provides code to show how branch 9 | // prediction can affect performance. 10 | package prediction 11 | 12 | import ( 13 | "math/rand" 14 | "testing" 15 | ) 16 | 17 | func BenchmarkPredictable(b *testing.B) { 18 | data := make([]uint8, 1024) 19 | 20 | b.ResetTimer() 21 | for i := 0; i < b.N; i++ { 22 | crunch(data) 23 | } 24 | } 25 | 26 | func BenchmarkUnpredictable(b *testing.B) { 27 | data := make([]uint8, 1024) 28 | rand.Seed(0) 29 | 30 | // Fill data with (pseudo) random noise 31 | for i := range data { 32 | data[i] = uint8(rand.Uint32()) 33 | } 34 | 35 | b.ResetTimer() 36 | for i := 0; i < b.N; i++ { 37 | crunch(data) 38 | } 39 | } 40 | 41 | func crunch(data []uint8) uint8 { 42 | var sum uint8 43 | for _, v := range data { 44 | if v < 128 { 45 | sum-- 46 | } else { 47 | sum++ 48 | } 49 | } 50 | return sum 51 | } 52 | -------------------------------------------------------------------------------- /01-language_syntax/03-pointers/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/FWmGnVUDoA 5 | 6 | // Sample program to show the basic concept of using a pointer 7 | // to share data. 8 | package main 9 | 10 | import "fmt" 11 | 12 | // main is the entry point for the application. 13 | func main() { 14 | // Declare variable of type int with a value of 10. 15 | count := 10 16 | 17 | // Display the "value of" and "address of" count. 18 | println("Before:", count, &count) 19 | 20 | // Pass the "address of" the variable count. 21 | increment(&count) 22 | 23 | println("After: ", count, &count) 24 | } 25 | 26 | // increment declares count as a pointer variable whose value is 27 | // always an address and points to values of type int. 28 | func increment(inc *int) { 29 | // Increment the value that the "pointer points to". (de-referencing) 30 | *inc++ 31 | println("Inc: ", *inc, &inc, inc) 32 | 33 | // Do this to prevent inlining. 34 | var x int 35 | fmt.Sprintf("Prevent Inlining: %d", x) 36 | } 37 | -------------------------------------------------------------------------------- /13-http/api/main.go: -------------------------------------------------------------------------------- 1 | // This program provides a sample web service that implements a 2 | // RESTFul CRUD API against a MongoDB database. 3 | package main 4 | 5 | import ( 6 | "log" 7 | "net/http" 8 | "os" 9 | "os/signal" 10 | 11 | "github.com/gobridge/gotraining/13-http/api/routes" 12 | ) 13 | 14 | // init is called before main. We are using init to customize logging output. 15 | func init() { 16 | log.SetFlags(log.LstdFlags | log.Lmicroseconds | log.Lshortfile) 17 | } 18 | 19 | // main is the entry point for the application. 20 | func main() { 21 | log.Println("main : Started") 22 | 23 | // Check the environment for a configured port value. 24 | port := os.Getenv("PORT") 25 | if port == "" { 26 | port = "3000" 27 | } 28 | 29 | // Create this goroutine to run the web server. 30 | go func() { 31 | log.Println("listener : Started : Listening on: http://localhost:" + port) 32 | http.ListenAndServe(":"+port, routes.API()) 33 | }() 34 | 35 | // Listen for an interrupt signal from the OS. 36 | sigChan := make(chan os.Signal, 1) 37 | signal.Notify(sigChan, os.Interrupt) 38 | <-sigChan 39 | 40 | log.Println("main : Completed") 41 | } 42 | -------------------------------------------------------------------------------- /04-packaging_exporting/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Create a package named toy with a single exported struct type named Toy. Add 5 | // the exported fields Name and Weight. Then add two unexported fields named 6 | // onHand and sold. Declare a factory function called New to create values of 7 | // type toy and accept parameters for the exported fields. Then declare methods 8 | // that return and update values for the unexported fields. 9 | // 10 | // Create a program that imports the toy package. Use the New function to create a 11 | // value of type toy. Then use the methods to set the counts and display the 12 | // field values of that toy value. 13 | package main 14 | 15 | // Add imports. 16 | 17 | // main is the entry point for the application. 18 | func main() { 19 | // Use the New function from the toy package to create a value of 20 | // type toy. 21 | 22 | // Use the methods from the toy value to set some initialize 23 | // values. 24 | 25 | // Display each field separately from the toy value. 26 | } 27 | -------------------------------------------------------------------------------- /00-slides/day_2_training.md: -------------------------------------------------------------------------------- 1 | ## Go Training - Day 2 2 | On this day we dive deeper into Go. We learn about packaging, exporting, using pointers, composition, error handling, concurrency, race conditions, and channels. 3 | 4 | *Note: This material has been designed to be taught in a classroom environment. The code is well commented but missing some of the contextual concepts and ideas that will be covered in class.* 5 | 6 | #### Packaging and Exporting 7 | [Packaging and Exporting](../04-packaging_exporting/readme.md) 8 | 9 | #### Using Pointers 10 | [Nature Of Types](../05-using_pointers/readme.md) 11 | 12 | #### Composition 13 | [Composition](../06-composition/readme.md) 14 | 15 | #### Error Handling 16 | [Error Handling](../07-error_handling/readme.md) 17 | 18 | #### Concurrency, Race Conditions and Channels 19 | [Goroutines](../08-concurrency_channels/01-goroutines/readme.md) | 20 | [Race Conditions](../08-concurrency_channels/02-race_conditions/readme.md) | 21 | [Channels](../08-concurrency_channels/03-channels/readme.md) 22 | ___ 23 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 24 | -------------------------------------------------------------------------------- /07-error_handling/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/8x6kDZxPWK 5 | 6 | // Sample program to show how the default error type is implemented. 7 | package main 8 | 9 | import "fmt" 10 | 11 | // http://golang.org/pkg/builtin/#error 12 | type error interface { 13 | Error() string 14 | } 15 | 16 | // http://golang.org/src/pkg/errors/errors.go 17 | type errorString struct { 18 | s string 19 | } 20 | 21 | // http://golang.org/src/pkg/errors/errors.go 22 | func (e *errorString) Error() string { 23 | return e.s 24 | } 25 | 26 | // http://golang.org/src/pkg/errors/errors.go 27 | // New returns an error that formats as the given text. 28 | func New(text string) error { 29 | return &errorString{text} 30 | } 31 | 32 | // main is the entry point for the application. 33 | func main() { 34 | if err := webCall(); err != nil { 35 | fmt.Println(err) 36 | return 37 | } 38 | 39 | fmt.Println("Life is good") 40 | } 41 | 42 | // webCall performs a web operation. 43 | func webCall() error { 44 | return New("Bad Request") 45 | } 46 | -------------------------------------------------------------------------------- /11-standard_library/03-writers_readers/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/MxcJ581bt6 5 | 6 | // Download any document from the web and display the content in 7 | // the terminal and write it to a file at the same time. 8 | package main 9 | 10 | // Add imports. 11 | 12 | // main is the entry point for the application. 13 | func main() { 14 | // Download the RSS feed for "http://www.goinggo.net/feeds/posts/default". 15 | // Check for errors. 16 | 17 | // Arrange for the response Body to be Closed using defer. 18 | 19 | // Declare a slice of io.Writer interface values. 20 | 21 | // Append stdout to the slice of writers. 22 | 23 | // Open a file named "goinggo.rss" and check for errors. 24 | 25 | // Close the file when the function returns. 26 | 27 | // Append the file to the slice of writers. 28 | 29 | // Create a MultiWriter interface value from the writers 30 | // inside the slice of io.Writer values. 31 | 32 | // Write the response to both the stdout and file using the 33 | // MultiWriter. Check for errors. 34 | } 35 | -------------------------------------------------------------------------------- /01-language_syntax/03-pointers/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/pUtHSTN0Ef 5 | 6 | // Declare and initialize a variable of type int with the value of 20. Display 7 | // the _address of_ and _value of_ the variable. 8 | // 9 | // Declare and initialize a pointer variable of type int that points to the last 10 | // variable you just created. Display the _address of_ , _value of_ and the 11 | // _value that the pointer points to_. 12 | package main 13 | 14 | import "fmt" 15 | 16 | // main is the entry point for the application. 17 | func main() { 18 | // Declare an integer variable with the value of 20. 19 | value := 20 20 | 21 | // Display the address of and value of the variable. 22 | fmt.Println("Address Of:", &value, "Value Of:", value) 23 | 24 | // Declare a pointer variable of type int. Assign the 25 | // address of the integer variable above. 26 | p := &value 27 | 28 | // Display the address of, value of and the value the pointer 29 | // points to. 30 | fmt.Println("Address Of:", &p, "Value Of:", p, "Points To:", *p) 31 | } 32 | -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/03-embedding/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/e5O_Dx5VpM 5 | 6 | // Sample program to show how what we are doing is NOT embedding 7 | // a type but just using a type as a field. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // user defines a user in the program. 15 | type user struct { 16 | name string 17 | email string 18 | } 19 | 20 | // notify implements a method that can be called via 21 | // a value of type user. 22 | func (u *user) notify() { 23 | fmt.Printf("Sending user email To %s<%s>\n", 24 | u.name, 25 | u.email) 26 | } 27 | 28 | // admin represents an admin user with privileges. 29 | type admin struct { 30 | person user // NOT Embedding 31 | level string 32 | } 33 | 34 | // main is the entry point for the application. 35 | func main() { 36 | // Create an admin user. 37 | ad := admin{ 38 | person: user{ 39 | name: "john smith", 40 | email: "john@yahoo.com", 41 | }, 42 | level: "super", 43 | } 44 | 45 | // We can access fields methods. 46 | ad.person.notify() 47 | } 48 | -------------------------------------------------------------------------------- /05-using_pointers/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/9_MSdcdlNQ 5 | 6 | // Declare a struct type named Point with two fields, X and Y of type int. 7 | // Implement a factory function for this type and a method that accept a value 8 | // of this type and calculates the distance between the two points. What is 9 | // the nature of this type? 10 | package main 11 | 12 | // Add imports. 13 | 14 | // Declare struct type named Point that represents a point in space. 15 | 16 | // Declare a function named New that returns a Point based on X and Y 17 | // positions on a graph. 18 | 19 | // Declare a method named Distance that finds the length of the hypotenuse 20 | // between two points. Pass one point in and return the answer. 21 | // Formula is the square root of (x2 - x1)^2 + (y2 - y1)^2 22 | // Use the math.Pow and math.Sqrt functions. 23 | 24 | // main is the entry point for the application. 25 | func main() { 26 | // Declare the first point. 27 | 28 | // Declare the second point. 29 | 30 | // Calculate the distance and display the result. 31 | } 32 | -------------------------------------------------------------------------------- /11-standard_library/readme.md: -------------------------------------------------------------------------------- 1 | ## Standard Library 2 | 3 | The Go standard library is a set of core packages that enhance and extend the language. These packages add to the number of different types of programs you can write without the need to build your own packages or download packages others have published. Since these packages are tied to the language, they come with some special guarantees that make the standard library special and something you want to leverage as much as possible. 4 | 5 | ## Guarantees 6 | 7 | * They will always exist for each minor release of the language. 8 | * They will honor the backwards compatibility promise. 9 | * They are part of the dev, build and release process for Go. 10 | * They are maintained and reviewed by Go contributors. 11 | * They are tested and benchmarked with each new release of the language. 12 | 13 | ## Package Review 14 | 15 | [Logging](../11-standard_library/01-logging/readme.md) 16 | 17 | [Encoding](../11-standard_library/02-encoding/readme.md) 18 | 19 | [Writers/Readers](../11-standard_library/03-writers_readers/readme.md) 20 | ___ 21 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 22 | -------------------------------------------------------------------------------- /04-packaging_exporting/exercises/exercise1/toy/toy.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Package toy contains support for managing toy inventory. 5 | package toy 6 | 7 | // Toy represents a toy we sell. 8 | type Toy struct { 9 | Name string 10 | Weight int 11 | 12 | onHand int 13 | sold int 14 | } 15 | 16 | // New creates values of type toy. 17 | func New(name string, weight int) *Toy { 18 | return &Toy{ 19 | Name: name, 20 | Weight: weight, 21 | } 22 | } 23 | 24 | // OnHand returns the current number of this 25 | // toy on hand. 26 | func (t *Toy) OnHand() int { 27 | return t.onHand 28 | } 29 | 30 | // UpdateOnHand updates the on hand count and 31 | // returns the current value. 32 | func (t *Toy) UpdateOnHand(count int) int { 33 | t.onHand = t.onHand + count 34 | return t.onHand 35 | } 36 | 37 | // Sold returns the current number of this 38 | // toy sold. 39 | func (t *Toy) Sold() int { 40 | return t.sold 41 | } 42 | 43 | // UpdateSold updates the sold count and 44 | // returns the current value. 45 | func (t *Toy) UpdateSold(count int) int { 46 | t.sold = t.sold + count 47 | return t.sold 48 | } 49 | -------------------------------------------------------------------------------- /01-language_syntax/06-functions/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/p0vlsW5sVL 5 | 6 | // Declare a struct type to maintain information about a user. Declare a function 7 | // that creates value of and returns pointers of this type and an error value. Call 8 | // this function from main and display the value. 9 | // 10 | // Make a second call to your function but this time ignore the value and just test 11 | // the error value. 12 | package main 13 | 14 | // Add imports. 15 | 16 | // Declare a type named user. 17 | 18 | // Declare a function that creates user type values and returns a pointer 19 | // to that value and an error value of nil. 20 | func funcName() /* (pointer return arg, error return arg) */ { 21 | // Create a value of type user and return the proper values. 22 | } 23 | 24 | // main is the entry point for the application. 25 | func main() { 26 | // Use the function to create a value of type user. Check 27 | // the error being returned. 28 | 29 | // Display the value that the pointer points to. 30 | 31 | // Call the function again and just check the error. 32 | } 33 | -------------------------------------------------------------------------------- /07-error_handling/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/4YHAbpynl3 5 | 6 | // Sample program to show how to use error variables to help the 7 | // caller determine the exact error being returned. 8 | package main 9 | 10 | import ( 11 | "errors" 12 | "fmt" 13 | ) 14 | 15 | var ( 16 | // ErrBadRequest is returned when there are problems with the request. 17 | ErrBadRequest = errors.New("Bad Request") 18 | 19 | // ErrMovedPermanently is returned when a 301/302 is returned. 20 | ErrMovedPermanently = errors.New("Moved Permanently") 21 | ) 22 | 23 | // main is the entry point for the application. 24 | func main() { 25 | if err := webCall(); err != nil { 26 | switch err { 27 | case ErrBadRequest: 28 | fmt.Println("Bad Request Occurred") 29 | return 30 | 31 | case ErrMovedPermanently: 32 | fmt.Println("The URL moved, check it again") 33 | return 34 | 35 | default: 36 | fmt.Println(err) 37 | return 38 | } 39 | } 40 | 41 | fmt.Println("Life is good") 42 | } 43 | 44 | // webCall performs a web operation. 45 | func webCall() error { 46 | return ErrBadRequest 47 | } 48 | -------------------------------------------------------------------------------- /02-array_slices_maps/03-maps/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/ZgPw0LU_Nv 5 | 6 | // Sample program to show how to declare, initialize and iterate 7 | // over a map. Shows how iterating over a map is random. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // user defines a user in the program. 15 | type user struct { 16 | name string 17 | email string 18 | } 19 | 20 | // main is the entry point for the application. 21 | func main() { 22 | // Declare and make a map that stores values 23 | // of type user with a key of type string. 24 | users := make(map[string]user) 25 | 26 | // Add key/value pairs to the map. 27 | users["Rob"] = user{"Roy", "Rob"} 28 | users["Ford"] = user{"Henry", "Ford"} 29 | users["Mouse"] = user{"Mickey", "Mouse"} 30 | users["Jackson"] = user{"Michael", "Jackson"} 31 | 32 | // Iterate over the map. 33 | for key, value := range users { 34 | fmt.Println(key, value) 35 | } 36 | 37 | fmt.Println() 38 | 39 | // Iterate over the map and notice the 40 | // results are different. 41 | for key := range users { 42 | fmt.Println(key) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /02-array_slices_maps/02-slices/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/mPKmyGNR2L 5 | 6 | // Declare a nil slice of integers. Declare a nil slice of integers. Create a 7 | // loop that appends 10 values to the slice. Iterate over the slice and display 8 | // each value. Iterate over the slice and display each value. 9 | // 10 | // Declare a slice of five strings and initialize the slice with string literal 11 | // values. Display all the elements. Take a slice of index one and two 12 | // and display the index position and value of each element in the new slice. 13 | package main 14 | 15 | // Add imports. 16 | 17 | // main is the entry point for the application. 18 | func main() { 19 | // Declare a nil slice of integers. 20 | 21 | // Appends numbers to the slice. 22 | 23 | // Display each value in the slice. 24 | 25 | // Declare a slice of strings and populate the slice with names. 26 | 27 | // Display each index position and slice value. 28 | 29 | // // Take a slice of index 1 and 2 of the slice of strings. 30 | 31 | // Display each index position and slice values for the new slice. 32 | } 33 | -------------------------------------------------------------------------------- /11-standard_library/02-encoding/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/OkIHsVwMQ7 5 | 6 | // Create a file with an array of JSON documents that contain a user name and email address. Declare a struct 7 | // type that maps to the JSON document. Using the json package, read the file and create a slice of this struct 8 | // type. Display the slice. 9 | // 10 | // Marshal the slice into pretty print strings and display each element. 11 | package main 12 | 13 | // Add imports. 14 | 15 | // Declare a struct type named user with two fields. Name of type string and 16 | // Email of type string. Add tags for each field for the unmarshal call. 17 | 18 | // main is the entry point for the application. 19 | func main() { 20 | // Use the os package to Open the JSON file. Check for errors. 21 | 22 | // Schedule the file to be closed once the function returns. 23 | 24 | // Declare a nil slice of user struct types. 25 | // Decode the JSON from the file into the slice. Check for errors. 26 | 27 | // Iterate over the slice and display each user value. 28 | 29 | // Marshal each user value and display the JSON. Check for errors. 30 | } 31 | -------------------------------------------------------------------------------- /01-language_syntax/05-type_conversions/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/-WjYGqauiY 5 | 6 | // Declare a named type called counter with a base type of int. Declare a variable 7 | // named c of type counter set to its zero value. Display the value of c. 8 | // 9 | // Declare a variable named c2 of type counter set to the value of 10. Display the value 10 | // of c2. 11 | // 12 | // Declare a variable named i of the base type int. Attempt to assign the value 13 | // of i to c. Does the compiler allow the assignment? 14 | package main 15 | 16 | // Add imports. 17 | 18 | // Declare the named type called counter with a base 19 | // type of int. 20 | 21 | // main is the entry point for the application. 22 | func main() { 23 | // Declare a variable named c of type counter 24 | // set to its zero value. 25 | 26 | // Display the value of c. 27 | 28 | // Declare a variable named c2 of type counter 29 | // set to the value of 10. 30 | 31 | // Display the value of c2. 32 | 33 | // Declare a variable named i of the base type int. 34 | 35 | // Assign the value of i to the variable named c. 36 | 37 | // Does it compile? 38 | } 39 | -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/03-embedding/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/UkrDXkk-Ch 5 | 6 | // Sample program to show how to embed a type into another type and 7 | // the relationship between the inner and outer type. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // user defines a user in the program. 15 | type user struct { 16 | name string 17 | email string 18 | } 19 | 20 | // notify implements a method that can be called via 21 | // a value of type user. 22 | func (u *user) notify() { 23 | fmt.Printf("Sending user email To %s<%s>\n", 24 | u.name, 25 | u.email) 26 | } 27 | 28 | // admin represents an admin user with privileges. 29 | type admin struct { 30 | user // Embedded Type 31 | level string 32 | } 33 | 34 | // main is the entry point for the application. 35 | func main() { 36 | // Create an admin user. 37 | ad := admin{ 38 | user: user{ 39 | name: "john smith", 40 | email: "john@yahoo.com", 41 | }, 42 | level: "super", 43 | } 44 | 45 | // We can access the inner type's method directly. 46 | ad.user.notify() 47 | 48 | // The inner type's method is promoted. 49 | ad.notify() 50 | } 51 | -------------------------------------------------------------------------------- /10-testing/01-testing/example1/example1_test.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Sample test to show how to write a basic unit test. 5 | package example1 6 | 7 | import ( 8 | "net/http" 9 | "testing" 10 | ) 11 | 12 | const succeed = "\u2713" 13 | const failed = "\u2717" 14 | 15 | // TestDownload validates the http Get function can download content. 16 | func TestDownload(t *testing.T) { 17 | url := "http://www.goinggo.net/feeds/posts/default?alt=rss" 18 | statusCode := 200 19 | 20 | t.Log("Given the need to test downloading content.") 21 | { 22 | t.Logf("\tWhen checking \"%s\" for status code \"%d\"", url, statusCode) 23 | { 24 | resp, err := http.Get(url) 25 | if err != nil { 26 | t.Fatal("\t\tShould be able to make the Get call.", 27 | failed, err) 28 | } 29 | t.Log("\t\tShould be able to make the Get call.", 30 | succeed) 31 | 32 | defer resp.Body.Close() 33 | 34 | if resp.StatusCode == statusCode { 35 | t.Logf("\t\tShould receive a \"%d\" status code. %v", 36 | statusCode, succeed) 37 | } else { 38 | t.Errorf("\t\tShould receive a \"%d\" status code. %v %v", 39 | statusCode, failed, resp.StatusCode) 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /00-slides/day1/quick/helloHTTP/helloHTTP.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/c44Q5OiX5z 5 | 6 | // Sample program to show off Go and check programming environment. 7 | package main 8 | 9 | import ( 10 | "encoding/json" 11 | "log" 12 | "net/http" 13 | ) 14 | 15 | type ( 16 | // hello holds a message. 17 | hello struct { 18 | Message string 19 | } 20 | ) 21 | 22 | // main is the entry point for the application. 23 | func main() { 24 | http.HandleFunc("/english", helloEnglish) 25 | http.HandleFunc("/chinese", helloChinese) 26 | http.ListenAndServe("localhost:9999", nil) 27 | } 28 | 29 | // helloEnglish sends a greeting in English. 30 | func helloEnglish(w http.ResponseWriter, r *http.Request) { 31 | err := json.NewEncoder(w).Encode(hello{"Hello World"}) 32 | if err != nil { 33 | log.Println("Error encoding JSON", err) 34 | return 35 | } 36 | log.Println("Sent English") 37 | } 38 | 39 | // helloChinese sends a greeting in Chinese. 40 | func helloChinese(w http.ResponseWriter, r *http.Request) { 41 | err := json.NewEncoder(w).Encode(hello{"你好世界"}) 42 | if err != nil { 43 | log.Println("Error encoding JSON", err) 44 | return 45 | } 46 | log.Println("Sent Chinese") 47 | } 48 | -------------------------------------------------------------------------------- /05-using_pointers/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/5KL4HipSJ- 5 | 6 | // Declare a struct type named Point with two fields, X and Y of type int. 7 | // Implement a factory function for this type and a method that accept a value 8 | // of this type and calculates the distance between the two points. What is 9 | // the nature of this type. 10 | package main 11 | 12 | import ( 13 | "fmt" 14 | "math" 15 | ) 16 | 17 | // Point represents a point in space. 18 | type Point struct { 19 | X int 20 | Y int 21 | } 22 | 23 | // New returns a Point based on X and Y positions on a graph. 24 | func New(x int, y int) Point { 25 | return Point{x, y} 26 | } 27 | 28 | // Distance finds the length of the hypotenuse between two points. 29 | // Formula is the square root of (x2 - x1)^2 + (y2 - y1)^2 30 | func (p Point) Distance(p2 Point) float64 { 31 | first := math.Pow(float64(p2.X-p.X), 2) 32 | second := math.Pow(float64(p2.Y-p.Y), 2) 33 | return math.Sqrt(first + second) 34 | } 35 | 36 | // main is the entry point for the application. 37 | func main() { 38 | p1 := New(37, -76) 39 | p2 := New(26, -80) 40 | 41 | dist := p1.Distance(p2) 42 | fmt.Println("Distance", dist) 43 | } 44 | -------------------------------------------------------------------------------- /01-language_syntax/05-type_conversions/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/KIdESKQc8C 5 | 6 | // Declare a named type called counter with a base type of int. Declare a variable 7 | // named c of type counter set to its zero value. Display the value of c. 8 | // 9 | // Declare a variable named c2 of type counter set to the value of 10. Display the value 10 | // of c2. 11 | // 12 | // Declare a variable named i of the base type int. Attempt to assign the value 13 | // of i to c. Does the compiler allow the assignment? 14 | package main 15 | 16 | import "fmt" 17 | 18 | // counter is a named type for counting. 19 | type counter int 20 | 21 | // main is the entry point for the application. 22 | func main() { 23 | // Declare a variable of type counter. 24 | var c counter 25 | 26 | // Display the value of c. 27 | fmt.Println(c) 28 | 29 | // Declare a second variable of type counter. Set 30 | // the value to 10. 31 | c2 := counter(10) 32 | 33 | // Display the value of c2. 34 | fmt.Println(c2) 35 | 36 | // Declare a variable named i of type int. 37 | i := 1 38 | 39 | // Assign the value of i to the variable named c. 40 | c = i 41 | 42 | // Does the program compile? 43 | } 44 | -------------------------------------------------------------------------------- /01-language_syntax/06-functions/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/fSjQ3caTy1 5 | 6 | // Declare a struct type to maintain information about a user. Declare a function 7 | // that creates value of and returns pointers of this type and an error value. Call 8 | // this function from main and display the value. 9 | // 10 | // Make a second call to your function but this time ignore the value and just test 11 | // the error value. 12 | package main 13 | 14 | import "fmt" 15 | 16 | // user represents a user in the system. 17 | type user struct { 18 | name string 19 | email string 20 | } 21 | 22 | // main is the entry point for the application. 23 | func main() { 24 | // Create a value of type user. 25 | u, err := newUser() 26 | if err != nil { 27 | fmt.Println(err) 28 | return 29 | } 30 | 31 | // Display the value. 32 | fmt.Println(*u) 33 | 34 | // Call the function and just check the error on the return. 35 | _, err = newUser() 36 | if err != nil { 37 | fmt.Println(err) 38 | return 39 | } 40 | } 41 | 42 | // newUser creates and returns pointers of user type values. 43 | func newUser() (*user, error) { 44 | return &user{"Bill", "bill@ardanstudios.com"}, nil 45 | } 46 | -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/01-methods/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/C8Z_MiYKbc 5 | 6 | // Declare a struct that represents a baseball player. Include name, atBats and hits. 7 | // Declare a method that calculates a players batting average. The formula is Hits / AtBats. 8 | // Declare a slice of this type and initialize the slice with several players. Iterate over 9 | // the slice displaying the players name and batting average. 10 | package main 11 | 12 | import "fmt" 13 | 14 | // batter represents a playing in the game. 15 | type batter struct { 16 | name string 17 | atBats int 18 | hits int 19 | } 20 | 21 | // average calculates the batting average for a batter. 22 | func (b *batter) average() float64 { 23 | return float64(b.hits) / float64(b.atBats) 24 | } 25 | 26 | // main is the entry point for the application. 27 | func main() { 28 | // Create a few players. 29 | players := []batter{ 30 | {"bill", 10, 7}, 31 | {"jim", 12, 6}, 32 | {"ed", 6, 4}, 33 | } 34 | 35 | // Display the batting average for each player. 36 | for _, player := range players { 37 | average := player.average() * 1000 38 | fmt.Printf("%s: AVG[.%.f]\n", player.name, average) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /04-packaging_exporting/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Create a package named toy with a single exported struct type named Toy. Add 5 | // the exported fields Name and Weight. Then add two unexported fields named 6 | // onHand and sold. Declare a factory function called New to create values of 7 | // type toy and accept parameters for the exported fields. Then declare methods 8 | // that return and update values for the unexported fields. 9 | // 10 | // Create a program that imports the toy package. Use the New function to create a 11 | // value of type toy. Then use the methods to set the counts and display the 12 | // field values of that toy value. 13 | package main 14 | 15 | import ( 16 | "fmt" 17 | 18 | "github.com/gobridge/gotraining/04-packaging_exporting/exercises/exercise1/toy" 19 | ) 20 | 21 | // main is the entry point for the application. 22 | func main() { 23 | // Create a value of type toy. 24 | toy := toy.New("Bat", 28) 25 | 26 | // Update the counts. 27 | toy.UpdateOnHand(100) 28 | toy.UpdateSold(2) 29 | 30 | // Display each field separately. 31 | fmt.Println("Name", toy.Name) 32 | fmt.Println("Weight", toy.Weight) 33 | fmt.Println("OnHand", toy.OnHand()) 34 | fmt.Println("Sold", toy.Sold()) 35 | } 36 | -------------------------------------------------------------------------------- /08-concurrency_channels/01-goroutines/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/AzDUqwkM58 5 | 6 | // Sample program to show how the goroutine scheduler 7 | // will time slice goroutines on a single thread. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "sync" 13 | ) 14 | 15 | // wg is used to wait for the program to finish. 16 | var wg sync.WaitGroup 17 | 18 | // main is the entry point for all Go programs. 19 | func main() { 20 | // Add a count of two, one for each goroutine. 21 | wg.Add(2) 22 | 23 | // Create two goroutines. 24 | fmt.Println("Create Goroutines") 25 | go printPrime("A") 26 | go printPrime("B") 27 | 28 | // Wait for the goroutines to finish. 29 | fmt.Println("Waiting To Finish") 30 | wg.Wait() 31 | 32 | fmt.Println("Terminating Program") 33 | } 34 | 35 | // printPrime displays prime numbers for the first 5000 numbers. 36 | func printPrime(prefix string) { 37 | next: 38 | for outer := 2; outer < 5000; outer++ { 39 | for inner := 2; inner < outer; inner++ { 40 | if outer%inner == 0 { 41 | continue next 42 | } 43 | } 44 | fmt.Printf("%s:%d\n", prefix, outer) 45 | } 46 | 47 | fmt.Println("Completed", prefix) 48 | 49 | // Tell main we are done. 50 | wg.Done() 51 | } 52 | -------------------------------------------------------------------------------- /13-http/example1/main.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/leTrm6v1yG 5 | 6 | // Sample program to show how to implement a handler function 7 | // with the http package. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "net/http" 13 | ) 14 | 15 | func main() { 16 | // Like many packages in the standard library, the http package has 17 | // convenience methods that are declared on the package level. These methods 18 | // actually delegate to an underlying structure that you can initialize 19 | // yourself. In this example, we are adding a handler to the http.DefaultServeMux 20 | http.HandleFunc("/", HelloHandler) 21 | 22 | // ListenAndServe will listen on the specified host:port combo. Passing nil 23 | // as the second argument means we will be using the http.DefaultServeMux as 24 | // our http handler 25 | http.ListenAndServe(":4000", nil) 26 | } 27 | 28 | // HelloHandler shows how the http Handlers are the universal interface for 29 | // handling http stuff, you will see that many Go developers rally around the 30 | // http.Handler interface. 31 | func HelloHandler(w http.ResponseWriter, r *http.Request) { 32 | // Fprintln is a nice way to write formatted text out to a io.Writer 33 | fmt.Fprintln(w, "Hello world") 34 | } 35 | -------------------------------------------------------------------------------- /08-concurrency_channels/01-goroutines/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/H-h1cbBW3B 5 | 6 | // Create a program that declares two anonymous functions. Once that counts up to 7 | // 100 from 0 and one that counts down to 0 from 100. Display each number with an 8 | // unique identifier for each goroutine. Then create goroutines from these functions 9 | // and don't let main return until the goroutines complete. 10 | // 11 | // Run the program in parallel. 12 | package main 13 | 14 | // main is the entry point for all Go programs. 15 | func main() { 16 | // Declare a wait group and set the count to two. 17 | 18 | // Allocate two contexts for the scheduler to use in the 19 | // second part of this exercise. 20 | 21 | // Declare an anonymous function and create a goroutine. 22 | { 23 | // Declare a loop that counts down from 100 to 0 and 24 | // display each value. 25 | 26 | // Decrements the count of the wait group. 27 | } 28 | 29 | // Declare an anonymous function and create a goroutine. 30 | { 31 | // Declare a loop that counts up from 0 to 100 and 32 | // display each value. 33 | 34 | // Decrements the count of the wait group. 35 | } 36 | 37 | // Wait for the goroutines to finish. 38 | } 39 | -------------------------------------------------------------------------------- /14-cli/04-patterns/readme.md: -------------------------------------------------------------------------------- 1 | ## Pattern Matching 2 | 3 | A fundamental convenience provided by shells is pattern matching of files. 4 | Let's initialize a directory with some files: 5 | 6 | touch a b1 c1 01.txt 02.txt 7 | 8 | We can now match against these four files in various ways using patterns. 9 | 10 | # display info for all files ending in '.txt': 01.txt 02.txt 11 | # the "star" will match any number of characters (including zero) 12 | ls -l *.txt 13 | 14 | # list all files starting with a lowercase letter: a b1 c1 15 | # character classes are case-sensitive and match exactly one character 16 | echo [a-z]* 17 | 18 | # list all files that do _not_ end with a number: a 01.txt 02.txt 19 | echo *[!0-9] 20 | 21 | # remove all files with names consisting of two characters: b1 c1 22 | # question marks match exactly one character each 23 | rm ?? 24 | 25 | Pattern matching is the default behavior. To instead specify an argument or 26 | filename containing a wildcard character or whitespace, it can be wrapped in 27 | either single or double quotes, or the special character can be escaped with a 28 | backslash, for example: 29 | 30 | # create two new files 31 | touch filename\ with\ spaces "more spaces" 32 | ___ 33 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 34 | -------------------------------------------------------------------------------- /11-standard_library/02-encoding/example4/example4.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/TOYrZJoLei 5 | 6 | // Sample program to show how write a custom Unmarshal and Marshal functions. 7 | package main 8 | 9 | import ( 10 | "encoding/json" 11 | "fmt" 12 | "time" 13 | ) 14 | 15 | // NullableTime represents a nullable time for our sample. 16 | type NullableTime struct { 17 | time.Time 18 | } 19 | 20 | // MarshalJSON implements the Marshaler interface. 21 | func (t NullableTime) MarshalJSON() ([]byte, error) { 22 | if t.IsZero() { 23 | return []byte(`null`), nil 24 | } 25 | 26 | return []byte(`"` + t.Format(time.RFC3339) + `"`), nil 27 | } 28 | 29 | // UnmarshalJSON implements the Unmarshaler interface. 30 | func (t *NullableTime) UnmarshalJSON(b []byte) error { 31 | if string(b) == "null" { 32 | t.Time = time.Time{} 33 | return nil 34 | } 35 | 36 | tt, err := time.Parse(`"`+time.RFC3339+`"`, string(b)) 37 | if err != nil { 38 | return err 39 | } 40 | 41 | t.Time = tt 42 | return nil 43 | } 44 | 45 | // main is the entry point for the application. 46 | func main() { 47 | var n NullableTime 48 | if err := json.Unmarshal([]byte("null"), &n); err != nil { 49 | fmt.Println(err) 50 | return 51 | } 52 | 53 | fmt.Printf("%+v", n) 54 | } 55 | -------------------------------------------------------------------------------- /templates/layout.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 23 |
24 | {{ yield }} 25 |
26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /08-concurrency_channels/02-race_conditions/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/LJETaLkVl0 5 | 6 | // go build -race 7 | 8 | // Sample program to show how to use the atomic package to 9 | // provide safe access to numeric types. 10 | package main 11 | 12 | import ( 13 | "fmt" 14 | "runtime" 15 | "sync" 16 | "sync/atomic" 17 | ) 18 | 19 | // counter is a variable incremented by all goroutines. 20 | var counter int64 21 | 22 | // wg is used to wait for the program to finish. 23 | var wg sync.WaitGroup 24 | 25 | // main is the entry point for all Go programs. 26 | func main() { 27 | // Add a count of two, one for each goroutine. 28 | wg.Add(2) 29 | 30 | // Create two goroutines. 31 | go incCounter(1) 32 | go incCounter(2) 33 | 34 | // Wait for the goroutines to finish. 35 | wg.Wait() 36 | 37 | // Display the final value. 38 | fmt.Println("Final Counter:", counter) 39 | } 40 | 41 | // incCounter increments the package level counter variable. 42 | func incCounter(id int) { 43 | for count := 0; count < 2; count++ { 44 | // Safely Add One To Counter. 45 | atomic.AddInt64(&counter, 1) 46 | 47 | // Yield the thread and be placed back in queue. 48 | runtime.Gosched() 49 | } 50 | 51 | // Tell main we are done. 52 | wg.Done() 53 | } 54 | -------------------------------------------------------------------------------- /01-language_syntax/01-variables/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/d2M0Q3mRnd 5 | 6 | // Declare three variables that are initialized to their zero value and three 7 | // declared with a literal value. Declare variables of type string, int and 8 | // bool. Display the values of those variables. 9 | // 10 | // Declare a new variable of type float32 and initialize the variable by 11 | // converting the literal value of Pi (3.14). 12 | package main 13 | 14 | import "fmt" 15 | 16 | // main is the entry point for the application. 17 | func main() { 18 | // Declare variables that are set to their zero value. 19 | var age int 20 | var name string 21 | var legal bool 22 | 23 | // Display the value of those variables. 24 | fmt.Println(age) 25 | fmt.Println(name) 26 | fmt.Println(legal) 27 | 28 | // Declare variables and initialize. 29 | // Using the short variable declaration operator. 30 | month := 10 31 | dayOfWeek := "Tuesday" 32 | happy := true 33 | 34 | // Display the value of those variables. 35 | fmt.Println(month) 36 | fmt.Println(dayOfWeek) 37 | fmt.Println(happy) 38 | 39 | // Perform a type conversion. 40 | pi := float32(3.14) 41 | 42 | // Display the value of that variable. 43 | fmt.Printf("%T [%v]\n", pi, pi) 44 | } 45 | -------------------------------------------------------------------------------- /11-standard_library/01-logging/readme.md: -------------------------------------------------------------------------------- 1 | ## Logging - Standard Library 2 | 3 | Logging is an important part of every program. Logs are our eyes and history to what is happening inside the program as it runs. The standard library provides the log package to support the basic features of logging and the ability for you to extend and customize logging to fit your needs. 4 | 5 | ## Notes 6 | 7 | * Support for logging is already built into the standard library. 8 | * The log package can be easily extended to meet your logging needs. 9 | 10 | ## Links 11 | 12 | http://www.goinggo.net/2013/11/using-log-package-in-go.html 13 | 14 | ## Code Review 15 | 16 | [Use of log package](example1/example1.go) ([Go Playground](http://play.golang.org/p/xO5OuPOJef)) 17 | 18 | [Customizing your own log](example2/example2.go) ([Go Playground](http://play.golang.org/p/008KxiH7Yj)) 19 | 20 | ## Exercises 21 | 22 | ### Exercise 1 23 | 24 | Setup a new program to use the log package. Set the Prefix to your first name and on each log line show the date and long path for the code file. 25 | 26 | [Template](exercises/template1/template1.go) ([Go Playground](http://play.golang.org/p/9eVWni05Ma)) | 27 | [Answer](exercises/exercise1/exercise1.go) ([Go Playground](http://play.golang.org/p/1-l_QmaSvy)) 28 | ___ 29 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /01-language_syntax/06-functions/example3/example3.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/XQS-twjrtl 5 | 6 | // From Spec: 7 | // a short variable declaration may redeclare variables provided they 8 | // were originally declared earlier in the same block with the same 9 | // type, and at least one of the non-blank variables is new. 10 | 11 | // Sample program to show some of the mechanics behind the 12 | // short variable declaration operator redeclares. 13 | package main 14 | 15 | import "fmt" 16 | 17 | // user is a struct type that declares user information. 18 | type user struct { 19 | id int 20 | name string 21 | } 22 | 23 | // main is the entry point for the application. 24 | func main() { 25 | // Declare the error variable. 26 | var err1 error 27 | 28 | // The short variable declaration operator will 29 | // declare u and redeclare err1. 30 | u, err1 := getUser() 31 | if err1 != nil { 32 | return 33 | } 34 | 35 | fmt.Println(u) 36 | 37 | // The short variable declaration operator will 38 | // redeclare u and declare err2. 39 | u, err2 := getUser() 40 | if err2 != nil { 41 | return 42 | } 43 | 44 | fmt.Println(u) 45 | } 46 | 47 | // getUser returns a pointer of type user. 48 | func getUser() (*user, error) { 49 | return &user{1432, "Betty"}, nil 50 | } 51 | -------------------------------------------------------------------------------- /10-testing/exercises/exercise1/bench_test.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | /* 5 | http://golang.org/cmd/go/#hdr-Description_of_testing_flags 6 | go test -run=XXX -bench=. 7 | go test -run=XXX -bench=BenchmarkSprintf 8 | go test -run=XXX -bench=BenchmarkFormat 9 | go test -run=XXX -bench=BenchmarkAtoi 10 | */ 11 | 12 | // Write three benchmark tests for converting an integer into a string. First using the 13 | // fmt.Sprintf function, then the strconv.FormatInt function and then strconv.Itoa. 14 | // Identify which function performs the best. 15 | package main 16 | 17 | import ( 18 | "fmt" 19 | "strconv" 20 | "testing" 21 | ) 22 | 23 | // BenchmarkSprintf provides performance numbers for the fmt.Sprintf function 24 | func BenchmarkSprintf(b *testing.B) { 25 | number := 10 26 | 27 | for i := 0; i < b.N; i++ { 28 | fmt.Sprintf("%d", number) 29 | } 30 | } 31 | 32 | // BenchmarkFormat provides performance numbers for the strconv.FormatInt function 33 | func BenchmarkFormat(b *testing.B) { 34 | number := int64(10) 35 | 36 | for i := 0; i < b.N; i++ { 37 | strconv.FormatInt(number, 10) 38 | } 39 | } 40 | 41 | // BenchmarkItoa provides performance numbers for the strconv.Itoa function 42 | func BenchmarkItoa(b *testing.B) { 43 | number := 10 44 | 45 | for i := 0; i < b.N; i++ { 46 | strconv.Itoa(number) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /14-cli/03-flow/readme.md: -------------------------------------------------------------------------------- 1 | ## Conditional Control Flow 2 | 3 | Commands that complete successfully exit with status zero; all non-zero exit 4 | statuses indicate failure. Conventionally, a status of 1 is used as the generic 5 | program error status, and 2 indicates user error (such as invalid input or 6 | arguments), but any value in the range of 0-127 may be used. On many systems, 7 | statuses 128-255 have special meaning (such as signal reporting) and should not 8 | be set. The exit status of the last process in a pipeline is used as the status 9 | for the entire pipeline. 10 | 11 | The success or failure of a pipeline may be used to run additional pipelines: 12 | 13 | rm some-file && echo success || echo failure 14 | 15 | Pipelines chained in this way are known as "lists" and have left-to-right 16 | precedence, such that the above will always either echo success or failure, but 17 | never both. Most commonly, AND sequences are chained together so that a series 18 | of tasks can proceed only if every task before it was successful: 19 | 20 | task1 && task2 && task3 21 | 22 | If semicolons were used instead (or if each task were on its own line), then 23 | the tasks would run regardless of whether the previous tasks failed. 24 | 25 | ## Example 26 | 27 | [Setting exit status](example1/parent.go) 28 | ___ 29 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 30 | -------------------------------------------------------------------------------- /01-language_syntax/03-pointers/advanced/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://docs.google.com/document/d/1CxgUBPlx9iJzkz9JWkb6tIpTe5q32QDmz8l0BouG0Cw/view 5 | 6 | // http://play.golang.org/p/931Cw6uzsn 7 | 8 | // go build -gcflags -m 9 | 10 | // Sample program to show varaibles stay on or escape from the stack. 11 | package main 12 | 13 | import "fmt" 14 | 15 | // main is the entry point for the application. 16 | func main() { 17 | stayOnStack() 18 | escapeToHeap() 19 | } 20 | 21 | // stayOnStack shows how the variable does not escape. 22 | func stayOnStack() { 23 | // Declare a variable of type integer. 24 | var x int 25 | 26 | // Display the address of the variable. 27 | println("Stack Addr:", &x) 28 | } 29 | 30 | // escapeToHeap shows how the variable does escape. 31 | func escapeToHeap() { 32 | // Declare a variable of type integer. 33 | var x int 34 | 35 | // Display the address of the variable. 36 | fmt.Println("Heap Addr:", &x) 37 | } 38 | 39 | /* 40 | ./example1.go:20: can inline stayOnStack 41 | ./example1.go:15: inlining call to stayOnStack 42 | ./example1.go:31: moved to heap: x 43 | ./example1.go:34: &x escapes to heap 44 | ./example1.go:34: escapeToHeap ... argument does not escape 45 | ./example1.go:15: stayOnStack &x does not escape 46 | ./example1.go:25: stayOnStack &x does not escape 47 | */ 48 | -------------------------------------------------------------------------------- /08-concurrency_channels/02-race_conditions/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/yBFA-MDcMw 5 | 6 | // Fix the race condition in this program. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "math/rand" 12 | "sync" 13 | "time" 14 | ) 15 | 16 | // numbers maintains a set of random numbers. 17 | var numbers []int 18 | 19 | // wg is used to wait for the program to finish. 20 | var wg sync.WaitGroup 21 | 22 | // init is called prior to main. 23 | func init() { 24 | rand.Seed(time.Now().UnixNano()) 25 | } 26 | 27 | // main is the entry point for all Go programs. 28 | func main() { 29 | // Add a count for each goroutine we will create. 30 | wg.Add(3) 31 | 32 | // Create three goroutines to generate random numbers. 33 | go random(10) 34 | go random(10) 35 | go random(10) 36 | 37 | // Wait for all the goroutines to finish. 38 | wg.Wait() 39 | 40 | // Display the set of random numbers. 41 | for i, number := range numbers { 42 | fmt.Println(i, number) 43 | } 44 | } 45 | 46 | // random generates random numbers and stores them into a slice. 47 | func random(amount int) { 48 | // Generate as many random numbers as specified. 49 | for i := 0; i < amount; i++ { 50 | n := rand.Intn(100) 51 | numbers = append(numbers, n) 52 | } 53 | 54 | // Tell main we are done. 55 | wg.Done() 56 | } 57 | -------------------------------------------------------------------------------- /11-standard_library/01-logging/example1/example1.go: -------------------------------------------------------------------------------- 1 | // http://play.golang.org/p/xO5OuPOJef 2 | 3 | // Sample program to show how to use the log package 4 | // from the standard library. 5 | package main 6 | 7 | import ( 8 | "log" 9 | "os" 10 | ) 11 | 12 | // init is called before main. 13 | func init() { 14 | // Change the output device from the default 15 | // stderr to stdout. 16 | log.SetOutput(os.Stdout) 17 | 18 | // Set the prefix string for each log line. 19 | log.SetPrefix("TRACE: ") 20 | 21 | // Set the extra log info. 22 | setFlags() 23 | } 24 | 25 | // setFlags adds extra information on each log line. 26 | func setFlags() { 27 | /* 28 | Ldate // the date: 2009/01/23 29 | Ltime // the time: 01:23:23 30 | Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. 31 | Llongfile // full file name and line number: /a/b/c/d.go:23 32 | Lshortfile // final file name element and line number: d.go:23. overrides Llongfile 33 | LstdFlags // Ldate | Ltime // initial values for the standard logger 34 | */ 35 | 36 | log.SetFlags(log.LstdFlags | log.Lshortfile) 37 | } 38 | 39 | // main is the entry point for the application. 40 | func main() { 41 | log.Println("main function started") 42 | 43 | names := []string{"Henry", "Lisa", "Bill", "Matt"} 44 | log.Printf("These are named %+v\n", names) 45 | 46 | log.Fatalln("Terminate Program") 47 | 48 | log.Println("main function ended") 49 | } 50 | -------------------------------------------------------------------------------- /01-language_syntax/02-struct_types/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/tnn-8hJPUd 5 | 6 | // Declare a struct type to maintain information about a user (name, email and age). 7 | // Create a value of this type, initialize with values and display each field. 8 | // 9 | // Declare and initialize an anonymous struct type with the same three fields. Display the value. 10 | package main 11 | 12 | import ( 13 | "fmt" 14 | ) 15 | 16 | // user represents a user in the system. 17 | type user struct { 18 | name string 19 | email string 20 | age int 21 | } 22 | 23 | // main is the entry point for the application. 24 | func main() { 25 | // Declare variable of type user and init using a struct literal. 26 | bill := user{ 27 | name: "Bill", 28 | email: "bill@ardanstudios.com", 29 | age: 45, 30 | } 31 | 32 | // Display the field values. 33 | fmt.Println("Name", bill.name) 34 | fmt.Println("Email", bill.email) 35 | fmt.Println("Age", bill.age) 36 | 37 | // Declare a variable using an anonymous struct. 38 | ed := struct { 39 | name string 40 | email string 41 | age int 42 | }{ 43 | name: "Ed", 44 | email: "ed@ardanstudios.com", 45 | age: 46, 46 | } 47 | 48 | // Display the field values. 49 | fmt.Println("Name", ed.name) 50 | fmt.Println("Email", ed.email) 51 | fmt.Println("Age", ed.age) 52 | } 53 | -------------------------------------------------------------------------------- /09-concurrency_patterns/task/task.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Package task provides a pool of goroutines to perform tasks. 5 | package task 6 | 7 | import "sync" 8 | 9 | // Worker must be implemented by types that want to use 10 | // the run pool. 11 | type Worker interface { 12 | Work() 13 | } 14 | 15 | // Task provides a pool of goroutines that can execute any Worker 16 | // tasks that are submitted. 17 | type Task struct { 18 | work chan Worker 19 | wg sync.WaitGroup 20 | } 21 | 22 | // New creates a new work pool. 23 | func New(maxGoroutines int) *Task { 24 | t := Task{ 25 | // Using an unbuffered channel because we want the 26 | // guarentee of knowing the work being submitted is 27 | // actually being worked on after the call to Run returns. 28 | work: make(chan Worker), 29 | } 30 | 31 | // The goroutines are the pool. So we could add code 32 | // to change the size of the pool later on. 33 | 34 | t.wg.Add(maxGoroutines) 35 | for i := 0; i < maxGoroutines; i++ { 36 | go func() { 37 | for w := range t.work { 38 | w.Work() 39 | } 40 | t.wg.Done() 41 | }() 42 | } 43 | 44 | return &t 45 | } 46 | 47 | // Do submits work to the pool. 48 | func (t *Task) Do(w Worker) { 49 | t.work <- w 50 | } 51 | 52 | // Shutdown waits for all the goroutines to shutdown. 53 | func (t *Task) Shutdown() { 54 | close(t.work) 55 | t.wg.Wait() 56 | } 57 | -------------------------------------------------------------------------------- /11-standard_library/03-writers_readers/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/LY5P96Xrbl 5 | 6 | // https://gist.github.com/jmoiron/e9f72720cef51862b967#file-01-curl-go 7 | // Sample code provided by Jason Moiron 8 | // 9 | // ./example2 http://www.goinggo.net/feeds/posts/default 10 | 11 | // Sample program to show how to write a simple version of curl using 12 | // the io.Reader and io.Writer interface support. 13 | package main 14 | 15 | import ( 16 | "fmt" 17 | "io" 18 | "net/http" 19 | "os" 20 | ) 21 | 22 | // init is called before main. 23 | func init() { 24 | if len(os.Args) != 2 { 25 | fmt.Println("Usage: ./example2 ") 26 | os.Exit(2) 27 | } 28 | } 29 | 30 | // main is the entry point for the application. 31 | func main() { 32 | // resp here is a response, and resp.Body is an io.Reader 33 | resp, err := http.Get(os.Args[1]) 34 | if err != nil { 35 | fmt.Println(err) 36 | return 37 | } 38 | // Close the ReadCloser when we're done with it. 39 | // We don't need to check the error, since 40 | // Close errors on Readers are meaningless. 41 | defer resp.Body.Close() 42 | 43 | // io.Copy(dst io.Writer, src io.Reader) (int64, error) 44 | // Copies from the Body to Stdout, returning any Read or Write error. 45 | _, err = io.Copy(os.Stdout, resp.Body) 46 | if err != nil { 47 | fmt.Println(err) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/01-methods/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/zHePe-yTUw 5 | 6 | // Sample program to show how to declare methods against 7 | // a named type. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // duration is a named type that represents a duration 15 | // of time in Nanosecond. 16 | type duration int64 17 | 18 | const ( 19 | nanosecond duration = 1 20 | microsecond = 1000 * nanosecond 21 | millisecond = 1000 * microsecond 22 | second = 1000 * millisecond 23 | minute = 60 * second 24 | hour = 60 * minute 25 | ) 26 | 27 | // setHours sets the specified number of hours. 28 | func (d *duration) setHours(h float64) { 29 | *d = duration(h) * hour 30 | } 31 | 32 | // hours returns the duration as a floating point number of hours. 33 | func (d duration) hours() float64 { 34 | hour := d / hour 35 | nsec := d % hour 36 | return float64(hour) + float64(nsec)*(1e-9/60/60) 37 | } 38 | 39 | // main is the entry point for the application. 40 | func main() { 41 | // Declare a variable of type duration set to 42 | // its zero value. 43 | var dur duration 44 | 45 | // Change the value of dur to equal 46 | // five seconds. 47 | dur.setHours(5) 48 | 49 | // Display the new value of dur. 50 | fmt.Println("Hours:", dur.hours()) 51 | } 52 | -------------------------------------------------------------------------------- /11-standard_library/01-logging/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/9eVWni05Ma 5 | 6 | // Setup a new program to use the log package. Set the Prefix to your first name and on each log line show 7 | // the date and long path for the code file. 8 | package main 9 | 10 | // Add imports. 11 | 12 | // init is called before main. 13 | func init() { 14 | // Change the output device from the default stderr to stdout. 15 | 16 | // Set the prefix string for each log line. 17 | 18 | // Set the extra log info. 19 | } 20 | 21 | // setFlags adds extra information on each log line. 22 | func setFlags() { 23 | /* 24 | Ldate // the date: 2009/01/23 25 | Ltime // the time: 01:23:23 26 | Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. 27 | Llongfile // full file name and line number: /a/b/c/d.go:23 28 | Lshortfile // final file name element and line number: d.go:23. overrides Llongfile 29 | LstdFlags // Ldate | Ltime // initial values for the standard logger 30 | */ 31 | 32 | // Set the flags. 33 | } 34 | 35 | // main is the entry point for the application. 36 | func main() { 37 | // Use the Println function. 38 | 39 | // Create a slice of strings and initialize with names. 40 | // Log the values of the slice. 41 | 42 | // Use the Fatalln function. 43 | } 44 | -------------------------------------------------------------------------------- /12-reflection/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/OSeD9F_P46 5 | 6 | /* 7 | An interface is a reference type who's header is a two word value. The 8 | first word represents the type of the value and the second is the data 9 | itself. 10 | 11 | Something like this: 12 | type interface struct { 13 | Type uintptr // points to the type of the interface implementation 14 | Data uintptr // holds the data for the interface's receiver 15 | } 16 | 17 | interface{} represents the empty set of methods and is satisfied by any 18 | value at all, since any value has zero or more methods. 19 | */ 20 | 21 | // Sample program to show how the empty interface works. 22 | package main 23 | 24 | import ( 25 | "encoding/json" 26 | "fmt" 27 | ) 28 | 29 | // User is a sample struct. 30 | type User struct { 31 | Name string 32 | Email string 33 | } 34 | 35 | // main is the entry point for the application. 36 | func main() { 37 | // Declare a variable of type User. 38 | user := User{ 39 | Name: "Henry Ford", 40 | Email: "henry@ford.com", 41 | } 42 | 43 | fmt.Println(JSONString(&user)) 44 | } 45 | 46 | // JSONString converts any value into a JSON string. 47 | func JSONString(value interface{}) string { 48 | data, err := json.MarshalIndent(value, "", " ") 49 | if err != nil { 50 | return "" 51 | } 52 | 53 | return string(data) 54 | } 55 | -------------------------------------------------------------------------------- /02-array_slices_maps/01-arrays/readme.md: -------------------------------------------------------------------------------- 1 | ## Arrays - Arrays, Slices and Maps 2 | 3 | Arrays are a special data structure in Go that allow us to allocate contiguous blocks of fixed size memory. Arrays have some special features in Go related to how they are declared and viewed as types. 4 | 5 | ## Notes 6 | 7 | * Arrays are fixed length data structures that can't change. 8 | * Arrays of different sizes are considered to be of different types. 9 | * Memory is allocated as a contiguous block. 10 | 11 | ## Code Review 12 | 13 | [Declare, initialize and iterate](example1/example1.go) ([Go Playground](https://play.golang.org/p/DGr8Zp9L_w)) 14 | 15 | [Different type arrays](example2/example2.go) ([Go Playground](http://play.golang.org/p/LVD43cYBNS)) 16 | 17 | [Contiguous memory allocations](example3/example3.go) ([Go Playground](https://play.golang.org/p/s4BSgxz0Y3)) 18 | 19 | ## Exercises 20 | 21 | ### Exercise 1 22 | 23 | Declare an array of 5 strings with each element initialized to its zero value. Declare a second array of 5 strings and initialize this array with literal string values. Assign the second array to the first and display the results of the first array. 24 | 25 | [Template](exercises/template1/template1.go) ([Go Playground](http://play.golang.org/p/ggjjRPzhAB)) | 26 | [Answer](exercises/exercise1/exercise1.go) ([Go Playground](http://play.golang.org/p/Pa3mrTCcpB)) 27 | ___ 28 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/02-interfaces/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/eY2Ms-UF-t 5 | 6 | // Sample program to show how to use an interface in Go. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | // notifier is an interface that defines notification 14 | // type behavior. 15 | type notifier interface { 16 | notify() 17 | } 18 | 19 | // user defines a user in the program. 20 | type user struct { 21 | name string 22 | email string 23 | } 24 | 25 | // notify implements the notifier interface with a pointer receiver. 26 | func (u *user) notify() { 27 | fmt.Printf("Sending User Email To %s<%s>\n", 28 | u.name, 29 | u.email) 30 | } 31 | 32 | // main is the entry point for the application. 33 | func main() { 34 | // Create a value of type User and send a notification. 35 | u := user{"Bill", "bill@email.com"} 36 | 37 | // Values of type user do not implement the interface because pointer 38 | // receivers don't belong to the method set of a value. 39 | 40 | sendNotification(u) 41 | 42 | // ./example1.go:40: cannot use u (type user) as type notifier in argument to sendNotification: 43 | // user does not implement notifier (notify method has pointer receiver) 44 | } 45 | 46 | // sendNotification accepts values that implement the notifier 47 | // interface and sends notifications. 48 | func sendNotification(n notifier) { 49 | n.notify() 50 | } 51 | -------------------------------------------------------------------------------- /01-language_syntax/03-pointers/exercises/exercise2/exercise2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/oEtveMoO1s 5 | 6 | // Declare a struct type and create a value of this type. Declare a function 7 | // that can change the value of some field in this struct type. Display the 8 | // value before and after the call to your function. 9 | package main 10 | 11 | import "fmt" 12 | 13 | // user represents a user in the system. 14 | type user struct { 15 | name string 16 | email string 17 | accessLevel int 18 | } 19 | 20 | // main is the entry point for the application. 21 | func main() { 22 | // Create a variable of type user and initialize each field. 23 | bill := user{ 24 | name: "Bill", 25 | email: "bill@ardanstudios.com", 26 | accessLevel: 1, 27 | } 28 | 29 | // Display the value of the accessLevel field. 30 | fmt.Println("access:", bill.accessLevel) 31 | 32 | // Share the bill variable with the accessLevel function 33 | // along with a value to update the accessLevel field with. 34 | accessLevel(&bill, 10) 35 | 36 | // Display the value of the accessLevel field again. 37 | fmt.Println("access:", bill.accessLevel) 38 | } 39 | 40 | // accessLevel changes the value of the users access level. 41 | func accessLevel(u *user, accessLevel int) { 42 | // Set of value of the accessLevel field to the value 43 | // that is passed in. 44 | u.accessLevel = accessLevel 45 | } 46 | -------------------------------------------------------------------------------- /02-array_slices_maps/02-slices/example4/example4.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/UzmwiMWDwd 5 | 6 | // Sample program to show how to grow a slice using the built-in function append 7 | // and how append grows the capacity of the underlying array. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Declare a nil slice of strings. 17 | var data []string 18 | 19 | // Capture the length and capacity of the slice. 20 | lastLen := len(data) 21 | lastCap := cap(data) 22 | 23 | // Append ~10k strings to the slice. 24 | for record := 1; record <= 10240; record++ { 25 | // Use the built-in function append to add to the slice. 26 | data = append(data, fmt.Sprintf("Rec: %d", record)) 27 | 28 | // when the capacity of the slice changes, display the changes. 29 | if lastCap != cap(data) { 30 | // Calculate the percent of change. 31 | lenChg := float64(len(data)-lastLen) / float64(lastLen) * 100 32 | capChg := float64(cap(data)-lastCap) / float64(lastCap) * 100 33 | 34 | // Save the new values for length and capacity. 35 | lastLen = len(data) 36 | lastCap = cap(data) 37 | 38 | // Display the results. 39 | fmt.Printf("Addr[%p]\tIndex[%d]\t\tLen[%d - %2.f%%]\t\tCap[%d - %2.f%%]\n", 40 | &data[0], 41 | record, 42 | len(data), 43 | lenChg, 44 | cap(data), 45 | capChg) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /00-slides/day_1_training.md: -------------------------------------------------------------------------------- 1 | ## Go Training - Day 1 2 | On this day we take our initial tour of the language. We learn about variables, types, data structures and OOP. We also explore what is idiomatic and how the language is very orthogonal. This includes following the community standards for coding and style. 3 | 4 | *Note: This material has been designed to be taught in a classroom environment. The code is well commented but missing some of the contextual concepts and ideas that will be covered in class.* 5 | 6 | #### Language Syntax 7 | [Variables](../01-language_syntax/01-variables/readme.md) | 8 | [Struct Types](../01-language_syntax/02-struct_types/readme.md) | 9 | [Pointers](../01-language_syntax/03-pointers/readme.md) | 10 | [Constants](../01-language_syntax/04-constants/readme.md) | 11 | [Type Conversions](../01-language_syntax/05-type_conversions/readme.md) | 12 | [Functions](../01-language_syntax/06-functions/readme.md) 13 | 14 | #### Arrays, Slices and Maps 15 | [Arrays](../02-array_slices_maps/01-arrays/readme.md) | 16 | [Slices](../02-array_slices_maps/02-slices/readme.md) | 17 | [Maps](../02-array_slices_maps/03-maps/readme.md) 18 | 19 | #### Methods, Interfaces and Embedding (OOP) 20 | [Methods](../03-methods_interfaces_embedding/01-methods/readme.md) | 21 | [Interfaces](../03-methods_interfaces_embedding/02-interfaces/readme.md) | 22 | [Embedding](../03-methods_interfaces_embedding/03-embedding/readme.md) 23 | ___ 24 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /01-language_syntax/04-constants/readme.md: -------------------------------------------------------------------------------- 1 | ## Constants - Language Syntax 2 | 3 | Constants are a way to create a named identifier who's value can never change. They also provide an incredible amount of flexibility to the language. The way constants are implemented in Go is very unique. 4 | 5 | ## Notes 6 | 7 | * Constants are not variables. 8 | * They existing only at compilation. 9 | * Untyped constants can be implictly converted where typed constants and variables can't. 10 | * Think of untyped constants as having a Kind, not a Type. 11 | 12 | ## Links 13 | 14 | https://golang.org/ref/spec#Constants 15 | 16 | http://blog.golang.org/constants 17 | 18 | http://www.goinggo.net/2014/04/introduction-to-numeric-constants-in-go.html 19 | 20 | ## Code Review 21 | 22 | [Declare and inialize constants](example1/example1.go) ([Go Playground](http://play.golang.org/p/fkQx0inUJ3)) 23 | 24 | [Parallel type system (Kind)](example2/example2.go) ([Go Playground](http://play.golang.org/p/ExxRWe6jUz)) 25 | 26 | ## Exercises 27 | 28 | ### Exercise 1 29 | 30 | **Part A:** Declare an untyped and typed constant and display their values. 31 | 32 | **Part B:** Multiply two literal constants into a typed variable and display the value. 33 | 34 | [Template](exercises/template1/template1.go) ([Go Playground](http://play.golang.org/p/qG3-9yn5_6)) | 35 | [Answer](exercises/exercise1/exercise1.go) ([Go Playground](http://play.golang.org/p/d2gkKxEftw)) 36 | ___ 37 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /01-language_syntax/06-functions/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/bYY-TRjfH0 5 | 6 | // Sample program to show how functions can return multiple values while using 7 | // named and struct types. 8 | package main 9 | 10 | import ( 11 | "encoding/json" 12 | "fmt" 13 | ) 14 | 15 | // user is a struct type that declares user information. 16 | type user struct { 17 | ID int 18 | Name string 19 | } 20 | 21 | // main is the entry point for the application. 22 | func main() { 23 | // Retrieve the user profile. 24 | u, err := retrieveUser("sally") 25 | if err != nil { 26 | fmt.Println(err) 27 | return 28 | } 29 | 30 | // Display the user profile. 31 | fmt.Printf("%+v\n", *u) 32 | } 33 | 34 | // retrieveUser retrieves the user document for the specified 35 | // user and returns a pointer to a user type value. 36 | func retrieveUser(name string) (*user, error) { 37 | // Make a call to get the user in a json response. 38 | r, err := getUser(name) 39 | if err != nil { 40 | return nil, err 41 | } 42 | 43 | // Unmarshal the json document into a value of 44 | // the user struct type. 45 | var u user 46 | err = json.Unmarshal([]byte(r), &u) 47 | return &u, err 48 | } 49 | 50 | // GetUser simulates a web call that returns a json 51 | // document for the specified user. 52 | func getUser(name string) (string, error) { 53 | response := `{"id":1432, "name":"sally"}` 54 | return response, nil 55 | } 56 | -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/03-embedding/example3/example3.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/BgEoThS7u9 5 | 6 | // Sample program to show how embedded types work with interfaces. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | // notifier is an interface that defined notification 14 | // type behavior. 15 | type notifier interface { 16 | notify() 17 | } 18 | 19 | // user defines a user in the program. 20 | type user struct { 21 | name string 22 | email string 23 | } 24 | 25 | // notify implements a method that can be called via 26 | // a value of type user. 27 | func (u *user) notify() { 28 | fmt.Printf("Sending user email To %s<%s>\n", 29 | u.name, 30 | u.email) 31 | } 32 | 33 | // admin represents an admin user with privileges. 34 | type admin struct { 35 | user 36 | level string 37 | } 38 | 39 | // main is the entry point for the application. 40 | func main() { 41 | // Create an admin user. 42 | ad := admin{ 43 | user: user{ 44 | name: "john smith", 45 | email: "john@yahoo.com", 46 | }, 47 | level: "super", 48 | } 49 | 50 | // Send the admin user a notification. 51 | // The embedded inner type's implementation of the 52 | // interface is "promoted" to the outer type. 53 | sendNotification(&ad) 54 | } 55 | 56 | // sendNotification accepts values that implement the notifier 57 | // interface and sends notifications. 58 | func sendNotification(n notifier) { 59 | n.notify() 60 | } 61 | -------------------------------------------------------------------------------- /13-http/readme.md: -------------------------------------------------------------------------------- 1 | ## HTTP - API's 2 | 3 | The Go standard library provides all the critical building blocks for producing web sites and APIs. 4 | 5 | ## Notes 6 | 7 | * net/http provides an HTTP/1.1 compliant protocol implementation. 8 | * There is support for SSL/TLS. 9 | * Adding routing and middleware to your applications requires only a few simple patterns. 10 | 11 | ## Links 12 | 13 | https://golang.org/pkg/net/http/ 14 | 15 | https://golang.org/doc/articles/wiki/ 16 | 17 | https://github.com/bradfitz/http2 18 | 19 | https://github.com/interagent/http-api-design/blob/master/README.md 20 | 21 | http://www.restapitutorial.com/httpstatuscodes.html 22 | 23 | ## Code Review 24 | 25 | [Hello World Server](example1/main.go) ([Go Playground](https://play.golang.org/p/leTrm6v1yG)) 26 | 27 | [1 Line File Server](example2/main.go) ([Go Playground](https://play.golang.org/p/Qmj_C5PEs1)) 28 | 29 | [Request and Response Basics](example3/main.go) ([Go Playground](https://play.golang.org/p/-dhowrDOO4)) 30 | 31 | ## Advanced Code Review 32 | 33 | [Web API](api) 34 | Sample code that provides best practices for building a RESTful API in Go. It leverages the standard library except for the router where a package named [httptreemux](https://github.com/dimfeld/httptreemux) is used. This router provides some nice conveniences such as handling verbs and access to parameters. 35 | 36 | ## Exercises 37 | 38 | ### Exercise 1 39 | 40 | TBD 41 | ___ 42 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 43 | -------------------------------------------------------------------------------- /01-language_syntax/03-pointers/example3/example3.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/VYqb11RiWr 5 | 6 | // Sample program to show the basic concept of using a pointer 7 | // to share data. 8 | package main 9 | 10 | import "fmt" 11 | 12 | // user represents a user in the system. 13 | type user struct { 14 | name string 15 | email string 16 | logins int 17 | } 18 | 19 | // main is the entry point for the application. 20 | func main() { 21 | // Declare and initialize a variable named bill of type user. 22 | bill := user{ 23 | name: "Bill", 24 | email: "bill@ardanstudios.com", 25 | } 26 | 27 | //** We don't need to include all the fields when specifying field 28 | // names with a struct literal. 29 | 30 | // Pass the "address of" the bill value. 31 | display(&bill) 32 | 33 | // Pass the "address of" the logins field from within the bill value. 34 | increment(&bill.logins) 35 | 36 | // Pass the "address of" the bill value. 37 | display(&bill) 38 | } 39 | 40 | // increment declares logins as a pointer variable whose value is 41 | // always an address and points to values of type int. 42 | func increment(logins *int) { 43 | *logins++ 44 | fmt.Printf("&logins[%p] logins[%p] *logins[%d]\n", &logins, logins, *logins) 45 | } 46 | 47 | // display declares u as user pointer variable whose value is always an address 48 | // and points to values of type user. 49 | func display(u *user) { 50 | fmt.Printf("%p\t%+v\n", u, *u) 51 | } 52 | -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/01-methods/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/AYsB78Dlxb 5 | 6 | // Sample program to show how to declare methods and how the Go 7 | // compiler supports them. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // user defines a user in the program. 15 | type user struct { 16 | name string 17 | email string 18 | } 19 | 20 | // notify implements a method with a value receiver. 21 | func (u user) notify() { 22 | fmt.Printf("Sending User Email To %s<%s>\n", 23 | u.name, 24 | u.email) 25 | } 26 | 27 | // changeEmail implements a method with a pointer receiver. 28 | func (u *user) changeEmail(email string) { 29 | u.email = email 30 | } 31 | 32 | // main is the entry point for the application. 33 | func main() { 34 | // Values of type user can be used to call methods 35 | // declared with a value receiver. 36 | bill := user{"Bill", "bill@email.com"} 37 | bill.notify() 38 | 39 | // Pointers of type user can also be used to call methods 40 | // declared with a value receiver. 41 | lisa := &user{"Lisa", "lisa@email.com"} 42 | lisa.notify() 43 | 44 | // Values of type user can be used to call methods 45 | // declared with a pointer receiver. 46 | bill.changeEmail("bill@gmail.com") 47 | bill.notify() 48 | 49 | // Pointers of type user can be used to call methods 50 | // declared with a pointer receiver. 51 | lisa.changeEmail("lisa@gmail.com") 52 | lisa.notify() 53 | } 54 | -------------------------------------------------------------------------------- /12-reflection/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/lgMQHWpZul 5 | 6 | // Declare a struct type that represents a request for a customer invoice. Include a CustomerID and InvoiceID field. Define 7 | // tags that can be used to validate the request. Define tags that specify both the length and range for the ID to be valid. 8 | // Declare a function named validate that accepts values of any type and processes the tags. Display the resutls of the validation. 9 | package main 10 | 11 | // Add imports. 12 | 13 | // Declare a struct type named Customer. Add the fields CustomerID of type int 14 | // with the tag `length:"3" range:"100-300"`, and field InvoiceID of type int 15 | // with tag `length:"5" range:"60000-99999"`. 16 | 17 | // validate performs data validation on any struct type value. 18 | func validate( /* parameter */ ) { 19 | // Retrieve the value that the interface contains or points to. 20 | 21 | // Iterate over the fields of the struct value. 22 | { 23 | // Retrieve the field information. 24 | 25 | // Get the value as an int, string and the length. 26 | 27 | // Test the length of the value based on the tag setting. 28 | 29 | // Test the range of the value based on the tag setting. 30 | } 31 | } 32 | 33 | // main is the entry point for the application. 34 | func main() { 35 | // Declare a variable of type Customer and initialize it. 36 | 37 | // Validate the value and display the results. 38 | } 39 | -------------------------------------------------------------------------------- /02-array_slices_maps/02-slices/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/BSNAUj2pd- 5 | 6 | // Declare a nil slice of integers. Declare a nil slice of integers. Create a 7 | // loop that appends 10 values to the slice. Iterate over the slice and display 8 | // each value. Iterate over the slice and display each value. 9 | // 10 | // Declare a slice of five strings and initialize the slice with string literal 11 | // values. Display all the elements. Take a slice of index one and two 12 | // and display the index position and value of each element in the new slice. 13 | package main 14 | 15 | import "fmt" 16 | 17 | // main is the entry point for the application. 18 | func main() { 19 | // Declare a nil slice of integers. 20 | var numbers []int 21 | 22 | // Append numbers to the slice. 23 | for i := 0; i < 5; i++ { 24 | numbers = append(numbers, i*10) 25 | } 26 | 27 | // Display each value. 28 | for _, number := range numbers { 29 | fmt.Println(number) 30 | } 31 | 32 | // Declare a slice of strings. 33 | names := []string{"Bill", "Lisa", "Jim", "Cathy"} 34 | 35 | // Display each index position and name. 36 | for i, name := range names { 37 | fmt.Printf("Index: %d Name: %s\n", i, name) 38 | } 39 | 40 | // Take a slice of index 1 and 2. 41 | slice := names[1:3] 42 | 43 | // Display the value of the new slice. 44 | for i, name := range slice { 45 | fmt.Printf("Index: %d Name: %s\n", i, name) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /01-language_syntax/01-variables/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/m4PJ0FpSwX 5 | 6 | // The playground is actually a 64-bit env with 32-bit pointers 7 | // The os/arch combo is named nacl/amd64p32 8 | 9 | // Sample program to show how to declare variables. 10 | package main 11 | 12 | import "fmt" 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Declare variables that are set to their zero value. 17 | var a int 18 | var b string 19 | var c float64 20 | var d bool 21 | 22 | fmt.Printf("var a int \t %T [%v]\n", a, a) 23 | fmt.Printf("var b string \t %T [%v]\n", b, b) 24 | fmt.Printf("var c float64 \t %T [%v]\n", c, c) 25 | fmt.Printf("var d bool \t %T [%v]\n\n", d, d) 26 | 27 | // Declare variables and initialize. 28 | // Using the short variable declaration operator. 29 | aa := 10 30 | bb := "hello" 31 | cc := 3.14159 32 | dd := true 33 | 34 | fmt.Printf("aa := 10 \t %T [%v]\n", aa, aa) 35 | fmt.Printf("bb := \"hello\" \t %T [%v]\n", bb, bb) 36 | fmt.Printf("cc := 3.14159 \t %T [%v]\n", cc, cc) 37 | fmt.Printf("dd := true \t %T [%v]\n\n", dd, dd) 38 | 39 | // Specify type and perform a conversion. 40 | aaa := int32(10) 41 | 42 | fmt.Printf("aaa := int32(10) %T [%v]\n", aaa, aaa) 43 | } 44 | 45 | /* 46 | Zero Values: 47 | 48 | Type Initialized Value 49 | Boolean false 50 | Integer 0 51 | Floating Point 0 52 | Complex 0i 53 | String "" (empty string) 54 | Pointer nil 55 | */ 56 | -------------------------------------------------------------------------------- /10-testing/01-testing/example2/example2_test.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Sample test to show how to write a basic unit table test. 5 | package example2 6 | 7 | import ( 8 | "net/http" 9 | "testing" 10 | ) 11 | 12 | const succeed = "\u2713" 13 | const failed = "\u2717" 14 | 15 | // TestDownload validates the http Get function can download content and 16 | // handles different status conditions properly. 17 | func TestDownload(t *testing.T) { 18 | var urls = []struct { 19 | url string 20 | statusCode int 21 | }{ 22 | {"http://www.goinggo.net/feeds/posts/default?alt=rss", http.StatusOK}, 23 | {"http://rss.cnn.com/rss/cnn_topstorie.rss", http.StatusNotFound}, 24 | } 25 | 26 | t.Log("Given the need to test downloading different content.") 27 | { 28 | for _, u := range urls { 29 | t.Logf("\tWhen checking \"%s\" for status code \"%d\"", u.url, u.statusCode) 30 | { 31 | resp, err := http.Get(u.url) 32 | if err != nil { 33 | t.Fatal("\t\tShould be able to make the Get call.", 34 | failed, err) 35 | } 36 | t.Log("\t\tShould be able to make the Get call.", 37 | succeed) 38 | 39 | defer resp.Body.Close() 40 | 41 | if resp.StatusCode == u.statusCode { 42 | t.Logf("\t\tShould receive a \"%d\" status code. %v", 43 | u.statusCode, succeed) 44 | } else { 45 | t.Errorf("\t\tShould receive a \"%d\" status code. %v %v", 46 | u.statusCode, failed, resp.StatusCode) 47 | } 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /02-array_slices_maps/03-maps/readme.md: -------------------------------------------------------------------------------- 1 | ## Maps - Arrays, Slices and Maps 2 | 3 | Maps provide a data structure that allow for the storage and management of key/value pair data. 4 | 5 | ## Notes 6 | 7 | * Maps provide a way to store and retrieve key/value pairs. 8 | * The map key must be a value that can be used in an assignment statement. 9 | * Iterating over a map is always random. 10 | 11 | ## Links 12 | 13 | http://blog.golang.org/go-maps-in-action 14 | 15 | http://www.goinggo.net/2013/12/macro-view-of-map-internals-in-go.html 16 | 17 | ## Code Review 18 | 19 | [Declare, initialize and iterate](example1/example1.go) ([Go Playground](http://play.golang.org/p/ZgPw0LU_Nv)) 20 | 21 | [Map literal initialization](example2/example2.go) ([Go Playground](http://play.golang.org/p/hC1o26x7Q5)) 22 | 23 | [Map key restrictions](example3/example3.go) ([Go Playground](http://play.golang.org/p/1JmxvWLAET)) 24 | 25 | ## Advanced Code Review 26 | 27 | [Composing maps of maps](advanced/example1/example1.go) ([Go Playground](http://play.golang.org/p/pQsoB02pDl)) 28 | 29 | ## Exercises 30 | 31 | ### Exercise 1 32 | 33 | Declare and make a map of integer values with a string as the key. Populate the map with five values and iterate over the map to display the key/value pairs. 34 | 35 | [Template](exercises/template1/template1.go) ([Go Playground](http://play.golang.org/p/-JBSUoux-v)) | 36 | [Answer](exercises/exercise1/exercise1.go) ([Go Playground](http://play.golang.org/p/8K-IZgJFSg)) 37 | ___ 38 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /11-standard_library/03-writers_readers/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/KtrDN1BStt 5 | 6 | // Download any document from the web and display the content in 7 | // the terminal and write it to a file at the same time. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "io" 13 | "net/http" 14 | "os" 15 | ) 16 | 17 | // main is the entry point for the application. 18 | func main() { 19 | // Retrieve the RSS feed for the blog. 20 | resp, err := http.Get("http://www.goinggo.net/feeds/posts/default") 21 | if err != nil { 22 | fmt.Println(err) 23 | return 24 | } 25 | 26 | // Arrange for the response Body to be Closed using defer. 27 | defer resp.Body.Close() 28 | 29 | // A slice of io.Writers we will write the file to. 30 | var writers []io.Writer 31 | 32 | // Send the document to stdout. 33 | writers = append(writers, os.Stdout) 34 | 35 | // Send the document to a file. 36 | file, err := os.Create("goinggo.rss") 37 | if err != nil { 38 | fmt.Println(err) 39 | return 40 | } 41 | defer file.Close() 42 | 43 | // Send the document to the file. 44 | writers = append(writers, file) 45 | 46 | // MultiWriter(io.Writer...) returns a single writer which multiplexes its 47 | // writes across all of the writers we pass in. 48 | dest := io.MultiWriter(writers...) 49 | 50 | // Write to dest the same way as before, copying from the Body. 51 | _, err = io.Copy(dest, resp.Body) 52 | if err != nil { 53 | fmt.Println(err) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /08-concurrency_channels/01-goroutines/example3/example3.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/cqsHoPD30n 5 | 6 | // Sample program to show how to create goroutines and 7 | // how the goroutine scheduler behaves with two contexts. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "runtime" 13 | "sync" 14 | ) 15 | 16 | // main is the entry point for all Go programs. 17 | func main() { 18 | // wg is used to wait for the program to finish. 19 | // Add a count of two, one for each goroutine. 20 | var wg sync.WaitGroup 21 | wg.Add(2) 22 | 23 | // Allocate two contexts for the scheduler to use. 24 | runtime.GOMAXPROCS(2) 25 | 26 | fmt.Println("Start Goroutines") 27 | 28 | // Declare an anonymous function and create a goroutine. 29 | go func() { 30 | // Display the alphabet three times. 31 | for count := 0; count < 3; count++ { 32 | for rune := 'a'; rune < 'a'+26; rune++ { 33 | fmt.Printf("%c ", rune) 34 | } 35 | } 36 | 37 | // Tell main we are done. 38 | wg.Done() 39 | }() 40 | 41 | // Declare an anonymous function and create a goroutine. 42 | go func() { 43 | // Display the alphabet three times. 44 | for count := 0; count < 3; count++ { 45 | for rune := 'A'; rune < 'A'+26; rune++ { 46 | fmt.Printf("%c ", rune) 47 | } 48 | } 49 | 50 | // Tell main we are done. 51 | wg.Done() 52 | }() 53 | 54 | // Wait for the goroutines to finish. 55 | fmt.Println("Waiting To Finish") 56 | wg.Wait() 57 | 58 | fmt.Println("\nTerminating Program") 59 | } 60 | -------------------------------------------------------------------------------- /11-standard_library/01-logging/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/1-l_QmaSvy 5 | 6 | // Setup a new program to use the log package. Set the Prefix to your first name and on each log line show 7 | // the date and long path for the code file. 8 | package main 9 | 10 | import ( 11 | "log" 12 | "os" 13 | ) 14 | 15 | // init is called before main. 16 | func init() { 17 | // Change the output device from the default stderr to stdout. 18 | log.SetOutput(os.Stdout) 19 | 20 | // Set the prefix string for each log line. 21 | log.SetPrefix("BILL: ") 22 | 23 | // Set the extra log info. 24 | setFlags() 25 | } 26 | 27 | // setFlags adds extra information on each log line. 28 | func setFlags() { 29 | /* 30 | Ldate // the date: 2009/01/23 31 | Ltime // the time: 01:23:23 32 | Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. 33 | Llongfile // full file name and line number: /a/b/c/d.go:23 34 | Lshortfile // final file name element and line number: d.go:23. overrides Llongfile 35 | LstdFlags // Ldate | Ltime // initial values for the standard logger 36 | */ 37 | 38 | log.SetFlags(log.Ldate | log.Llongfile) 39 | } 40 | 41 | // main is the entry point for the application. 42 | func main() { 43 | log.Println("main function started") 44 | 45 | names := []string{"Henry", "Lisa", "Bill", "Matt"} 46 | log.Printf("These are named %+v\n", names) 47 | 48 | log.Fatalln("Terminate Program") 49 | } 50 | -------------------------------------------------------------------------------- /08-concurrency_channels/02-race_conditions/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/wFTNvVoBpz 5 | 6 | // Answer for exercise 1 of Race Conditions. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "math/rand" 12 | "sync" 13 | "time" 14 | ) 15 | 16 | // numbers maintains a set of random numbers. 17 | var numbers []int 18 | 19 | // wg is used to wait for the program to finish. 20 | var wg sync.WaitGroup 21 | 22 | // mutex will help protect the slice. 23 | var mutex sync.Mutex 24 | 25 | // init is called prior to main. 26 | func init() { 27 | rand.Seed(time.Now().UnixNano()) 28 | } 29 | 30 | // main is the entry point for all Go programs. 31 | func main() { 32 | // Add a count for each goroutine we will create. 33 | wg.Add(3) 34 | 35 | // Create three goroutines to generate random numbers. 36 | go random(10) 37 | go random(10) 38 | go random(10) 39 | 40 | // Wait for all the goroutines to finish. 41 | wg.Wait() 42 | 43 | // Display the set of random numbers. 44 | for i, number := range numbers { 45 | fmt.Println(i, number) 46 | } 47 | } 48 | 49 | // random generates random numbers and stores them into a slice. 50 | func random(amount int) { 51 | // Generate as many random numbers as specified. 52 | for i := 0; i < amount; i++ { 53 | n := rand.Intn(100) 54 | 55 | // Protect this append to keep access safe. 56 | mutex.Lock() 57 | { 58 | numbers = append(numbers, n) 59 | } 60 | mutex.Unlock() 61 | } 62 | 63 | // Tell main we are done. 64 | wg.Done() 65 | } 66 | -------------------------------------------------------------------------------- /08-concurrency_channels/01-goroutines/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/LI0TEB6PMf 5 | 6 | // Sample program to show how to create goroutines and 7 | // how the scheduler behaves. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "sync" 13 | ) 14 | 15 | // wg is used to wait for the program to finish. 16 | var wg sync.WaitGroup 17 | 18 | // main is the entry point for all Go programs. 19 | func main() { 20 | // Add a count of two, one for each goroutine. 21 | wg.Add(2) 22 | 23 | fmt.Println("Start Goroutines") 24 | 25 | // Create a goroutine from the lowercase function. 26 | go lowercase() 27 | 28 | // Create a goroutine from the uppercase function. 29 | go uppercase() 30 | 31 | // Wait for the goroutines to finish. 32 | fmt.Println("Waiting To Finish") 33 | wg.Wait() 34 | 35 | fmt.Println("\nTerminating Program") 36 | } 37 | 38 | // lowercase displays the set of lowercase letters three times. 39 | func lowercase() { 40 | // Display the alphabet three times 41 | for count := 0; count < 3; count++ { 42 | for rune := 'a'; rune < 'a'+26; rune++ { 43 | fmt.Printf("%c ", rune) 44 | } 45 | } 46 | 47 | // Tell main we are done. 48 | wg.Done() 49 | } 50 | 51 | // uppercase displays the set of uppercase letters three times. 52 | func uppercase() { 53 | // Display the alphabet three times 54 | for count := 0; count < 3; count++ { 55 | for rune := 'A'; rune < 'A'+26; rune++ { 56 | fmt.Printf("%c ", rune) 57 | } 58 | } 59 | 60 | // Tell main we are done. 61 | wg.Done() 62 | } 63 | -------------------------------------------------------------------------------- /09-concurrency_patterns/task/main/main.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // This sample program demonstrates how to use the work package 5 | // to use a pool of goroutines to get work done. 6 | package main 7 | 8 | import ( 9 | "log" 10 | "sync" 11 | "time" 12 | 13 | "github.com/gobridge/gotraining/09-concurrency_patterns/task" 14 | ) 15 | 16 | // names provides a set of names to display. 17 | var names = []string{ 18 | "steve", 19 | "bob", 20 | "mary", 21 | "therese", 22 | "jason", 23 | } 24 | 25 | // namePrinter provides special support for printing names. 26 | type namePrinter struct { 27 | name string 28 | } 29 | 30 | // Work implements the Worker interface. 31 | func (m namePrinter) Work() { 32 | log.Println(m.name) 33 | time.Sleep(3 * time.Second) 34 | } 35 | 36 | // main is the entry point for all Go programs. 37 | func main() { 38 | // Create a task pool with 4 goroutines. 39 | t := task.New(10) 40 | 41 | var wg sync.WaitGroup 42 | wg.Add(10 * len(names)) 43 | 44 | for i := 0; i < 10; i++ { 45 | // Iterate over the slice of names. 46 | for _, name := range names { 47 | // Create a namePrinter and provide the 48 | // specific name. 49 | np := namePrinter{ 50 | name: name, 51 | } 52 | 53 | go func() { 54 | // Submit the task to be worked on. When Do 55 | // returns, we know it is being handled. 56 | t.Do(np) 57 | wg.Done() 58 | }() 59 | } 60 | } 61 | 62 | wg.Wait() 63 | 64 | // Shutdown the task pool and wait for all existing work 65 | // to be completed. 66 | t.Shutdown() 67 | } 68 | -------------------------------------------------------------------------------- /02-array_slices_maps/02-slices/advanced/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/dJk2eycWhH 5 | 6 | // Sample program to show how to use a third index slice. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | // main is the entry point for the application. 14 | func main() { 15 | // Create a slice of strings with different types of fruit. 16 | slice := []string{"Apple", "Orange", "Banana", "Grape", "Plum"} 17 | inspectSlice(slice) 18 | 19 | // Take a slice of slice. We want just index 2 20 | // takeOne[0] = "Banana" 21 | // Length: 3 - 2 22 | // Capacity: 5 - 2 23 | takeOne := slice[2:3] 24 | inspectSlice(takeOne) 25 | 26 | // For slice[ i : j : k ] the 27 | // Length: j - i 28 | // Capacity: k - i 29 | 30 | // Take a slice of just index 2 with a length and capacity of 1 31 | // takeOneCapOne[0] = "Banana" 32 | // Length: 3 - 2 33 | // Capacity: 3 - 2 34 | takeOneCapOne := slice[2:3:3] // Use the third index position to 35 | inspectSlice(takeOneCapOne) // set the capacity to 1. 36 | 37 | // Append a new element which will create a new 38 | // underlying array to increase capacity. 39 | takeOneCapOne = append(takeOneCapOne, "Kiwi") 40 | inspectSlice(takeOneCapOne) 41 | } 42 | 43 | // inspectSlice exposes the slice header for review. 44 | func inspectSlice(slice []string) { 45 | fmt.Printf("Length[%d] Capacity[%d]\n", len(slice), cap(slice)) 46 | for index, value := range slice { 47 | fmt.Printf("[%d] %p %s\n", 48 | index, 49 | &slice[index], 50 | value) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /07-error_handling/exercises/template2/template2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/x6UimVQMMQ 5 | 6 | // Create a custom error type called appError that contains three fields, Err error, 7 | // Message string and Code int. Implement the error interface providing your own message 8 | // using these three fields. Write a function called checkFlag that accepts a bool value. 9 | // If the value is false, return a pointer of your custom error type initialized as you like. 10 | // If the value is true, return a default error. Write a main function to call the 11 | // checkFlag function and check the error for the concrete type. 12 | package main 13 | 14 | // Add imports. 15 | 16 | // Declare a struct type named appError with three fields, Err of type error, 17 | // Message of type string and Code of type int. 18 | 19 | // Declare a method for the appError struct type that implements the 20 | // error interface. 21 | 22 | // Declare a function named checkFlag that accepts a boolean value and 23 | // returns an error interface value. 24 | func checkFlag( /* parameter */ ) /* return arg */ { 25 | // If the parameter is false return an appError. 26 | 27 | // Return a default error. 28 | } 29 | 30 | // main is the entry point for the application. 31 | func main() { 32 | // Call the checkFlag function to simulate an error of the 33 | // concrete type. 34 | 35 | // Check the concrete type and handle appropriately. 36 | switch e := err.(type) { 37 | // Apply the case for the default error type. 38 | 39 | // Apply the default case. 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /10-testing/03-caching/caching.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/GQQXh3cf15 5 | 6 | // package caching provides code to show why CPU caches matter and the way 7 | // the hardware caches memory affects performance. 8 | package caching 9 | 10 | import "fmt" 11 | 12 | const cols = 64 13 | 14 | // Set the size of each row to be 4k. 15 | //const rows = 4 * 1024 16 | 17 | // Set the size of each row to be 64k. 18 | const rows = 64 * 1024 19 | 20 | // matrix represents a set of columns that each exist on 21 | // their own cache line. 22 | var matrix [cols][rows]byte 23 | 24 | // init sets ~13% of the matrix to 0XFF. 25 | func init() { 26 | var ctr int 27 | for col := 0; col < cols; col++ { 28 | for row := 0; row < rows; row++ { 29 | if row%8 == 0 { 30 | matrix[col][row] = 0xFF 31 | ctr++ 32 | } 33 | } 34 | } 35 | 36 | fmt.Println(ctr, "Elements set out of", cols*rows) 37 | } 38 | 39 | // rowTraverse traverses the matrix linearly by each column for each row. 40 | func rowTraverse() int { 41 | var ctr int 42 | 43 | for col := 0; col < cols; col++ { 44 | for row := 0; row < rows; row++ { 45 | if matrix[col][row] == 0xFF { 46 | ctr++ 47 | } 48 | } 49 | } 50 | 51 | return ctr 52 | } 53 | 54 | // colTraverse traverses the matrix linearly by each row for each column. 55 | func colTraverse() int { 56 | var ctr int 57 | 58 | for row := 0; row < rows; row++ { 59 | for col := 0; col < cols; col++ { 60 | if matrix[col][row] == 0xFF { 61 | ctr++ 62 | } 63 | } 64 | } 65 | 66 | return ctr 67 | } 68 | -------------------------------------------------------------------------------- /08-concurrency_channels/02-race_conditions/example3/example3.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/qifiyxrX1R 5 | 6 | // go build -race 7 | 8 | // Sample program to show how to use the atomic package functions 9 | // Store and Load to provide safe access to numeric types. 10 | package main 11 | 12 | import ( 13 | "fmt" 14 | "sync" 15 | "sync/atomic" 16 | "time" 17 | ) 18 | 19 | // shutdown is a flag to alert running goroutines to shutdown. 20 | var shutdown int64 21 | 22 | // wg is used to wait for the program to finish. 23 | var wg sync.WaitGroup 24 | 25 | // main is the entry point for all Go programs. 26 | func main() { 27 | // Add a count of two, one for each goroutine. 28 | wg.Add(2) 29 | 30 | // Create two goroutines. 31 | go doWork("A") 32 | go doWork("B") 33 | 34 | // Give the goroutines time to run so we can see 35 | // the shutdown flag work. 36 | time.Sleep(time.Second) 37 | 38 | // Safely flag it is time to shutdown. 39 | fmt.Println("Shutdown Now") 40 | atomic.StoreInt64(&shutdown, 1) 41 | 42 | // Wait for the goroutines to finish. 43 | wg.Wait() 44 | } 45 | 46 | // doWork simulates a goroutine performing work and 47 | // checking the Shutdown flag to terminate early. 48 | func doWork(name string) { 49 | for { 50 | fmt.Printf("Doing %s Work\n", name) 51 | time.Sleep(250 * time.Millisecond) 52 | 53 | // Do we need to shutdown. 54 | if atomic.LoadInt64(&shutdown) == 1 { 55 | fmt.Printf("Shutting %s Down\n", name) 56 | break 57 | } 58 | } 59 | 60 | // Tell main we are done. 61 | wg.Done() 62 | } 63 | -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/02-interfaces/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/Lo1ucf1e9d 5 | 6 | // Sample program to show how polymorphic behavior with interfaces. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | ) 12 | 13 | // notifier is an interface that defines notification 14 | // type behavior. 15 | type notifier interface { 16 | notify() 17 | } 18 | 19 | // user defines a user in the program. 20 | type user struct { 21 | name string 22 | email string 23 | } 24 | 25 | // notify implements the notifier interface with a pointer receiver. 26 | func (u *user) notify() { 27 | fmt.Printf("Sending user Email To %s<%s>\n", 28 | u.name, 29 | u.email) 30 | } 31 | 32 | // admin defines a admin in the program. 33 | type admin struct { 34 | name string 35 | email string 36 | } 37 | 38 | // notify implements the notifier interface with a pointer receiver. 39 | func (a *admin) notify() { 40 | fmt.Printf("Sending admin Email To %s<%s>\n", 41 | a.name, 42 | a.email) 43 | } 44 | 45 | // main is the entry point for the application. 46 | func main() { 47 | // Create two values one of type user and one of type admin. 48 | bill := user{"Bill", "bill@email.com"} 49 | jill := admin{"Jill", "jill@email.com"} 50 | 51 | // Pass a pointer of the values to support the interface. 52 | sendNotification(&bill) 53 | sendNotification(&jill) 54 | } 55 | 56 | // sendNotification accepts values that implement the notifier 57 | // interface and sends notifications. 58 | func sendNotification(n notifier) { 59 | n.notify() 60 | } 61 | -------------------------------------------------------------------------------- /01-language_syntax/04-constants/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/fkQx0inUJ3 5 | 6 | // Sample program to show how to declare constants and their 7 | // implementation in Go. 8 | package main 9 | 10 | // main is the entry point for the application. 11 | func main() { 12 | // Constants live within the compiler. 13 | // They have a parallel type system. 14 | // Compiler can perform implicit conversions of untyped constants. 15 | 16 | // Untyped Constants. 17 | const ui = 12345 // kind: integer 18 | const uf = 3.141592 // kind: floating-point 19 | 20 | // Typed Constants still use the constant type system but their precision 21 | // is restricted. 22 | const ti int = 12345 // type: int64 23 | const tf float64 = 3.141592 // type: float64 24 | 25 | // ./constants.go:14: constant 1000 overflows uint8 26 | // const myUint8 uint8 = 1000 27 | 28 | // Constant arithmetic supports different kinds. 29 | // Kind Promotion is used to determine kind in these scenarios. 30 | // Variable answer will be implicitly converted to type floating point. 31 | var answer = 3 * 0.333 // KindInt(3) * KindFloat(0.333) 32 | 33 | // Variable third will be of kind floating point. 34 | const third = 1 / 3.0 // KindInt(1) / KindFloat(3.0) 35 | 36 | // Variable zero will be of kind integer. 37 | const zero = 1 / 3 // KindInt(1) / KindInt(3) 38 | 39 | // This is an example of constant arithmetic between typed and 40 | // untyped constants. Must have like types to perform math. 41 | const one int8 = 1 42 | const two = 2 * one // KindInt(2) * int8(1) 43 | } 44 | -------------------------------------------------------------------------------- /08-concurrency_channels/03-channels/exercises/template2/template2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/vc6c1-M2EB 5 | 6 | // Write a problem that uses a buffered channel to maintain a buffer 7 | // of four strings. In main, send the strings 'A', 'B', 'C' and 'D' 8 | // into the channel. Then create 20 goroutines that receive a string 9 | // from the channel, display the value and then send the string back 10 | // into the channel. Once each goroutine is done performing that task, 11 | // allow the goroutine to terminate. 12 | package main 13 | 14 | // Add Imports. 15 | 16 | // Declare a constant and set the value for the number of goroutines. 17 | 18 | // Declare a constant and set the value for the number of buffers. 19 | 20 | // Declare a wait group. 21 | 22 | // Declare a buffered channel of type string and initialize it based on 23 | // the constant you declared above. 24 | 25 | // Declare a function for the goroutine that will process work 26 | // from the buffered channel. 27 | func worker(worker int) { 28 | // Receive a string from the channel. 29 | 30 | // Display the string. 31 | 32 | // Send the string back into the channel. 33 | 34 | // Tell main this goroutine is done. 35 | } 36 | 37 | // main is the entry point for all Go programs. 38 | func main() { 39 | // Increment the wait group for the number of 40 | // goroutines based on the value of the constant. 41 | 42 | // Create the number of goroutines based on the 43 | // value of the constant. 44 | 45 | // Add strings in the buffered channel. 46 | 47 | // Wait for all the work to get done. 48 | } 49 | -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/01-methods/advanced/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/MNI1jR8Ets 5 | 6 | // Sample program to show how to declare function variables. 7 | package main 8 | 9 | import "fmt" 10 | 11 | // data is a struct to bind methods to. 12 | type data struct { 13 | name string 14 | age int 15 | } 16 | 17 | // displayName provides a pretty print view of the name. 18 | func (d data) displayName() { 19 | fmt.Println("My Name Is: ", d.name) 20 | } 21 | 22 | // setAge sets the age and displays the value. 23 | func (d *data) setAge(age int) { 24 | d.age = age 25 | fmt.Println("Set Age: ", d.age) 26 | } 27 | 28 | // main is the entry point for the application. 29 | func main() { 30 | // Declare a variable of type data. 31 | d := data{ 32 | name: "Bill", 33 | } 34 | 35 | // Declare a function variable for the method 36 | // bound to the d variable. 37 | f1 := d.displayName 38 | 39 | // Call the method via the variable. 40 | f1() 41 | 42 | // Declare a function variable for the function 43 | // bound to the package. 44 | f2 := data.displayName 45 | 46 | // Call the function passing the receiver. 47 | f2(d) 48 | 49 | // Declare a function variable for the method 50 | // bound to the d variable. 51 | f3 := d.setAge 52 | 53 | // Call the method via the variable passing the parameter. 54 | f3(45) 55 | 56 | // Declare a function variable for the function 57 | // bound to the package. The receiver is a pointer. 58 | f4 := (*data).setAge 59 | 60 | // Call the function passing the receiver and the parameter. 61 | f4(&d, 55) 62 | } 63 | -------------------------------------------------------------------------------- /01-language_syntax/01-variables/readme.md: -------------------------------------------------------------------------------- 1 | ## Variables - Language Syntax 2 | 3 | Variables are at the heart of the language and provide the ability to read from and write to memory. In Go, access to memory is type safe. This means the compiler takes type seriously and will not allow us to use variables outside the scope of how they are declared. 4 | 5 | ## Notes 6 | 7 | * When variables are being declared to their zero value, use the keyword var. 8 | * When variables are being declared and initialized, use the short variable declaration operator. 9 | * Escape analysis is used to determine when a value escapes to the heap. 10 | 11 | ## Links 12 | 13 | [Built-In Types](http://golang.org/ref/spec#Boolean_types) 14 | 15 | https://golang.org/doc/effective_go.html#variables 16 | 17 | http://www.goinggo.net/2013/08/gustavos-ieee-754-brain-teaser.html 18 | 19 | ## Code Review 20 | 21 | [Declare and initialize variables](example1/example1.go) ([Go Playground](http://play.golang.org/p/6w6hBNE75a)) 22 | 23 | ## Exercises 24 | 25 | ### Exercise 1 26 | 27 | **Part A:** Declare three variables that are initialized to their zero value and three declared with a literal value. Declare variables of type string, int and bool. Display the values of those variables. 28 | 29 | **Part B:** Declare a new variable of type float32 and initialize the variable by converting the literal value of Pi (3.14). 30 | 31 | [Template](exercises/template1/template1.go) ([Go Playground](https://play.golang.org/p/1xUWjHMB3I)) | 32 | [Answer](exercises/exercise1/exercise1.go) ([Go Playground](https://play.golang.org/p/d2M0Q3mRnd)) 33 | ___ 34 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 35 | -------------------------------------------------------------------------------- /02-array_slices_maps/02-slices/example3/example3.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/nZnkHsGj_P 5 | 6 | // Sample program to show how to takes slices of slices to create different 7 | // views of and make changes to the underlying array. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Create a slice with a length of 5 elements and a capacity of 8. 17 | slice1 := make([]string, 5, 8) 18 | slice1[0] = "Apple" 19 | slice1[1] = "Orange" 20 | slice1[2] = "Banana" 21 | slice1[3] = "Grape" 22 | slice1[4] = "Plum" 23 | 24 | inspectSlice(slice1) 25 | 26 | // For slice[i:j] with an underlying array of capacity k 27 | // Final Length: j - i 28 | // Final Capacity: k - i 29 | 30 | // Take a slice of slice1. We want just indexes 2 and 3. 31 | // slice2[0] = "Banana" 32 | // slice2[1] = "Grape" 33 | // Length: 4 - 2 34 | // Capacity: 8 - 2 35 | 36 | // Parameters are [starting_index : (starting_index + length) 37 | slice2 := slice1[2:4] 38 | inspectSlice(slice2) 39 | 40 | fmt.Println("*************************") 41 | 42 | // Change the value of the index 0 of slice3. 43 | slice2[0] = "CHANGED" 44 | 45 | // Display the change across all existing slices. 46 | inspectSlice(slice1) 47 | inspectSlice(slice2) 48 | } 49 | 50 | // inspectSlice exposes the slice header for review. 51 | func inspectSlice(slice []string) { 52 | fmt.Printf("Length[%d] Capacity[%d]\n", len(slice), cap(slice)) 53 | for i, v := range slice { 54 | fmt.Printf("[%d] %p %s\n", 55 | i, 56 | &slice[i], 57 | v) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /11-standard_library/02-encoding/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/Huf8jEDUJO 5 | 6 | // Create a file with an array of JSON documents that contain a user name and email address. Declare a struct 7 | // type that maps to the JSON document. Using the json package, read the file and create a slice of this struct 8 | // type. Display the slice. 9 | // 10 | // Marshal the slice into pretty print strings and display each element. 11 | package main 12 | 13 | import ( 14 | "encoding/json" 15 | "fmt" 16 | "os" 17 | ) 18 | 19 | // user is the data we need to unmarshal and marshal. 20 | type user struct { 21 | Name string `json:"name"` 22 | Email string `json:"email"` 23 | } 24 | 25 | // main is the entry point for the application. 26 | func main() { 27 | // Open the file. 28 | file, err := os.Open("data.json") 29 | if err != nil { 30 | fmt.Println("Open File", err) 31 | return 32 | } 33 | 34 | // Schedule the file to be closed once 35 | // the function returns. 36 | defer file.Close() 37 | 38 | // Decode the file into this slice. 39 | var users []user 40 | err = json.NewDecoder(file).Decode(&users) 41 | if err != nil { 42 | fmt.Println("Decode File", err) 43 | return 44 | } 45 | 46 | // Iterate over the slice and display 47 | // each user. 48 | for _, u := range users { 49 | fmt.Printf("%+v\n", u) 50 | } 51 | 52 | uData, err := json.MarshalIndent(&users, "", " ") 53 | if err != nil { 54 | fmt.Println("MarshalIndent", err) 55 | return 56 | } 57 | 58 | // Convert the byte slice to a string and display. 59 | fmt.Println(string(uData)) 60 | } 61 | -------------------------------------------------------------------------------- /08-concurrency_channels/01-goroutines/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/mB4QslSNoA 5 | 6 | // Create a program that declares two anonymous functions. Once that counts up to 7 | // 100 from 0 and one that counts down to 0 from 100. Display each number with an 8 | // unique identifier for each goroutine. Then create goroutines from these functions 9 | // and don't let main return until the goroutines complete. 10 | // 11 | // Run the program in parallel. 12 | package main 13 | 14 | import ( 15 | "fmt" 16 | "sync" 17 | ) 18 | 19 | // main is the entry point for all Go programs. 20 | func main() { 21 | // wg is used to wait for the program to finish. 22 | // Add a count of two, one for each goroutine. 23 | var wg sync.WaitGroup 24 | wg.Add(2) 25 | 26 | // Allocate two contexts for the scheduler to use. 27 | // runtime.GOMAXPROCS(2) 28 | 29 | fmt.Println("Start Goroutines") 30 | 31 | // Declare an anonymous function and create a goroutine. 32 | go func() { 33 | // Count down from 100 to 0. 34 | for count := 100; count >= 0; count-- { 35 | fmt.Printf("[A:%d]\n", count) 36 | } 37 | 38 | // Tell main we are done. 39 | wg.Done() 40 | }() 41 | 42 | // Declare an anonymous function and create a goroutine. 43 | go func() { 44 | // Count up from 0 to 100. 45 | for count := 0; count < 100; count++ { 46 | fmt.Printf("[B:%d]\n", count) 47 | } 48 | 49 | // Tell main we are done. 50 | wg.Done() 51 | }() 52 | 53 | // Wait for the goroutines to finish. 54 | fmt.Println("Waiting To Finish") 55 | wg.Wait() 56 | 57 | fmt.Println("\nTerminating Program") 58 | } 59 | -------------------------------------------------------------------------------- /08-concurrency_channels/03-channels/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/G7O-DnJrEA 5 | 6 | // Write a program where two goroutines pass an integer back and forth 7 | // ten times. Display when each goroutine receives the integer. Increment 8 | // the integer with each pass. Once the integer equals ten, terminate 9 | // the program cleanly. 10 | package main 11 | 12 | // Add imports. 13 | 14 | // Declare a wait group variable. 15 | 16 | // Declare a function for the goroutine. Pass in a name for the 17 | // routine and a channel of type int used to share the value back and forth. 18 | func goroutine( /* parameters */ ) { 19 | for { 20 | // Receive on the channel, waiting for the integer. 21 | 22 | // Check if the channel is closed. 23 | { 24 | // Call done on the waitgroup. 25 | // Display the goroutine is finished and return. 26 | } 27 | 28 | // Display the integer value received. 29 | 30 | // Check is the value from the channel is 10. 31 | { 32 | // Close the channel. 33 | // Call done on the waitgroup. 34 | // Display the goroutine is finished and return. 35 | } 36 | 37 | // Increment the value by one and send in back through 38 | // the channel. 39 | } 40 | } 41 | 42 | // main is the entry point for all Go programs. 43 | func main() { 44 | // Declare and initialize an unbuffered channel 45 | // of type int. 46 | 47 | // Increment the wait group for each goroutine 48 | // to be created. 49 | 50 | // Create the two goroutines. 51 | 52 | // Send the initial integer value into the channel. 53 | 54 | // Wait for all the goroutines to finish. 55 | } 56 | -------------------------------------------------------------------------------- /12-reflection/readme.md: -------------------------------------------------------------------------------- 1 | ## Reflection 2 | 3 | Reflection is the ability to inspect a value to derive type or other meta-data. Reflection can give our program incredible flexibility to work with data of different types or create values on the fly. Reflection is critical for the encoding and decoding of data. 4 | 5 | ## Notes 6 | 7 | * The reflection package allows us to inspect our types. 8 | * We can add "tags" to our struct fields to store and use meta-data. 9 | * Encoding package leverages reflection and we can as well. 10 | 11 | ## Links 12 | 13 | http://blog.golang.org/laws-of-reflection 14 | 15 | ## Code Review 16 | 17 | [Empty Interface](example1/example1.go) ([Go Playground](http://play.golang.org/p/OSeD9F_P46)) 18 | 19 | [Reflect struct types with tags](example2/example2.go) ([Go Playground](http://play.golang.org/p/y0WyYezH05)) 20 | 21 | ## Advanced Code Review 22 | 23 | [Decoding function for integers](example3/example3.go) ([Go Playground](http://play.golang.org/p/bWQ6hiVECQ)) 24 | 25 | ## Exercises 26 | 27 | ### Exercise 1 28 | Declare a struct type that represents a request for a customer invoice. Include a CustomerID and InvoiceID field. Define tags that can be used to validate the request. Define tags that specify both the length and range for the ID to be valid. Declare a function named validate that accepts values of any type and processes the tags. Display the results of the validation. 29 | 30 | [Template](exercises/template1/template1.go) ([Go Playground](http://play.golang.org/p/lgMQHWpZul)) | 31 | [Answer](exercises/exercise1/exercise1.go) ([Go Playground](http://play.golang.org/p/xy-wyPrsjz)) 32 | ___ 33 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 34 | -------------------------------------------------------------------------------- /01-language_syntax/02-struct_types/readme.md: -------------------------------------------------------------------------------- 1 | ## Struct Types - Language Syntax 2 | 3 | Struct types are a way of creating complex types that group fields of data together. They are a great way of organizing and sharing the different aspects of the data your program consumes. 4 | 5 | ## Notes 6 | 7 | * We can use the struct literal form to initialize a value from a struct type. 8 | * The dot (.) operator allows us to access individual field values. 9 | * We can create anonymous structs. 10 | 11 | ## Links 12 | 13 | http://www.goinggo.net/2013/07/understanding-type-in-go.html 14 | 15 | http://www.goinggo.net/2013/07/object-oriented-programming-in-go.html 16 | 17 | ## Code Review 18 | 19 | [Declare, create and initialize struct types](example1/example1.go) ([Go Playground](http://play.golang.org/p/-oeDmu2et8)) 20 | 21 | [Anonymous struct types](example2/example2.go) ([Go Playground](http://play.golang.org/p/_xxuE1Ep6U)) 22 | 23 | ## Advanced Code Review 24 | 25 | [Struct type alignments](advanced/example1/example1.go) ([Go Playground](http://play.golang.org/p/1CL1ACDipG)) 26 | 27 | ## Exercises 28 | 29 | ### Exercise 1 30 | 31 | **Part A:** Declare a struct type to maintain information about a user (name, email and age). Create a value of this type, initialize with values and display each field. 32 | 33 | **Part B:** Declare and initialize an anonymous struct type with the same three fields. Display the value. 34 | 35 | [Template](exercises/template1/template1.go) ([Go Playground](http://play.golang.org/p/ItPe2EEy9X)) | 36 | [Answer](exercises/exercise1/exercise1.go) ([Go Playground](http://play.golang.org/p/tnn-8hJPUd)) 37 | ___ 38 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 39 | -------------------------------------------------------------------------------- /06-composition/readme.md: -------------------------------------------------------------------------------- 1 | ## Composition 2 | 3 | Composition goes beyond the mechanics of type embedding. It's a design pattern we can leverage in Go to build larger programs from smaller parts. These smaller parts come from the declaration and implementation of types that have a single focus. Programs that are architected with composition in mind have a better chance to grow and adapt to changes. 4 | 5 | ## Notes 6 | 7 | * Declare types and behavior with composition in mind. 8 | * Composition is like building software with lego blocks. 9 | * This is much more than the mechanics of type embedding. 10 | 11 | ## Links 12 | 13 | http://golang.org/doc/effective_go.html#embedding 14 | 15 | ## Code Review 16 | 17 | [Composition I](example1/example1.go) ([Go Playground](http://play.golang.org/p/W5ya6_LAU6)) 18 | 19 | [Composition II](example2/example2.go) ([Go Playground](http://play.golang.org/p/xsDJhCYOBA)) 20 | 21 | ## Exercises 22 | 23 | ### Exercise 1 24 | 25 | **Part A** Follow the guided comments to: 26 | 27 | **Part B** Declare a sysadmin type that implements the administrator interface. 28 | 29 | **Part C** Declare a programmer type that implements the developer interface. 30 | 31 | **Part D** Declare a company type that embeds both an administrator and a developer. 32 | 33 | **Part E** Create a sysadmin, programmers, and a company which are available for hire, and use them to complete some predefined tasks. 34 | 35 | [Template](exercises/template1/template1.go) ([Go Playground](http://play.golang.org/p/b8ww3jd2Xs)) | 36 | [Answer](exercises/exercise1/exercise1.go) ([Go Playground](http://play.golang.org/p/8t5ns3cqNp)) 37 | ___ 38 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 39 | -------------------------------------------------------------------------------- /08-concurrency_channels/03-channels/exercises/exercise1/exercise1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/v7fEyd86i3 5 | 6 | // Write a program where two goroutines pass an integer back and forth 7 | // ten times. Display when each goroutine receives the integer. Increment 8 | // the integer with each pass. Once the integer equals ten, terminate 9 | // the program cleanly. 10 | package main 11 | 12 | import ( 13 | "fmt" 14 | "sync" 15 | ) 16 | 17 | // wg is used to wait for the program to finish. 18 | var wg sync.WaitGroup 19 | 20 | // main is the entry point for all Go programs. 21 | func main() { 22 | // Create an unbuffered channel. 23 | share := make(chan int) 24 | 25 | // Add a count of two, one for each goroutine. 26 | wg.Add(2) 27 | 28 | // Launch two goroutines. 29 | go goroutine("Bill", share) 30 | go goroutine("Lisa", share) 31 | 32 | // Start the sharing. 33 | share <- 1 34 | 35 | // Wait for the program to finish. 36 | wg.Wait() 37 | } 38 | 39 | // goroutine simulates sharing a value. 40 | func goroutine(name string, share chan int) { 41 | for { 42 | // Wait for the ball to be hit back to us. 43 | value, ok := <-share 44 | if !ok { 45 | // If the channel was closed, shutdown. 46 | wg.Done() 47 | fmt.Printf("Goroutine %s Down\n", name) 48 | return 49 | } 50 | 51 | // Display the value. 52 | fmt.Printf("Goroutine %s Inc %d\n", name, value) 53 | 54 | // Terminate when the value is 10. 55 | if value == 10 { 56 | close(share) 57 | wg.Done() 58 | fmt.Printf("Goroutine %s Down\n", name) 59 | return 60 | } 61 | 62 | // Share the value. 63 | share <- (value + 1) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /05-using_pointers/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/H5HRoElN6q 5 | 6 | // Sample code to show how the standard library in general, 7 | // does not pass built-in type values with a pointer. 8 | 9 | // ******************************************************* 10 | 11 | // http://golang.org/src/os/env.go 12 | // 13 | // For the caller to use this function, they must pass a copy of their uint8 type 14 | // value into the function. This is the same for the return value. A copy of the 15 | // function’s bool type value is being returned back to the caller. 16 | func isShellSpecialVar(c uint8) bool { 17 | switch c { 18 | case '*', '#', '$', '@', '!', '?', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': 19 | return true 20 | } 21 | return false 22 | } 23 | 24 | // http://golang.org/src/os/env.go 25 | // 26 | // It is best to treat values of type string the same way you treat boolean 27 | // and numeric type values, as a primitive data value. 28 | func getShellName(s string) (string, int) { 29 | switch { 30 | case s[0] == '{': 31 | . . . 32 | return "", 1 // Bad syntax; just eat the brace. 33 | case isShellSpecialVar(s[0]): 34 | return s[0:1], 1 35 | } 36 | . . . 37 | return s[:i], i 38 | } 39 | 40 | // http://golang.org/src/strings/strings.go 41 | // 42 | // All of the functions in the strings package accept copies of the caller’s 43 | // string values and return copies of the string values they create. 44 | func Trim(s string, cutset string) string { 45 | if s == "" || cutset == "" { 46 | return s 47 | } 48 | return TrimFunc(s, makeCutsetFunc(cutset)) 49 | } -------------------------------------------------------------------------------- /08-concurrency_channels/03-channels/exercises/exercise2/exercise2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/K9gNyTRA0s 5 | 6 | // Write a problem that uses a buffered channel to maintain a buffer 7 | // of four strings. In main, send the strings 'A', 'B', 'C' and 'D' 8 | // into the channel. Then create 20 goroutines that receive a string 9 | // from the channel, display the value and then send the string back 10 | // into the channel. Once each goroutine is done performing that task, 11 | // allow the goroutine to terminate. 12 | package main 13 | 14 | import ( 15 | "fmt" 16 | "sync" 17 | ) 18 | 19 | const ( 20 | goroutines = 20 21 | capacity = 4 22 | ) 23 | 24 | // wg is used to wait for the program to finish. 25 | var wg sync.WaitGroup 26 | 27 | // resources is a buffered channel to manage strings. 28 | var resources = make(chan string, capacity) 29 | 30 | // main is the entry point for all Go programs. 31 | func main() { 32 | // Launch goroutines to handle the work. 33 | wg.Add(goroutines) 34 | for gr := 1; gr <= goroutines; gr++ { 35 | go worker(gr) 36 | } 37 | 38 | // Add the strings. 39 | for rune := 'A'; rune < 'A'+capacity; rune++ { 40 | resources <- string(rune) 41 | } 42 | 43 | // Wait for all the work to get done. 44 | wg.Wait() 45 | } 46 | 47 | // worker is launched as a goroutine to process work from 48 | // the buffered channel. 49 | func worker(worker int) { 50 | // Receive a string from the channel. 51 | value := <-resources 52 | 53 | // Display the value. 54 | fmt.Printf("Worker: %d : %s\n", worker, value) 55 | 56 | // Place the string back. 57 | resources <- value 58 | 59 | // Tell main we are done. 60 | wg.Done() 61 | } 62 | -------------------------------------------------------------------------------- /07-error_handling/exercises/template1/template1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/Rt3O-7ndtJ 5 | 6 | // Create two error variables, one called ErrInvalidValue and the other 7 | // called ErrAmountTooLarge. Provide the static message for each variable. 8 | // Then write a function called checkAmount that accepts a float64 type value 9 | // and returns an error value. Check the value for zero and if it is, return 10 | // the ErrInvalidValue. Check the value for greater than $1,000 and if it is, 11 | // return the ErrAmountTooLarge. Write a main function to call the checkAmount 12 | // function and check the return error value. Display a proper message to the screen. 13 | package main 14 | 15 | // Add imports. 16 | 17 | // Declare an error variable named ErrInvalidValue using the New 18 | // function from the errors package. 19 | 20 | // Declare an error variable named ErrAmountTooLarge using the New 21 | // function from the errors package. 22 | 23 | // Declare a function named checkAmount that accepts a value of 24 | // type float64 and returns an error interface value. 25 | func checkAmount( /* parameter */ ) /* return arg */ { 26 | // Is the parameter equal to zero. If so then return 27 | // the error variable. 28 | 29 | // Is the parameter greater than 1000. If so then return 30 | // the other error variable. 31 | 32 | // Return nil for the error value. 33 | } 34 | 35 | // main is the entry point for the application. 36 | func main() { 37 | // Call the checkAmount function and check the error. Then 38 | // use a switch/case to compare the error with each variable. 39 | // Add a default case. Return if there is an error. 40 | 41 | // Display everything is good. 42 | } 43 | -------------------------------------------------------------------------------- /03-methods_interfaces_embedding/01-methods/readme.md: -------------------------------------------------------------------------------- 1 | ## Methods - Methods, Interfaces and Embedding 2 | 3 | Methods are functions that are declared with a receiver which binds the method to a type. Then the method and can be used to operate on values or pointers of that type. 4 | 5 | ## Notes 6 | 7 | * Methods are functions that contain a receiver value. 8 | * Receivers bind a method to a type and can be value or pointers. 9 | * Methods are called against values and pointers, not packages. 10 | * Go support function and method variables. 11 | 12 | ## Links 13 | 14 | https://golang.org/doc/effective_go.html#methods 15 | 16 | http://www.goinggo.net/2014/05/methods-interfaces-and-embedded-types.html 17 | 18 | ## Code Review 19 | 20 | [Declare and receiver behavior](example1/example1.go) ([Go Playground](https://play.golang.org/p/AYsB78Dlxb)) 21 | 22 | [Named typed methods](example2/example2.go) ([Go Playground](https://play.golang.org/p/zHePe-yTUw)) 23 | 24 | ## Advanced Code Review 25 | 26 | [Function/Method variables](advanced/example1/example1.go) ([Go Playground](http://play.golang.org/p/MNI1jR8Ets)) 27 | 28 | ## Exercises 29 | 30 | ### Exercise 1 31 | 32 | Declare a struct that represents a baseball player. Include name, atBats and hits. Declare a method that calculates a players batting average. The formula is Hits / AtBats. Declare a slice of this type and initialize the slice with several players. Iterate over the slice displaying the players name and batting average. 33 | 34 | [Template](exercises/template1/template1.go) ([Go Playground](http://play.golang.org/p/Rj0QfwVPhX)) | 35 | [Answer](exercises/exercise1/exercise1.go) ([Go Playground](http://play.golang.org/p/C8Z_MiYKbc)) 36 | ___ 37 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). -------------------------------------------------------------------------------- /13-http/api/views/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Users Example 5 | 6 | 14 | 33 | 34 | 35 |

Current Users

36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 60 | 61 |
FirstLastEmailCompanyaddress
{{user.first_name}}{{user.last_name}}{{user.email}}{{user.company}} 50 | 51 | 52 | 57 | 58 |
53 | {{addr.line_one}}
54 | {{addr.line_two}}
55 | {{addr.city}}, {{addr.state}} {{addr.zipcode}}
56 |
59 |
62 | 63 | 64 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "html/template" 6 | "io/ioutil" 7 | "net/http" 8 | "os" 9 | "strings" 10 | 11 | "github.com/theplant/blackfriday" 12 | "gopkg.in/unrolled/render.v1" 13 | ) 14 | 15 | var Render = render.New(render.Options{ 16 | Layout: "layout", 17 | IsDevelopment: true, 18 | }) 19 | 20 | func main() { 21 | port := os.Getenv("PORT") 22 | if port == "" { 23 | port = "8080" 24 | } 25 | 26 | fs := http.FileServer(http.Dir(".")) 27 | handler := func(rw http.ResponseWriter, r *http.Request) { 28 | // Render the index as the main readme 29 | if r.URL.Path == "/" { 30 | if err := renderMarkdown(rw, "README.md"); err != nil { 31 | return 32 | } 33 | // Render markdown files 34 | } else if strings.HasSuffix(r.URL.Path, ".md") { 35 | if err := renderMarkdown(rw, r.URL.Path[1:]); err != nil { 36 | return 37 | } 38 | } else if strings.HasSuffix(r.URL.Path, ".go") { 39 | if err := renderCode(rw, r.URL.Path[1:]); err != nil { 40 | return 41 | } 42 | } else { 43 | fs.ServeHTTP(rw, r) 44 | } 45 | 46 | } 47 | 48 | fmt.Println("Listening on port", port) 49 | http.ListenAndServe(":"+port, http.HandlerFunc(handler)) 50 | } 51 | 52 | func renderMarkdown(rw http.ResponseWriter, name string) error { 53 | data, err := ioutil.ReadFile(name) 54 | if err != nil { 55 | http.Error(rw, "Unable to read file", 500) 56 | return err 57 | } 58 | 59 | output := blackfriday.MarkdownCommon(data) 60 | Render.HTML(rw, 200, "slide", template.HTML(output)) 61 | return nil 62 | } 63 | 64 | func renderCode(rw http.ResponseWriter, name string) error { 65 | data, err := ioutil.ReadFile(name) 66 | if err != nil { 67 | http.Error(rw, "Unable to read file", 500) 68 | return err 69 | } 70 | 71 | Render.HTML(rw, 200, "code", string(data)) 72 | return nil 73 | } 74 | -------------------------------------------------------------------------------- /01-language_syntax/06-functions/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/wPVvgwPlHw 5 | 6 | // Sample program to show how we can use the blank IDentifier to ignore return values. 7 | package main 8 | 9 | import ( 10 | "encoding/json" 11 | "errors" 12 | "fmt" 13 | ) 14 | 15 | type ( 16 | // user is a struct type that declares user information. 17 | user struct { 18 | ID int 19 | Name string 20 | } 21 | 22 | // updateStats provIDes update stats. 23 | updateStats struct { 24 | Modified int 25 | Duration float64 26 | Success bool 27 | Message string 28 | } 29 | ) 30 | 31 | // main is the entry point for the application. 32 | func main() { 33 | // Declare and initialize a value of type user. 34 | u := user{ 35 | ID: 1432, 36 | Name: "Betty", 37 | } 38 | 39 | // Update the user Name. Don't care about the update stats. 40 | if _, err := updateUser(&u); err != nil { 41 | fmt.Println(err) 42 | return 43 | } 44 | 45 | // Display the update was Successful. 46 | fmt.Println("Updated user record for ID", u.ID) 47 | } 48 | 49 | // updateUser updates the specified user document. 50 | func updateUser(u *user) (*updateStats, error) { 51 | // response simulates a JSON response. 52 | response := `{"Modified":1, "Duration":0.005, "Success" : true, "Message": "updated"}` 53 | 54 | // Unmarshal the json document into a value of 55 | // the userStats struct type. 56 | var us updateStats 57 | if err := json.Unmarshal([]byte(response), &us); err != nil { 58 | return nil, err 59 | } 60 | 61 | // Check the update status to verify the update 62 | // was Successful. 63 | if us.Success != true { 64 | return nil, errors.New(us.Message) 65 | } 66 | 67 | return &us, nil 68 | } 69 | -------------------------------------------------------------------------------- /11-standard_library/02-encoding/readme.md: -------------------------------------------------------------------------------- 1 | ## Encoding - Standard Library 2 | 3 | Encoding is the process or marshaling or unmarshaling data into different forms. Taking JSON string documents and convert them to values of our user defined types is a very common practice in many go programs today. Go's support for encoding is amazing and improves and gets faster with every release. 4 | 5 | ## Notes 6 | 7 | * Support for Decoding and Encoding JSON and XML are provided by the standard libary. 8 | * This package gets better and better with every release. 9 | 10 | ## Links 11 | 12 | http://www.goinggo.net/2014/01/decode-json-documents-in-go.html 13 | 14 | ## Code Review 15 | 16 | [Unmarshal JSON documents](example1/example1.go) ([Go Playground](http://play.golang.org/p/ocxFH62yaw)) 17 | 18 | [Unmarshal JSON files](example2/example2.go) ([Go Playground](http://play.golang.org/p/IWfOJbmMdL)) 19 | 20 | [Marshal a user defined type](example3/example3.go) ([Go Playground](http://play.golang.org/p/rLDpqYbnGR)) 21 | 22 | [Custom Marshaler and Unmarshler](example4/example4.go) ([Go Playground](http://play.golang.org/p/TOYrZJoLei)) 23 | 24 | ## Exercises 25 | 26 | ### Exercise 1 27 | 28 | **Part A** Create a file with an array of JSON documents that contain a user name and email address. Declare a struct type that maps to the JSON document. Using the json package, read the file and create a slice of this struct type. Display the slice. 29 | 30 | **Part B** Marshal the slice into pretty print strings and display each element. 31 | 32 | [Template](exercises/template1/template1.go) ([Go Playground](http://play.golang.org/p/OkIHsVwMQ7)) | 33 | [Answer](exercises/exercise1/exercise1.go) ([Go Playground](http://play.golang.org/p/Huf8jEDUJO)) 34 | ___ 35 | All material is licensed under the [GNU Free Documentation License](https://github.com/gobridge/gotraining/blob/master/LICENSE). 36 | -------------------------------------------------------------------------------- /01-language_syntax/06-functions/advanced/example1/example1.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/eg14ClW4_y 5 | 6 | // Sample program to show how to trap panics that can occur from the Go runtime. 7 | package main 8 | 9 | import ( 10 | "fmt" 11 | "runtime" 12 | ) 13 | 14 | // main is the entry point for the application. 15 | func main() { 16 | // Call the testPanic function to run the test. 17 | if err := testPanic(); err != nil { 18 | fmt.Println("Error:", err) 19 | } 20 | } 21 | 22 | // catchPanic catches panics and processes the error. 23 | func catchPanic(err *error) { 24 | // Check if a panic occurred. 25 | if r := recover(); r != nil { 26 | fmt.Println("PANIC Deferred") 27 | 28 | // Capture the stack trace 29 | buf := make([]byte, 10000) 30 | runtime.Stack(buf, false) 31 | fmt.Println("Stack Trace:", string(buf)) 32 | 33 | // If the caller wants the error back provide it. 34 | if err != nil { 35 | *err = fmt.Errorf("%v", r) 36 | } 37 | } 38 | } 39 | 40 | // mimicError is a function that simulates an error for 41 | // testing the code. 42 | func mimicError(key string) error { 43 | return fmt.Errorf("Mimic Error : %s", key) 44 | } 45 | 46 | // testPanic simulates a function that encounters a panic to 47 | // test our catchPanic function. 48 | func testPanic() (err error) { 49 | // Schedule the catchPanic function to be called when 50 | // the testPanic function returns. 51 | defer catchPanic(&err) 52 | 53 | fmt.Println("Start Test") 54 | 55 | // Mimic a traditional error from a function. 56 | err = mimicError("1") 57 | 58 | // Trying to dereference a nil pointer will cause the 59 | // runtime to panic. 60 | var p *int 61 | *p = 10 62 | 63 | fmt.Println("End Test") 64 | return err 65 | } 66 | -------------------------------------------------------------------------------- /08-concurrency_channels/02-race_conditions/example4/example4.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // https://play.golang.org/p/nr8BM7lvNA 5 | 6 | // go build -race 7 | 8 | // Sample program to show how to use a mutex to define critical 9 | // sections of code that need synchronous access. 10 | package main 11 | 12 | import ( 13 | "fmt" 14 | "runtime" 15 | "sync" 16 | ) 17 | 18 | // counter is a variable incremented by all goroutines. 19 | var counter int 20 | 21 | // wg is used to wait for the program to finish. 22 | var wg sync.WaitGroup 23 | 24 | // mutex is used to define a critical section of code. 25 | var mutex sync.Mutex 26 | 27 | // main is the entry point for all Go programs. 28 | func main() { 29 | // Add a count of two, one for each goroutine. 30 | wg.Add(2) 31 | 32 | // Create two goroutines. 33 | go incCounter(1) 34 | go incCounter(2) 35 | 36 | // Wait for the goroutines to finish. 37 | wg.Wait() 38 | fmt.Printf("Final Counter: %d\n", counter) 39 | } 40 | 41 | // incCounter increments the package level Counter variable 42 | // using the Mutex to synchronize and provide safe access. 43 | func incCounter(id int) { 44 | for count := 0; count < 2; count++ { 45 | // Only allow one goroutine through this 46 | // critical section at a time. 47 | mutex.Lock() 48 | { 49 | // Capture the value of counter. 50 | value := counter 51 | 52 | // Yield the thread and be placed back in queue. 53 | runtime.Gosched() 54 | 55 | // Increment our local value of counter. 56 | value++ 57 | 58 | // Store the value back into counter. 59 | counter = value 60 | } 61 | mutex.Unlock() 62 | // Release the lock and allow any 63 | // waiting goroutine through. 64 | } 65 | 66 | // Tell main we are done. 67 | wg.Done() 68 | } 69 | -------------------------------------------------------------------------------- /08-concurrency_channels/03-channels/example2/example2.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // http://play.golang.org/p/AzJuQsPG3a 5 | 6 | // Sample program to show how to use an unbuffered channel to 7 | // simulate a relay race between four goroutines. 8 | package main 9 | 10 | import ( 11 | "fmt" 12 | "sync" 13 | "time" 14 | ) 15 | 16 | // wg is used to wait for the program to finish. 17 | var wg sync.WaitGroup 18 | 19 | // main is the entry point for all Go programs. 20 | func main() { 21 | // Create an unbuffered channel. 22 | track := make(chan int) 23 | 24 | // Add a count of one for the last runner. 25 | wg.Add(1) 26 | 27 | // First runner to his mark. 28 | go Runner(track) 29 | 30 | // Start the race. 31 | track <- 1 32 | 33 | // Wait for the race to finish. 34 | wg.Wait() 35 | } 36 | 37 | // Runner simulates a person running in the relay race. 38 | func Runner(track chan int) { 39 | // The number of exchanges of the baton. 40 | const maxExchanges = 4 41 | 42 | var exchange int 43 | 44 | // Wait to receive the baton. 45 | baton := <-track 46 | 47 | // Start running around the track. 48 | fmt.Printf("Runner %d Running With Baton\n", baton) 49 | 50 | // New runner to the line. 51 | if baton < maxExchanges { 52 | exchange = baton + 1 53 | fmt.Printf("Runner %d To The Line\n", exchange) 54 | go Runner(track) 55 | } 56 | 57 | // Running around the track. 58 | time.Sleep(100 * time.Millisecond) 59 | 60 | // Is the race over. 61 | if baton == maxExchanges { 62 | fmt.Printf("Runner %d Finished, Race Over\n", baton) 63 | wg.Done() 64 | return 65 | } 66 | 67 | // Exchange the baton for the next runner. 68 | fmt.Printf("Runner %d Exchange With Runner %d\n", 69 | baton, 70 | exchange) 71 | 72 | track <- exchange 73 | } 74 | -------------------------------------------------------------------------------- /10-testing/01-testing/example4/handlers/handlers_test.go: -------------------------------------------------------------------------------- 1 | // All material is licensed under the GNU Free Documentation License 2 | // https://github.com/gobridge/gotraining/blob/master/LICENSE 3 | 4 | // Sample test to show how to test the execution of an internal endpoint. 5 | package handlers_test 6 | 7 | import ( 8 | "encoding/json" 9 | "net/http" 10 | "net/http/httptest" 11 | "testing" 12 | 13 | "github.com/gobridge/gotraining/10-testing/01-testing/example4/handlers" 14 | ) 15 | 16 | const succeed = "\u2713" 17 | const failed = "\u2717" 18 | 19 | func init() { 20 | handlers.Routes() 21 | } 22 | 23 | // TestSendJSON testing the sendjson internal endpoint. 24 | func TestSendJSON(t *testing.T) { 25 | t.Log("Given the need to test the SendJSON endpoint.") 26 | { 27 | r, _ := http.NewRequest("GET", "/sendjson", nil) 28 | w := httptest.NewRecorder() 29 | http.DefaultServeMux.ServeHTTP(w, r) 30 | 31 | if w.Code != 200 { 32 | t.Fatalf("\tShould receive a status code of \"200\" for the response. Received[%d] %s", w.Code, failed) 33 | } 34 | t.Log("\tShould receive a status code of \"200\" for the response.", succeed) 35 | 36 | u := struct { 37 | Name string 38 | Email string 39 | }{} 40 | if err := json.NewDecoder(w.Body).Decode(&u); err != nil { 41 | t.Fatal("\tShould be able to decode the response.", failed) 42 | } 43 | t.Log("\tShould be able to decode the response.", succeed) 44 | 45 | if u.Name == "Bill" { 46 | t.Log("\tShould have \"Bill\" for Name in the response.", succeed) 47 | } else { 48 | t.Error("\tShould have \"Bill\" for Name in the response.", failed, u.Name) 49 | } 50 | 51 | if u.Email == "bill@ardanstudios.com" { 52 | t.Log("\tShould have \"bill@ardanstudios.com\" for Email in the response.", succeed) 53 | } else { 54 | t.Error("\tShould have \"bill@ardanstudios.com\" for Email in the response.", failed, u.Email) 55 | } 56 | } 57 | } 58 | --------------------------------------------------------------------------------