├── 10-profiling ├── cmd │ └── beers-cli │ │ ├── beers.cpu.prof │ │ ├── beers.mem.prof │ │ └── main.go ├── internal │ ├── storage │ │ ├── ontario │ │ │ ├── repository_test.go │ │ │ ├── bench.new │ │ │ ├── bench.old │ │ │ └── repository.go │ │ ├── inmem │ │ │ └── repository.go │ │ ├── csv │ │ │ └── repository.go │ │ └── mock │ │ │ └── repository.go │ ├── errors │ │ └── errortypes.go │ ├── fetching │ │ ├── service.go │ │ └── service_test.go │ ├── cli │ │ └── beers.go │ ├── mock │ │ └── repository.go │ └── beer.go └── data │ └── beers.csv ├── 11-sharing_memory_concurrency ├── cmd │ └── beers-cli │ │ ├── beers.cpu.prof │ │ ├── beers.mem.prof │ │ └── main.go ├── internal │ ├── storage │ │ ├── ontario │ │ │ ├── repository_test.go │ │ │ ├── bench.new │ │ │ ├── bench.old │ │ │ └── repository.go │ │ ├── inmem │ │ │ └── repository.go │ │ ├── csv │ │ │ └── repository.go │ │ └── mock │ │ │ └── repository.go │ ├── errors │ │ └── errortypes.go │ ├── cli │ │ └── beers.go │ ├── fetching │ │ ├── service.go │ │ └── service_test.go │ ├── mock │ │ └── repository.go │ └── beer.go └── data │ └── beers.csv ├── .github └── dependabot.yml ├── 09-benchmarking ├── internal │ ├── storage │ │ ├── ontario │ │ │ ├── repository_test.go │ │ │ ├── bench.new │ │ │ ├── bench.old │ │ │ └── repository.go │ │ ├── inmem │ │ │ └── repository.go │ │ ├── csv │ │ │ └── repository.go │ │ └── mock │ │ │ └── repository.go │ ├── errors │ │ └── errortypes.go │ ├── fetching │ │ ├── service.go │ │ └── service_test.go │ ├── cli │ │ └── beers.go │ ├── mock │ │ └── repository.go │ └── beer.go ├── data │ └── beers.csv └── cmd │ └── beers-cli │ └── main.go ├── 03-reading_files ├── internal │ ├── beer.go │ └── cli │ │ └── beers.go ├── cmd │ └── beers-cli │ │ └── main.go └── data │ └── beers.csv ├── 06-error_handling ├── internal │ ├── errors │ │ └── errortypes.go │ ├── storage │ │ ├── csv │ │ │ └── repository.go │ │ └── ontario │ │ │ └── repository.go │ ├── cli │ │ └── beers.go │ └── beer.go ├── data │ └── beers.csv └── cmd │ └── beers-cli │ └── main.go ├── 02-refactor-to-cobra ├── cmd │ └── beers-cli │ │ └── main.go └── internal │ └── cli │ └── beers.go ├── go.mod ├── mock └── product.imp.json ├── ontario-mock └── product.imp.json ├── 04-modeling_data ├── data │ └── beers.csv ├── cmd │ └── beers-cli │ │ └── main.go └── internal │ ├── cli │ └── beers.go │ ├── storage │ └── csv │ │ └── repository.go │ └── beer.go ├── 08-automated_tests ├── data │ └── beers.csv ├── internal │ ├── storage │ │ ├── inmem │ │ │ └── repository.go │ │ ├── csv │ │ │ └── repository.go │ │ ├── ontario │ │ │ └── repository.go │ │ └── mock │ │ │ └── repository.go │ ├── errors │ │ └── errortypes.go │ ├── fetching │ │ ├── service.go │ │ └── service_test.go │ ├── cli │ │ └── beers.go │ └── beer.go └── cmd │ └── beers-cli │ └── main.go ├── 05-parsing_http_response ├── data │ └── beers.csv ├── cmd │ └── beers-cli │ │ └── main.go └── internal │ ├── storage │ ├── ontario │ │ └── repository.go │ └── csv │ │ └── repository.go │ ├── cli │ └── beers.go │ └── beer.go ├── 07-behaviour_error_handling ├── data │ └── beers.csv ├── cmd │ └── beers-cli │ │ └── main.go └── internal │ ├── errors │ └── errortypes.go │ ├── storage │ ├── csv │ │ └── repository.go │ └── ontario │ │ └── repository.go │ ├── cli │ └── beers.go │ └── beer.go ├── 01-go_flags └── main.go ├── README.md └── go.sum /10-profiling/cmd/beers-cli/beers.cpu.prof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piraces/golang-examples/master/10-profiling/cmd/beers-cli/beers.cpu.prof -------------------------------------------------------------------------------- /10-profiling/cmd/beers-cli/beers.mem.prof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piraces/golang-examples/master/10-profiling/cmd/beers-cli/beers.mem.prof -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/cmd/beers-cli/beers.cpu.prof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piraces/golang-examples/master/11-sharing_memory_concurrency/cmd/beers-cli/beers.cpu.prof -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/cmd/beers-cli/beers.mem.prof: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piraces/golang-examples/master/11-sharing_memory_concurrency/cmd/beers-cli/beers.mem.prof -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | time: "08:00" 8 | timezone: Europe/Madrid 9 | open-pull-requests-limit: 2 10 | -------------------------------------------------------------------------------- /09-benchmarking/internal/storage/ontario/repository_test.go: -------------------------------------------------------------------------------- 1 | package ontario 2 | 3 | import "testing" 4 | 5 | func BenchmarkGetBeers(b *testing.B) { 6 | repo := NewOntarioRepository() 7 | b.ResetTimer() 8 | for n := 0; n < b.N; n++ { 9 | repo.GetBeers() 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /10-profiling/internal/storage/ontario/repository_test.go: -------------------------------------------------------------------------------- 1 | package ontario 2 | 3 | import "testing" 4 | 5 | func BenchmarkGetBeers(b *testing.B) { 6 | repo := NewOntarioRepository() 7 | b.ResetTimer() 8 | for n := 0; n < b.N; n++ { 9 | repo.GetBeers() 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/storage/ontario/repository_test.go: -------------------------------------------------------------------------------- 1 | package ontario 2 | 3 | import "testing" 4 | 5 | func BenchmarkGetBeers(b *testing.B) { 6 | repo := NewOntarioRepository() 7 | b.ResetTimer() 8 | for n := 0; n < b.N; n++ { 9 | repo.GetBeers() 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /03-reading_files/internal/beer.go: -------------------------------------------------------------------------------- 1 | package beerscli 2 | 3 | // Beer representation of beer into data struct 4 | type Beer struct { 5 | ProductID int 6 | Name string 7 | Price float64 8 | Category string 9 | Type string 10 | Brewer string 11 | Country string 12 | } 13 | -------------------------------------------------------------------------------- /06-error_handling/internal/errors/errortypes.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import "fmt" 4 | 5 | type BadResponseErr struct { 6 | Msg string 7 | File string 8 | Line int 9 | } 10 | 11 | func (e *BadResponseErr) Error() string { 12 | return fmt.Sprintf("%s: %d: %s", e.File, e.Line, e.Msg) 13 | } 14 | -------------------------------------------------------------------------------- /10-profiling/internal/storage/ontario/bench.new: -------------------------------------------------------------------------------- 1 | goos: darwin 2 | goarch: amd64 3 | pkg: github.com/CodelyTV/golang-examples/10-profiling/internal/storage/ontario 4 | BenchmarkGetBeers-8 200 8124287 ns/op 5 | PASS 6 | ok github.com/CodelyTV/golang-examples/10-profiling/internal/storage/ontario 2.476s 7 | -------------------------------------------------------------------------------- /10-profiling/internal/storage/ontario/bench.old: -------------------------------------------------------------------------------- 1 | goos: darwin 2 | goarch: amd64 3 | pkg: github.com/CodelyTV/golang-examples/10-profiling/internal/storage/ontario 4 | BenchmarkGetBeers-8 50 25692443 ns/op 5 | PASS 6 | ok github.com/CodelyTV/golang-examples/10-profiling/internal/storage/ontario 1.333s 7 | -------------------------------------------------------------------------------- /09-benchmarking/internal/storage/ontario/bench.new: -------------------------------------------------------------------------------- 1 | goos: darwin 2 | goarch: amd64 3 | pkg: github.com/CodelyTV/golang-examples/09-benchmarking/internal/storage/ontario 4 | BenchmarkGetBeers-8 200 8124287 ns/op 5 | PASS 6 | ok github.com/CodelyTV/golang-examples/09-benchmarking/internal/storage/ontario 2.476s 7 | -------------------------------------------------------------------------------- /09-benchmarking/internal/storage/ontario/bench.old: -------------------------------------------------------------------------------- 1 | goos: darwin 2 | goarch: amd64 3 | pkg: github.com/CodelyTV/golang-examples/09-benchmarking/internal/storage/ontario 4 | BenchmarkGetBeers-8 50 25692443 ns/op 5 | PASS 6 | ok github.com/CodelyTV/golang-examples/09-benchmarking/internal/storage/ontario 1.333s 7 | -------------------------------------------------------------------------------- /03-reading_files/cmd/beers-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/CodelyTV/golang-examples/03-reading_files/internal/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func main() { 9 | rootCmd := &cobra.Command{Use: "beers-cli"} 10 | rootCmd.AddCommand(cli.InitBeersCmd()) 11 | rootCmd.Execute() 12 | } 13 | -------------------------------------------------------------------------------- /02-refactor-to-cobra/cmd/beers-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/CodelyTV/golang-examples/02-refactor-to-cobra/internal/cli" 5 | "github.com/spf13/cobra" 6 | ) 7 | 8 | func main() { 9 | rootCmd := &cobra.Command{Use: "beers-cli"} 10 | rootCmd.AddCommand(cli.InitBeersCmd()) 11 | rootCmd.Execute() 12 | } 13 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/storage/ontario/bench.new: -------------------------------------------------------------------------------- 1 | goos: darwin 2 | goarch: amd64 3 | pkg: github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal/storage/ontario 4 | BenchmarkGetBeers-8 200 8124287 ns/op 5 | PASS 6 | ok github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal/storage/ontario 2.476s 7 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/storage/ontario/bench.old: -------------------------------------------------------------------------------- 1 | goos: darwin 2 | goarch: amd64 3 | pkg: github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal/storage/ontario 4 | BenchmarkGetBeers-8 50 25692443 ns/op 5 | PASS 6 | ok github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal/storage/ontario 1.333s 7 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/CodelyTV/golang-examples 2 | 3 | go 1.12 4 | 5 | require ( 6 | github.com/json-iterator/go v1.1.11 7 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 8 | github.com/modern-go/reflect2 v1.0.1 // indirect 9 | github.com/pkg/errors v0.9.1 10 | github.com/spf13/cobra v0.0.7 11 | github.com/stretchr/testify v1.7.0 12 | ) 13 | -------------------------------------------------------------------------------- /mock/product.imp.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "method": "GET", 5 | "endpoint": "/products" 6 | }, 7 | "response": { 8 | "status": 200, 9 | "headers": { 10 | "Content-Type": "application/json" 11 | }, 12 | "bodyFile": "responses/products.json" 13 | } 14 | } 15 | ] -------------------------------------------------------------------------------- /ontario-mock/product.imp.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "request": { 4 | "method": "GET", 5 | "endpoint": "/products" 6 | }, 7 | "response": { 8 | "status": 200, 9 | "headers": { 10 | "Content-Type": "application/json" 11 | }, 12 | "bodyFile": "product_response.json" 13 | } 14 | } 15 | ] 16 | -------------------------------------------------------------------------------- /04-modeling_data/data/beers.csv: -------------------------------------------------------------------------------- 1 | 127,Mad Jack Mixer,Domestic Specialty,23.95,Lager,Molson,Canada 2 | 128,Mad Jack Hard Root Beer,Domestic Specialty,15.25,Lager,Molson,Canada 3 | 131,Keystone Ice,Value,49.65,Lager,Molson,Canada 4 | 133,Mad Jack,Domestic Specialty,15.25,Malt,Molson,Canada 5 | 8431,Lake Wilcox Bandit Apa,Ontario Craft,63.60,Ale,Lake Wilcox Brewing,Canada 6 | 8520130,Grolsch 0.0,Non-Alcoholic Beer,49.50,Non-Alcoholic Beer,Grolsch Export B.V.,Canada 7 | -------------------------------------------------------------------------------- /09-benchmarking/data/beers.csv: -------------------------------------------------------------------------------- 1 | 127,Mad Jack Mixer,Domestic Specialty,23.95,Lager,Molson,Canada 2 | 128,Mad Jack Hard Root Beer,Domestic Specialty,15.25,Lager,Molson,Canada 3 | 131,Keystone Ice,Value,49.65,Lager,Molson,Canada 4 | 133,Mad Jack,Domestic Specialty,15.25,Malt,Molson,Canada 5 | 8431,Lake Wilcox Bandit Apa,Ontario Craft,63.60,Ale,Lake Wilcox Brewing,Canada 6 | 8520130,Grolsch 0.0,Non-Alcoholic Beer,49.50,Non-Alcoholic Beer,Grolsch Export B.V.,Canada 7 | -------------------------------------------------------------------------------- /10-profiling/data/beers.csv: -------------------------------------------------------------------------------- 1 | 127,Mad Jack Mixer,Domestic Specialty,23.95,Lager,Molson,Canada 2 | 128,Mad Jack Hard Root Beer,Domestic Specialty,15.25,Lager,Molson,Canada 3 | 131,Keystone Ice,Value,49.65,Lager,Molson,Canada 4 | 133,Mad Jack,Domestic Specialty,15.25,Malt,Molson,Canada 5 | 8431,Lake Wilcox Bandit Apa,Ontario Craft,63.60,Ale,Lake Wilcox Brewing,Canada 6 | 8520130,Grolsch 0.0,Non-Alcoholic Beer,49.50,Non-Alcoholic Beer,Grolsch Export B.V.,Canada 7 | -------------------------------------------------------------------------------- /03-reading_files/data/beers.csv: -------------------------------------------------------------------------------- 1 | 127,Mad Jack Mixer,Domestic Specialty,23.95,Larger,Molson,Canada 2 | 128,Mad Jack Hard Root Beer,Domestic Specialty,15.25,Larger,Molson,Canada 3 | 131,Keystone Ice,Value,49.65,Larger,Molson,Canada 4 | 133,Mad Jack,Domestic Specialty,15.25,Malt,Molson,Canada 5 | 8431,Lake Wilcox Bandit Apa,Ontario Craft,63.60,Ale,Lake Wilcox Brewing,Canada 6 | 8520130,Grolsch 0.0,Non-Alcoholic Beer,49.50,Non-Alcoholic Beer,Grolsch Export B.V.,Canada 7 | -------------------------------------------------------------------------------- /06-error_handling/data/beers.csv: -------------------------------------------------------------------------------- 1 | 127,Mad Jack Mixer,Domestic Specialty,23.95,Lager,Molson,Canada 2 | 128,Mad Jack Hard Root Beer,Domestic Specialty,15.25,Lager,Molson,Canada 3 | 131,Keystone Ice,Value,49.65,Lager,Molson,Canada 4 | 133,Mad Jack,Domestic Specialty,15.25,Malt,Molson,Canada 5 | 8431,Lake Wilcox Bandit Apa,Ontario Craft,63.60,Ale,Lake Wilcox Brewing,Canada 6 | 8520130,Grolsch 0.0,Non-Alcoholic Beer,49.50,Non-Alcoholic Beer,Grolsch Export B.V.,Canada 7 | -------------------------------------------------------------------------------- /08-automated_tests/data/beers.csv: -------------------------------------------------------------------------------- 1 | 127,Mad Jack Mixer,Domestic Specialty,23.95,Lager,Molson,Canada 2 | 128,Mad Jack Hard Root Beer,Domestic Specialty,15.25,Lager,Molson,Canada 3 | 131,Keystone Ice,Value,49.65,Lager,Molson,Canada 4 | 133,Mad Jack,Domestic Specialty,15.25,Malt,Molson,Canada 5 | 8431,Lake Wilcox Bandit Apa,Ontario Craft,63.60,Ale,Lake Wilcox Brewing,Canada 6 | 8520130,Grolsch 0.0,Non-Alcoholic Beer,49.50,Non-Alcoholic Beer,Grolsch Export B.V.,Canada 7 | -------------------------------------------------------------------------------- /04-modeling_data/cmd/beers-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/CodelyTV/golang-examples/04-modeling_data/internal/cli" 5 | "github.com/CodelyTV/golang-examples/04-modeling_data/internal/storage/csv" 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | func main() { 10 | 11 | csvRepo := csv.NewRepository() 12 | 13 | rootCmd := &cobra.Command{Use: "beers-cli"} 14 | rootCmd.AddCommand(cli.InitBeersCmd(csvRepo)) 15 | rootCmd.Execute() 16 | } 17 | -------------------------------------------------------------------------------- /05-parsing_http_response/data/beers.csv: -------------------------------------------------------------------------------- 1 | 127,Mad Jack Mixer,Domestic Specialty,23.95,Lager,Molson,Canada 2 | 128,Mad Jack Hard Root Beer,Domestic Specialty,15.25,Lager,Molson,Canada 3 | 131,Keystone Ice,Value,49.65,Lager,Molson,Canada 4 | 133,Mad Jack,Domestic Specialty,15.25,Malt,Molson,Canada 5 | 8431,Lake Wilcox Bandit Apa,Ontario Craft,63.60,Ale,Lake Wilcox Brewing,Canada 6 | 8520130,Grolsch 0.0,Non-Alcoholic Beer,49.50,Non-Alcoholic Beer,Grolsch Export B.V.,Canada 7 | -------------------------------------------------------------------------------- /07-behaviour_error_handling/data/beers.csv: -------------------------------------------------------------------------------- 1 | 127,Mad Jack Mixer,Domestic Specialty,23.95,Lager,Molson,Canada 2 | 128,Mad Jack Hard Root Beer,Domestic Specialty,15.25,Lager,Molson,Canada 3 | 131,Keystone Ice,Value,49.65,Lager,Molson,Canada 4 | 133,Mad Jack,Domestic Specialty,15.25,Malt,Molson,Canada 5 | 8431,Lake Wilcox Bandit Apa,Ontario Craft,63.60,Ale,Lake Wilcox Brewing,Canada 6 | 8520130,Grolsch 0.0,Non-Alcoholic Beer,49.50,Non-Alcoholic Beer,Grolsch Export B.V.,Canada 7 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/data/beers.csv: -------------------------------------------------------------------------------- 1 | 127,Mad Jack Mixer,Domestic Specialty,23.95,Lager,Molson,Canada 2 | 128,Mad Jack Hard Root Beer,Domestic Specialty,15.25,Lager,Molson,Canada 3 | 131,Keystone Ice,Value,49.65,Lager,Molson,Canada 4 | 133,Mad Jack,Domestic Specialty,15.25,Malt,Molson,Canada 5 | 8431,Lake Wilcox Bandit Apa,Ontario Craft,63.60,Ale,Lake Wilcox Brewing,Canada 6 | 8520130,Grolsch 0.0,Non-Alcoholic Beer,49.50,Non-Alcoholic Beer,Grolsch Export B.V.,Canada 7 | -------------------------------------------------------------------------------- /01-go_flags/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | "os" 8 | ) 9 | 10 | var beers = map[string]string{ 11 | "01D9X58E7NPXX5MVCR9QN794CH": "Mad Jack Mixer", 12 | "01D9X5BQ5X48XMMVZ2F2G3R5MS": "Keystone Ice", 13 | "01D9X5CVS1M9VR5ZD627XDF6ND": "Belgian Moon", 14 | } 15 | 16 | func main() { 17 | 18 | beersCmd := flag.NewFlagSet("beers", flag.ExitOnError) 19 | flag.Parse() 20 | 21 | if flag.NArg() == 0 { 22 | log.Fatal("You must specified a command beers") 23 | os.Exit(2) 24 | } 25 | 26 | switch flag.Arg(0) { 27 | case "beers": 28 | ID := beersCmd.String("id", "", "find by ID") 29 | beersCmd.Parse(os.Args[2:]) 30 | 31 | if *ID != "" { 32 | fmt.Println(beers[*ID]) 33 | } else { 34 | fmt.Println(beers) 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /06-error_handling/cmd/beers-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | "github.com/CodelyTV/golang-examples/06-error_handling/internal/storage/ontario" 7 | 8 | beerscli "github.com/CodelyTV/golang-examples/06-error_handling/internal" 9 | "github.com/CodelyTV/golang-examples/06-error_handling/internal/cli" 10 | "github.com/CodelyTV/golang-examples/06-error_handling/internal/storage/csv" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | func main() { 15 | 16 | csvData := flag.Bool("csv", false, "load data from csv") 17 | flag.Parse() 18 | var repo beerscli.BeerRepo 19 | repo = csv.NewRepository() 20 | 21 | if !*csvData { 22 | repo = ontario.NewOntarioRepository() 23 | } 24 | 25 | rootCmd := &cobra.Command{Use: "beers-cli"} 26 | rootCmd.AddCommand(cli.InitBeersCmd(repo)) 27 | rootCmd.Execute() 28 | } 29 | -------------------------------------------------------------------------------- /05-parsing_http_response/cmd/beers-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | "github.com/CodelyTV/golang-examples/05-parsing_http_response/internal/storage/ontario" 7 | 8 | beerscli "github.com/CodelyTV/golang-examples/05-parsing_http_response/internal" 9 | "github.com/CodelyTV/golang-examples/05-parsing_http_response/internal/cli" 10 | "github.com/CodelyTV/golang-examples/05-parsing_http_response/internal/storage/csv" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | func main() { 15 | 16 | csvData := flag.Bool("csv", false, "load data from csv") 17 | flag.Parse() 18 | 19 | var repo beerscli.BeerRepo 20 | repo = csv.NewRepository() 21 | 22 | if !*csvData { 23 | repo = ontario.NewOntarioRepository() 24 | } 25 | 26 | rootCmd := &cobra.Command{Use: "beers-cli"} 27 | rootCmd.AddCommand(cli.InitBeersCmd(repo)) 28 | rootCmd.Execute() 29 | } 30 | -------------------------------------------------------------------------------- /07-behaviour_error_handling/cmd/beers-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | "github.com/CodelyTV/golang-examples/07-behaviour_error_handling/internal/storage/ontario" 7 | 8 | beerscli "github.com/CodelyTV/golang-examples/07-behaviour_error_handling/internal" 9 | "github.com/CodelyTV/golang-examples/07-behaviour_error_handling/internal/cli" 10 | "github.com/CodelyTV/golang-examples/07-behaviour_error_handling/internal/storage/csv" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | func main() { 15 | 16 | csvData := flag.Bool("csv", false, "load data from csv") 17 | flag.Parse() 18 | var repo beerscli.BeerRepo 19 | repo = csv.NewRepository() 20 | 21 | if !*csvData { 22 | repo = ontario.NewOntarioRepository() 23 | } 24 | 25 | rootCmd := &cobra.Command{Use: "beers-cli"} 26 | rootCmd.AddCommand(cli.InitBeersCmd(repo)) 27 | rootCmd.Execute() 28 | } 29 | -------------------------------------------------------------------------------- /10-profiling/internal/storage/inmem/repository.go: -------------------------------------------------------------------------------- 1 | package inmem 2 | 3 | import ( 4 | beerscli "github.com/CodelyTV/golang-examples/10-profiling/internal" 5 | ) 6 | 7 | type repository struct { 8 | } 9 | 10 | // NewRepository initialize csv repository 11 | func NewRepository() beerscli.BeerRepo { 12 | return &repository{} 13 | } 14 | 15 | // GetBeers fetch beers data from memory 16 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 17 | return []beerscli.Beer{ 18 | beerscli.NewBeer( 19 | 127, 20 | "Mad Jack Mixer", 21 | "Domestic Specialty", 22 | "Molson", 23 | "Canada", 24 | "23.95", 25 | beerscli.NewBeerType("Lager"), 26 | ), 27 | beerscli.NewBeer( 28 | 8520130, 29 | "Grolsch 0.0", 30 | "Non-Alcoholic Beer", 31 | "Grolsch Export B.V.", 32 | "Canada", 33 | "49.50", 34 | beerscli.NewBeerType("Non-Alcoholic Beer"), 35 | ), 36 | }, nil 37 | } 38 | -------------------------------------------------------------------------------- /09-benchmarking/internal/storage/inmem/repository.go: -------------------------------------------------------------------------------- 1 | package inmem 2 | 3 | import ( 4 | beerscli "github.com/CodelyTV/golang-examples/09-benchmarking/internal" 5 | ) 6 | 7 | type repository struct { 8 | } 9 | 10 | // NewRepository initialize csv repository 11 | func NewRepository() beerscli.BeerRepo { 12 | return &repository{} 13 | } 14 | 15 | // GetBeers fetch beers data from memory 16 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 17 | return []beerscli.Beer{ 18 | beerscli.NewBeer( 19 | 127, 20 | "Mad Jack Mixer", 21 | "Domestic Specialty", 22 | "Molson", 23 | "Canada", 24 | "23.95", 25 | beerscli.NewBeerType("Lager"), 26 | ), 27 | beerscli.NewBeer( 28 | 8520130, 29 | "Grolsch 0.0", 30 | "Non-Alcoholic Beer", 31 | "Grolsch Export B.V.", 32 | "Canada", 33 | "49.50", 34 | beerscli.NewBeerType("Non-Alcoholic Beer"), 35 | ), 36 | }, nil 37 | } 38 | -------------------------------------------------------------------------------- /08-automated_tests/internal/storage/inmem/repository.go: -------------------------------------------------------------------------------- 1 | package inmem 2 | 3 | import ( 4 | beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" 5 | ) 6 | 7 | type repository struct { 8 | } 9 | 10 | // NewRepository initialize csv repository 11 | func NewRepository() beerscli.BeerRepo { 12 | return &repository{} 13 | } 14 | 15 | // GetBeers fetch beers data from memory 16 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 17 | return []beerscli.Beer{ 18 | beerscli.NewBeer( 19 | 127, 20 | "Mad Jack Mixer", 21 | "Domestic Specialty", 22 | "Molson", 23 | "Canada", 24 | "23.95", 25 | beerscli.NewBeerType("Lager"), 26 | ), 27 | beerscli.NewBeer( 28 | 8520130, 29 | "Grolsch 0.0", 30 | "Non-Alcoholic Beer", 31 | "Grolsch Export B.V.", 32 | "Canada", 33 | "49.50", 34 | beerscli.NewBeerType("Non-Alcoholic Beer"), 35 | ), 36 | }, nil 37 | } 38 | -------------------------------------------------------------------------------- /10-profiling/internal/errors/errortypes.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "github.com/pkg/errors" 5 | ) 6 | 7 | type dataUnreacheable struct { 8 | error 9 | } 10 | 11 | // WrapDataUnreacheable returns an error which wraps err that satisfies 12 | // IsDataUnreacheable() 13 | func WrapDataUnreacheable(err error, format string, args ...interface{}) error { 14 | return &dataUnreacheable{errors.Wrapf(err, format, args...)} 15 | } 16 | 17 | // NewDataUnreacheable returns an error which satisfies IsDataUnreacheable() 18 | func NewDataUnreacheable(format string, args ...interface{}) error { 19 | return &dataUnreacheable{errors.Errorf(format, args...)} 20 | } 21 | 22 | // IsDataUnreacheable reports whether err was created with DataUnreacheablef() or 23 | // NewDataUnreacheable() 24 | func IsDataUnreacheable(err error) bool { 25 | err = errors.Cause(err) 26 | _, ok := err.(*dataUnreacheable) 27 | return ok 28 | } 29 | -------------------------------------------------------------------------------- /08-automated_tests/internal/errors/errortypes.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "github.com/pkg/errors" 5 | ) 6 | 7 | type dataUnreacheable struct { 8 | error 9 | } 10 | 11 | // WrapDataUnreacheable returns an error which wraps err that satisfies 12 | // IsDataUnreacheable() 13 | func WrapDataUnreacheable(err error, format string, args ...interface{}) error { 14 | return &dataUnreacheable{errors.Wrapf(err, format, args...)} 15 | } 16 | 17 | // NewDataUnreacheable returns an error which satisfies IsDataUnreacheable() 18 | func NewDataUnreacheable(format string, args ...interface{}) error { 19 | return &dataUnreacheable{errors.Errorf(format, args...)} 20 | } 21 | 22 | // IsDataUnreacheable reports whether err was created with DataUnreacheablef() or 23 | // NewDataUnreacheable() 24 | func IsDataUnreacheable(err error) bool { 25 | err = errors.Cause(err) 26 | _, ok := err.(*dataUnreacheable) 27 | return ok 28 | } 29 | -------------------------------------------------------------------------------- /09-benchmarking/internal/errors/errortypes.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "github.com/pkg/errors" 5 | ) 6 | 7 | type dataUnreacheable struct { 8 | error 9 | } 10 | 11 | // WrapDataUnreacheable returns an error which wraps err that satisfies 12 | // IsDataUnreacheable() 13 | func WrapDataUnreacheable(err error, format string, args ...interface{}) error { 14 | return &dataUnreacheable{errors.Wrapf(err, format, args...)} 15 | } 16 | 17 | // NewDataUnreacheable returns an error which satisfies IsDataUnreacheable() 18 | func NewDataUnreacheable(format string, args ...interface{}) error { 19 | return &dataUnreacheable{errors.Errorf(format, args...)} 20 | } 21 | 22 | // IsDataUnreacheable reports whether err was created with DataUnreacheablef() or 23 | // NewDataUnreacheable() 24 | func IsDataUnreacheable(err error) bool { 25 | err = errors.Cause(err) 26 | _, ok := err.(*dataUnreacheable) 27 | return ok 28 | } 29 | -------------------------------------------------------------------------------- /07-behaviour_error_handling/internal/errors/errortypes.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "github.com/pkg/errors" 5 | ) 6 | 7 | type dataUnreacheable struct { 8 | error 9 | } 10 | 11 | // WrapDataUnreacheable returns an error which wraps err that satisfies 12 | // IsDataUnreacheable() 13 | func WrapDataUnreacheable(err error, format string, args ...interface{}) error { 14 | return &dataUnreacheable{errors.Wrapf(err, format, args...)} 15 | } 16 | 17 | // NewDataUnreacheable returns an error which satisfies IsDataUnreacheable() 18 | func NewDataUnreacheable(format string, args ...interface{}) error { 19 | return &dataUnreacheable{errors.Errorf(format, args...)} 20 | } 21 | 22 | // IsDataUnreacheable reports whether err was created with DataUnreacheablef() or 23 | // NewDataUnreacheable() 24 | func IsDataUnreacheable(err error) bool { 25 | err = errors.Cause(err) 26 | _, ok := err.(*dataUnreacheable) 27 | return ok 28 | } 29 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/errors/errortypes.go: -------------------------------------------------------------------------------- 1 | package errors 2 | 3 | import ( 4 | "github.com/pkg/errors" 5 | ) 6 | 7 | type dataUnreacheable struct { 8 | error 9 | } 10 | 11 | // WrapDataUnreacheable returns an error which wraps err that satisfies 12 | // IsDataUnreacheable() 13 | func WrapDataUnreacheable(err error, format string, args ...interface{}) error { 14 | return &dataUnreacheable{errors.Wrapf(err, format, args...)} 15 | } 16 | 17 | // NewDataUnreacheable returns an error which satisfies IsDataUnreacheable() 18 | func NewDataUnreacheable(format string, args ...interface{}) error { 19 | return &dataUnreacheable{errors.Errorf(format, args...)} 20 | } 21 | 22 | // IsDataUnreacheable reports whether err was created with DataUnreacheablef() or 23 | // NewDataUnreacheable() 24 | func IsDataUnreacheable(err error) bool { 25 | err = errors.Cause(err) 26 | _, ok := err.(*dataUnreacheable) 27 | return ok 28 | } 29 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/storage/inmem/repository.go: -------------------------------------------------------------------------------- 1 | package inmem 2 | 3 | import ( 4 | beerscli "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal" 5 | ) 6 | 7 | type repository struct { 8 | } 9 | 10 | // NewRepository initialize csv repository 11 | func NewRepository() beerscli.BeerRepo { 12 | return &repository{} 13 | } 14 | 15 | // GetBeers fetch beers data from memory 16 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 17 | return []beerscli.Beer{ 18 | beerscli.NewBeer( 19 | 127, 20 | "Mad Jack Mixer", 21 | "Domestic Specialty", 22 | "Molson", 23 | "Canada", 24 | "23.95", 25 | beerscli.NewBeerType("Lager"), 26 | ), 27 | beerscli.NewBeer( 28 | 8520130, 29 | "Grolsch 0.0", 30 | "Non-Alcoholic Beer", 31 | "Grolsch Export B.V.", 32 | "Canada", 33 | "49.50", 34 | beerscli.NewBeerType("Non-Alcoholic Beer"), 35 | ), 36 | }, nil 37 | } 38 | -------------------------------------------------------------------------------- /09-benchmarking/cmd/beers-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | "github.com/CodelyTV/golang-examples/09-benchmarking/internal/fetching" 7 | 8 | "github.com/CodelyTV/golang-examples/09-benchmarking/internal/storage/ontario" 9 | 10 | beerscli "github.com/CodelyTV/golang-examples/09-benchmarking/internal" 11 | "github.com/CodelyTV/golang-examples/09-benchmarking/internal/cli" 12 | "github.com/CodelyTV/golang-examples/09-benchmarking/internal/storage/csv" 13 | "github.com/spf13/cobra" 14 | ) 15 | 16 | func main() { 17 | 18 | csvData := flag.Bool("csv", false, "load data from csv") 19 | flag.Parse() 20 | var repo beerscli.BeerRepo 21 | repo = csv.NewRepository() 22 | 23 | if !*csvData { 24 | repo = ontario.NewOntarioRepository() 25 | } 26 | 27 | fetchingService := fetching.NewService(repo) 28 | 29 | rootCmd := &cobra.Command{Use: "beers-cli"} 30 | rootCmd.AddCommand(cli.InitBeersCmd(fetchingService)) 31 | rootCmd.Execute() 32 | } 33 | -------------------------------------------------------------------------------- /08-automated_tests/cmd/beers-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | "github.com/CodelyTV/golang-examples/08-automated_tests/internal/fetching" 7 | 8 | "github.com/CodelyTV/golang-examples/08-automated_tests/internal/storage/ontario" 9 | 10 | beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" 11 | "github.com/CodelyTV/golang-examples/08-automated_tests/internal/cli" 12 | "github.com/CodelyTV/golang-examples/08-automated_tests/internal/storage/csv" 13 | "github.com/spf13/cobra" 14 | ) 15 | 16 | func main() { 17 | 18 | csvData := flag.Bool("csv", false, "load data from csv") 19 | flag.Parse() 20 | var repo beerscli.BeerRepo 21 | repo = csv.NewRepository() 22 | 23 | if !*csvData { 24 | repo = ontario.NewOntarioRepository() 25 | } 26 | 27 | fetchingService := fetching.NewService(repo) 28 | 29 | rootCmd := &cobra.Command{Use: "beers-cli"} 30 | rootCmd.AddCommand(cli.InitBeersCmd(fetchingService)) 31 | rootCmd.Execute() 32 | } 33 | -------------------------------------------------------------------------------- /05-parsing_http_response/internal/storage/ontario/repository.go: -------------------------------------------------------------------------------- 1 | package ontario 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/05-parsing_http_response/internal" 10 | ) 11 | 12 | const ( 13 | productsEndpoint = "/products" 14 | ontarioURL = "http://ontariobeerapi.ca" 15 | ) 16 | 17 | type beerRepo struct { 18 | url string 19 | } 20 | 21 | // NewOntarioRepository fetch beers data from csv 22 | func NewOntarioRepository() beerscli.BeerRepo { 23 | return &beerRepo{url: ontarioURL} 24 | } 25 | 26 | func (b *beerRepo) GetBeers() (beers []beerscli.Beer, err error) { 27 | response, err := http.Get(fmt.Sprintf("%v%v", b.url, productsEndpoint)) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | contents, err := ioutil.ReadAll(response.Body) 33 | if err != nil { 34 | return nil, err 35 | } 36 | 37 | err = json.Unmarshal(contents, &beers) 38 | if err != nil { 39 | return nil, err 40 | } 41 | return 42 | } 43 | -------------------------------------------------------------------------------- /02-refactor-to-cobra/internal/cli/beers.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | // CobraFn function definion of run cobra command 10 | type CobraFn func(cmd *cobra.Command, args []string) 11 | 12 | var beers = map[string]string{ 13 | "01D9X58E7NPXX5MVCR9QN794CH": "Mad Jack Mixer", 14 | "01D9X5BQ5X48XMMVZ2F2G3R5MS": "Keystone Ice", 15 | "01D9X5CVS1M9VR5ZD627XDF6ND": "Belgian Moon", 16 | } 17 | 18 | const idFlag = "id" 19 | 20 | // InitBeersCmd initialize beers command 21 | func InitBeersCmd() *cobra.Command { 22 | beersCmd := &cobra.Command{ 23 | Use: "beers", 24 | Short: "Print data about beers", 25 | Run: runBeersFn(), 26 | } 27 | 28 | beersCmd.Flags().StringP(idFlag, "i", "", "id of the beer") 29 | 30 | return beersCmd 31 | } 32 | 33 | func runBeersFn() CobraFn { 34 | return func(cmd *cobra.Command, args []string) { 35 | id, _ := cmd.Flags().GetString(idFlag) 36 | 37 | if id != "" { 38 | fmt.Println(beers[id]) 39 | } else { 40 | fmt.Println(beers) 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /04-modeling_data/internal/cli/beers.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | beerscli "github.com/CodelyTV/golang-examples/04-modeling_data/internal" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | // CobraFn function definion of run cobra command 12 | type CobraFn func(cmd *cobra.Command, args []string) 13 | 14 | const idFlag = "id" 15 | 16 | // InitBeersCmd initialize beers command 17 | func InitBeersCmd(repository beerscli.BeerRepo) *cobra.Command { 18 | beersCmd := &cobra.Command{ 19 | Use: "beers", 20 | Short: "Print data about beers", 21 | Run: runBeersFn(repository), 22 | } 23 | 24 | beersCmd.Flags().StringP(idFlag, "i", "", "id of the beer") 25 | 26 | return beersCmd 27 | } 28 | 29 | func runBeersFn(repository beerscli.BeerRepo) CobraFn { 30 | return func(cmd *cobra.Command, args []string) { 31 | beers, _ := repository.GetBeers() 32 | 33 | id, _ := cmd.Flags().GetString(idFlag) 34 | 35 | if id != "" { 36 | i, _ := strconv.Atoi(id) 37 | for _, beer := range beers { 38 | if beer.ProductID == i { 39 | fmt.Println(beer) 40 | return 41 | } 42 | } 43 | } else { 44 | fmt.Println(beers) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /10-profiling/internal/fetching/service.go: -------------------------------------------------------------------------------- 1 | package fetching 2 | 3 | import ( 4 | beerscli "github.com/CodelyTV/golang-examples/10-profiling/internal" 5 | "github.com/pkg/errors" 6 | ) 7 | 8 | // Service provides beer fetching operations 9 | type Service interface { 10 | // FetchBeers fetch all beers from repository 11 | FetchBeers() ([]beerscli.Beer, error) 12 | // FetchByID filter all beers and get only the beer that match with given id 13 | FetchByID(id int) (beerscli.Beer, error) 14 | } 15 | 16 | type service struct { 17 | bR beerscli.BeerRepo 18 | } 19 | 20 | // NewService creates an adding service with the necessary dependencies 21 | func NewService(r beerscli.BeerRepo) Service { 22 | return &service{r} 23 | } 24 | 25 | func (s *service) FetchBeers() ([]beerscli.Beer, error) { 26 | return s.bR.GetBeers() 27 | } 28 | 29 | func (s *service) FetchByID(id int) (beerscli.Beer, error) { 30 | beers, err := s.FetchBeers() 31 | if err != nil { 32 | return beerscli.Beer{}, err 33 | } 34 | 35 | for _, beer := range beers { 36 | if beer.ProductID == id { 37 | return beer, nil 38 | } 39 | } 40 | 41 | return beerscli.Beer{}, errors.Errorf("Beer %d not found", id) 42 | } 43 | -------------------------------------------------------------------------------- /09-benchmarking/internal/fetching/service.go: -------------------------------------------------------------------------------- 1 | package fetching 2 | 3 | import ( 4 | beerscli "github.com/CodelyTV/golang-examples/09-benchmarking/internal" 5 | "github.com/pkg/errors" 6 | ) 7 | 8 | // Service provides beer fetching operations 9 | type Service interface { 10 | // FetchBeers fetch all beers from repository 11 | FetchBeers() ([]beerscli.Beer, error) 12 | // FetchByID filter all beers and get only the beer that match with given id 13 | FetchByID(id int) (beerscli.Beer, error) 14 | } 15 | 16 | type service struct { 17 | bR beerscli.BeerRepo 18 | } 19 | 20 | // NewService creates an adding service with the necessary dependencies 21 | func NewService(r beerscli.BeerRepo) Service { 22 | return &service{r} 23 | } 24 | 25 | func (s *service) FetchBeers() ([]beerscli.Beer, error) { 26 | return s.bR.GetBeers() 27 | } 28 | 29 | func (s *service) FetchByID(id int) (beerscli.Beer, error) { 30 | beers, err := s.FetchBeers() 31 | if err != nil { 32 | return beerscli.Beer{}, err 33 | } 34 | 35 | for _, beer := range beers { 36 | if beer.ProductID == id { 37 | return beer, nil 38 | } 39 | } 40 | 41 | return beerscli.Beer{}, errors.Errorf("Beer %d not found", id) 42 | } 43 | -------------------------------------------------------------------------------- /08-automated_tests/internal/fetching/service.go: -------------------------------------------------------------------------------- 1 | package fetching 2 | 3 | import ( 4 | beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" 5 | "github.com/pkg/errors" 6 | ) 7 | 8 | // Service provides beer fetching operations 9 | type Service interface { 10 | // FetchBeers fetch all beers from repository 11 | FetchBeers() ([]beerscli.Beer, error) 12 | // FetchByID filter all beers and get only the beer that match with given id 13 | FetchByID(id int) (beerscli.Beer, error) 14 | } 15 | 16 | type service struct { 17 | bR beerscli.BeerRepo 18 | } 19 | 20 | // NewService creates an adding service with the necessary dependencies 21 | func NewService(r beerscli.BeerRepo) Service { 22 | return &service{r} 23 | } 24 | 25 | func (s *service) FetchBeers() ([]beerscli.Beer, error) { 26 | return s.bR.GetBeers() 27 | } 28 | 29 | func (s *service) FetchByID(id int) (beerscli.Beer, error) { 30 | beers, err := s.FetchBeers() 31 | if err != nil { 32 | return beerscli.Beer{}, err 33 | } 34 | 35 | for _, beer := range beers { 36 | if beer.ProductID == id { 37 | return beer, nil 38 | } 39 | } 40 | 41 | return beerscli.Beer{}, errors.Errorf("Beer %d not found", id) 42 | } 43 | -------------------------------------------------------------------------------- /10-profiling/internal/storage/csv/repository.go: -------------------------------------------------------------------------------- 1 | package csv 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "strconv" 7 | "strings" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/10-profiling/internal" 10 | ) 11 | 12 | type repository struct { 13 | } 14 | 15 | // NewRepository initialize csv repository 16 | func NewRepository() beerscli.BeerRepo { 17 | return &repository{} 18 | } 19 | 20 | // GetBeers fetch beers data from csv 21 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 22 | f, _ := os.Open("10-profiling/data/beers.csv") 23 | reader := bufio.NewReader(f) 24 | 25 | var beers []beerscli.Beer 26 | 27 | for line := readLine(reader); line != nil; line = readLine(reader) { 28 | values := strings.Split(string(line), ",") 29 | 30 | productID, _ := strconv.Atoi(values[0]) 31 | 32 | beer := beerscli.NewBeer( 33 | productID, 34 | values[1], 35 | values[2], 36 | values[5], 37 | values[6], 38 | values[3], 39 | beerscli.NewBeerType(values[4]), 40 | ) 41 | 42 | beers = append(beers, beer) 43 | } 44 | 45 | return beers, nil 46 | } 47 | 48 | func readLine(reader *bufio.Reader) (line []byte) { 49 | line, _, _ = reader.ReadLine() 50 | return 51 | } 52 | -------------------------------------------------------------------------------- /05-parsing_http_response/internal/cli/beers.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | 7 | beerscli "github.com/CodelyTV/golang-examples/05-parsing_http_response/internal" 8 | "github.com/spf13/cobra" 9 | ) 10 | 11 | // CobraFn function definion of run cobra command 12 | type CobraFn func(cmd *cobra.Command, args []string) 13 | 14 | const idFlag = "id" 15 | 16 | // InitBeersCmd initialize beers command 17 | func InitBeersCmd(repository beerscli.BeerRepo) *cobra.Command { 18 | beersCmd := &cobra.Command{ 19 | Use: "beers", 20 | Short: "Print data about beers", 21 | Run: runBeersFn(repository), 22 | } 23 | 24 | beersCmd.Flags().StringP(idFlag, "i", "", "id of the beer") 25 | 26 | return beersCmd 27 | } 28 | 29 | func runBeersFn(repository beerscli.BeerRepo) CobraFn { 30 | return func(cmd *cobra.Command, args []string) { 31 | beers, _ := repository.GetBeers() 32 | 33 | id, _ := cmd.Flags().GetString(idFlag) 34 | 35 | if id != "" { 36 | i, _ := strconv.Atoi(id) 37 | for _, beer := range beers { 38 | if beer.ProductID == i { 39 | fmt.Println(beer) 40 | return 41 | } 42 | } 43 | } else { 44 | fmt.Println(beers) 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /09-benchmarking/internal/storage/csv/repository.go: -------------------------------------------------------------------------------- 1 | package csv 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "strconv" 7 | "strings" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/09-benchmarking/internal" 10 | ) 11 | 12 | type repository struct { 13 | } 14 | 15 | // NewRepository initialize csv repository 16 | func NewRepository() beerscli.BeerRepo { 17 | return &repository{} 18 | } 19 | 20 | // GetBeers fetch beers data from csv 21 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 22 | f, _ := os.Open("09-benchmarking/data/beers.csv") 23 | reader := bufio.NewReader(f) 24 | 25 | var beers []beerscli.Beer 26 | 27 | for line := readLine(reader); line != nil; line = readLine(reader) { 28 | values := strings.Split(string(line), ",") 29 | 30 | productID, _ := strconv.Atoi(values[0]) 31 | 32 | beer := beerscli.NewBeer( 33 | productID, 34 | values[1], 35 | values[2], 36 | values[5], 37 | values[6], 38 | values[3], 39 | beerscli.NewBeerType(values[4]), 40 | ) 41 | 42 | beers = append(beers, beer) 43 | } 44 | 45 | return beers, nil 46 | } 47 | 48 | func readLine(reader *bufio.Reader) (line []byte) { 49 | line, _, _ = reader.ReadLine() 50 | return 51 | } 52 | -------------------------------------------------------------------------------- /06-error_handling/internal/storage/csv/repository.go: -------------------------------------------------------------------------------- 1 | package csv 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "strconv" 7 | "strings" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/06-error_handling/internal" 10 | ) 11 | 12 | type repository struct { 13 | } 14 | 15 | // NewRepository initialize csv repository 16 | func NewRepository() beerscli.BeerRepo { 17 | return &repository{} 18 | } 19 | 20 | // GetBeers fetch beers data from csv 21 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 22 | f, _ := os.Open("06-error_handling/data/beers.csv") 23 | reader := bufio.NewReader(f) 24 | 25 | var beers []beerscli.Beer 26 | 27 | for line := readLine(reader); line != nil; line = readLine(reader) { 28 | values := strings.Split(string(line), ",") 29 | 30 | productID, _ := strconv.Atoi(values[0]) 31 | 32 | beer := beerscli.NewBeer( 33 | productID, 34 | values[1], 35 | values[2], 36 | values[5], 37 | values[6], 38 | values[3], 39 | beerscli.NewBeerType(values[4]), 40 | ) 41 | 42 | beers = append(beers, beer) 43 | } 44 | 45 | return beers, nil 46 | } 47 | 48 | func readLine(reader *bufio.Reader) (line []byte) { 49 | line, _, _ = reader.ReadLine() 50 | return 51 | } 52 | -------------------------------------------------------------------------------- /08-automated_tests/internal/storage/csv/repository.go: -------------------------------------------------------------------------------- 1 | package csv 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "strconv" 7 | "strings" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" 10 | ) 11 | 12 | type repository struct { 13 | } 14 | 15 | // NewRepository initialize csv repository 16 | func NewRepository() beerscli.BeerRepo { 17 | return &repository{} 18 | } 19 | 20 | // GetBeers fetch beers data from csv 21 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 22 | f, _ := os.Open("08-automated_tests/data/beers.csv") 23 | reader := bufio.NewReader(f) 24 | 25 | var beers []beerscli.Beer 26 | 27 | for line := readLine(reader); line != nil; line = readLine(reader) { 28 | values := strings.Split(string(line), ",") 29 | 30 | productID, _ := strconv.Atoi(values[0]) 31 | 32 | beer := beerscli.NewBeer( 33 | productID, 34 | values[1], 35 | values[2], 36 | values[5], 37 | values[6], 38 | values[3], 39 | beerscli.NewBeerType(values[4]), 40 | ) 41 | 42 | beers = append(beers, beer) 43 | } 44 | 45 | return beers, nil 46 | } 47 | 48 | func readLine(reader *bufio.Reader) (line []byte) { 49 | line, _, _ = reader.ReadLine() 50 | return 51 | } 52 | -------------------------------------------------------------------------------- /06-error_handling/internal/storage/ontario/repository.go: -------------------------------------------------------------------------------- 1 | package ontario 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/06-error_handling/internal" 10 | "github.com/pkg/errors" 11 | ) 12 | 13 | const ( 14 | productsEndpoint = "/products" 15 | ontarioURL = "http://ontariobeerapi.ca" 16 | ) 17 | 18 | type beerRepo struct { 19 | url string 20 | } 21 | 22 | // NewOntarioRepository fetch beers data from csv 23 | func NewOntarioRepository() beerscli.BeerRepo { 24 | return &beerRepo{url: ontarioURL} 25 | } 26 | 27 | func (b *beerRepo) GetBeers() (beers []beerscli.Beer, err error) { 28 | response, err := http.Get(fmt.Sprintf("%v%v", b.url, productsEndpoint)) 29 | if err != nil { 30 | return nil, errors.Wrapf(err, "Something happened when call the endpoint: %s", productsEndpoint) 31 | } 32 | 33 | contents, err := ioutil.ReadAll(response.Body) 34 | if err != nil { 35 | return nil, errors.Wrap(err, "Something happened when read the content") 36 | } 37 | 38 | err = json.Unmarshal(contents, &beers) 39 | if err != nil { 40 | return nil, errors.Wrap(err, "Something happened when unmarshal the content") 41 | } 42 | return 43 | } 44 | -------------------------------------------------------------------------------- /10-profiling/internal/cli/beers.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strconv" 7 | 8 | "github.com/CodelyTV/golang-examples/10-profiling/internal/fetching" 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | // CobraFn function definion of run cobra command 13 | type CobraFn func(cmd *cobra.Command, args []string) 14 | 15 | const idFlag = "id" 16 | 17 | // InitBeersCmd initialize beers command 18 | func InitBeersCmd(service fetching.Service) *cobra.Command { 19 | beersCmd := &cobra.Command{ 20 | Use: "beers", 21 | Short: "Print data about beers", 22 | Run: runBeersFn(service), 23 | } 24 | 25 | beersCmd.Flags().StringP(idFlag, "i", "", "id of the beer") 26 | 27 | return beersCmd 28 | } 29 | 30 | func runBeersFn(service fetching.Service) CobraFn { 31 | return func(cmd *cobra.Command, args []string) { 32 | 33 | id, _ := cmd.Flags().GetString(idFlag) 34 | if id != "" { 35 | i, _ := strconv.Atoi(id) 36 | beer, err := service.FetchByID(i) 37 | if err != nil { 38 | log.Fatal(err) 39 | } 40 | 41 | fmt.Println(beer) 42 | return 43 | } 44 | 45 | beers, err := service.FetchBeers() 46 | if err != nil { 47 | log.Fatal(err) 48 | } 49 | fmt.Println(beers) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /05-parsing_http_response/internal/storage/csv/repository.go: -------------------------------------------------------------------------------- 1 | package csv 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "strconv" 7 | "strings" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/05-parsing_http_response/internal" 10 | ) 11 | 12 | type repository struct { 13 | } 14 | 15 | // NewRepository initialize csv repository 16 | func NewRepository() beerscli.BeerRepo { 17 | return &repository{} 18 | } 19 | 20 | // GetBeers fetch beers data from csv 21 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 22 | f, _ := os.Open("05-parsing_http_response/data/beers.csv") 23 | reader := bufio.NewReader(f) 24 | 25 | var beers []beerscli.Beer 26 | 27 | for line := readLine(reader); line != nil; line = readLine(reader) { 28 | values := strings.Split(string(line), ",") 29 | 30 | productID, _ := strconv.Atoi(values[0]) 31 | 32 | beer := beerscli.NewBeer( 33 | productID, 34 | values[1], 35 | values[2], 36 | values[5], 37 | values[6], 38 | values[3], 39 | beerscli.NewBeerType(values[4]), 40 | ) 41 | 42 | beers = append(beers, beer) 43 | } 44 | 45 | return beers, nil 46 | } 47 | 48 | func readLine(reader *bufio.Reader) (line []byte) { 49 | line, _, _ = reader.ReadLine() 50 | return 51 | } 52 | -------------------------------------------------------------------------------- /09-benchmarking/internal/cli/beers.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strconv" 7 | 8 | "github.com/CodelyTV/golang-examples/09-benchmarking/internal/fetching" 9 | 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | // CobraFn function definion of run cobra command 14 | type CobraFn func(cmd *cobra.Command, args []string) 15 | 16 | const idFlag = "id" 17 | 18 | // InitBeersCmd initialize beers command 19 | func InitBeersCmd(service fetching.Service) *cobra.Command { 20 | beersCmd := &cobra.Command{ 21 | Use: "beers", 22 | Short: "Print data about beers", 23 | Run: runBeersFn(service), 24 | } 25 | 26 | beersCmd.Flags().StringP(idFlag, "i", "", "id of the beer") 27 | 28 | return beersCmd 29 | } 30 | 31 | func runBeersFn(service fetching.Service) CobraFn { 32 | return func(cmd *cobra.Command, args []string) { 33 | 34 | id, _ := cmd.Flags().GetString(idFlag) 35 | if id != "" { 36 | i, _ := strconv.Atoi(id) 37 | beer, err := service.FetchByID(i) 38 | if err != nil { 39 | log.Fatal(err) 40 | } 41 | 42 | fmt.Println(beer) 43 | return 44 | } 45 | 46 | beers, err := service.FetchBeers() 47 | if err != nil { 48 | log.Fatal(err) 49 | } 50 | fmt.Println(beers) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /07-behaviour_error_handling/internal/storage/csv/repository.go: -------------------------------------------------------------------------------- 1 | package csv 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "strconv" 7 | "strings" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/07-behaviour_error_handling/internal" 10 | ) 11 | 12 | type repository struct { 13 | } 14 | 15 | // NewRepository initialize csv repository 16 | func NewRepository() beerscli.BeerRepo { 17 | return &repository{} 18 | } 19 | 20 | // GetBeers fetch beers data from csv 21 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 22 | f, _ := os.Open("07-behaviour_error_handling/data/beers.csv") 23 | reader := bufio.NewReader(f) 24 | 25 | var beers []beerscli.Beer 26 | 27 | for line := readLine(reader); line != nil; line = readLine(reader) { 28 | values := strings.Split(string(line), ",") 29 | 30 | productID, _ := strconv.Atoi(values[0]) 31 | 32 | beer := beerscli.NewBeer( 33 | productID, 34 | values[1], 35 | values[2], 36 | values[5], 37 | values[6], 38 | values[3], 39 | beerscli.NewBeerType(values[4]), 40 | ) 41 | 42 | beers = append(beers, beer) 43 | } 44 | 45 | return beers, nil 46 | } 47 | 48 | func readLine(reader *bufio.Reader) (line []byte) { 49 | line, _, _ = reader.ReadLine() 50 | return 51 | } 52 | -------------------------------------------------------------------------------- /08-automated_tests/internal/cli/beers.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strconv" 7 | 8 | "github.com/CodelyTV/golang-examples/08-automated_tests/internal/fetching" 9 | 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | // CobraFn function definion of run cobra command 14 | type CobraFn func(cmd *cobra.Command, args []string) 15 | 16 | const idFlag = "id" 17 | 18 | // InitBeersCmd initialize beers command 19 | func InitBeersCmd(service fetching.Service) *cobra.Command { 20 | beersCmd := &cobra.Command{ 21 | Use: "beers", 22 | Short: "Print data about beers", 23 | Run: runBeersFn(service), 24 | } 25 | 26 | beersCmd.Flags().StringP(idFlag, "i", "", "id of the beer") 27 | 28 | return beersCmd 29 | } 30 | 31 | func runBeersFn(service fetching.Service) CobraFn { 32 | return func(cmd *cobra.Command, args []string) { 33 | 34 | id, _ := cmd.Flags().GetString(idFlag) 35 | if id != "" { 36 | i, _ := strconv.Atoi(id) 37 | beer, err := service.FetchByID(i) 38 | if err != nil { 39 | log.Fatal(err) 40 | } 41 | 42 | fmt.Println(beer) 43 | return 44 | } 45 | 46 | beers, err := service.FetchBeers() 47 | if err != nil { 48 | log.Fatal(err) 49 | } 50 | fmt.Println(beers) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/storage/csv/repository.go: -------------------------------------------------------------------------------- 1 | package csv 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "strconv" 7 | "strings" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal" 10 | ) 11 | 12 | type repository struct { 13 | } 14 | 15 | // NewRepository initialize csv repository 16 | func NewRepository() beerscli.BeerRepo { 17 | return &repository{} 18 | } 19 | 20 | // GetBeers fetch beers data from csv 21 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 22 | f, _ := os.Open("11-sharing_memory_concurrency/data/beers.csv") 23 | reader := bufio.NewReader(f) 24 | 25 | var beers []beerscli.Beer 26 | 27 | for line := readLine(reader); line != nil; line = readLine(reader) { 28 | values := strings.Split(string(line), ",") 29 | 30 | productID, _ := strconv.Atoi(values[0]) 31 | 32 | beer := beerscli.NewBeer( 33 | productID, 34 | values[1], 35 | values[2], 36 | values[5], 37 | values[6], 38 | values[3], 39 | beerscli.NewBeerType(values[4]), 40 | ) 41 | 42 | beers = append(beers, beer) 43 | } 44 | 45 | return beers, nil 46 | } 47 | 48 | func readLine(reader *bufio.Reader) (line []byte) { 49 | line, _, _ = reader.ReadLine() 50 | return 51 | } 52 | -------------------------------------------------------------------------------- /04-modeling_data/internal/storage/csv/repository.go: -------------------------------------------------------------------------------- 1 | package csv 2 | 3 | import ( 4 | "bufio" 5 | "os" 6 | "strconv" 7 | "strings" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/04-modeling_data/internal" 10 | ) 11 | 12 | type repository struct { 13 | } 14 | 15 | // NewRepository initialize csv repository 16 | func NewRepository() beerscli.BeerRepo { 17 | return &repository{} 18 | } 19 | 20 | // GetBeers fetch beers data from csv 21 | func (r *repository) GetBeers() ([]beerscli.Beer, error) { 22 | f, _ := os.Open("04-modeling_data/data/beers.csv") 23 | reader := bufio.NewReader(f) 24 | 25 | var beers []beerscli.Beer 26 | 27 | for line := readLine(reader); line != nil; line = readLine(reader) { 28 | values := strings.Split(string(line), ",") 29 | 30 | productID, _ := strconv.Atoi(values[0]) 31 | price, _ := strconv.ParseFloat(values[3], 64) 32 | 33 | beer := beerscli.NewBeer( 34 | productID, 35 | values[1], 36 | values[2], 37 | values[5], 38 | values[6], 39 | beerscli.NewBeerType(values[4]), 40 | price, 41 | ) 42 | 43 | beers = append(beers, beer) 44 | } 45 | 46 | return beers, nil 47 | } 48 | 49 | func readLine(reader *bufio.Reader) (line []byte) { 50 | line, _, _ = reader.ReadLine() 51 | return 52 | } 53 | -------------------------------------------------------------------------------- /06-error_handling/internal/cli/beers.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strconv" 7 | 8 | beerscli "github.com/CodelyTV/golang-examples/06-error_handling/internal" 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | // CobraFn function definion of run cobra command 13 | type CobraFn func(cmd *cobra.Command, args []string) 14 | 15 | const idFlag = "id" 16 | 17 | // InitBeersCmd initialize beers command 18 | func InitBeersCmd(repository beerscli.BeerRepo) *cobra.Command { 19 | beersCmd := &cobra.Command{ 20 | Use: "beers", 21 | Short: "Print data about beers", 22 | Run: runBeersFn(repository), 23 | } 24 | 25 | beersCmd.Flags().StringP(idFlag, "i", "", "id of the beer") 26 | 27 | return beersCmd 28 | } 29 | 30 | func runBeersFn(repository beerscli.BeerRepo) CobraFn { 31 | return func(cmd *cobra.Command, args []string) { 32 | beers, err := repository.GetBeers() 33 | if err != nil { 34 | log.Fatal(err) 35 | } 36 | 37 | id, _ := cmd.Flags().GetString(idFlag) 38 | 39 | if id != "" { 40 | i, _ := strconv.Atoi(id) 41 | for _, beer := range beers { 42 | if beer.ProductID == i { 43 | fmt.Println(beer) 44 | return 45 | } 46 | } 47 | } else { 48 | fmt.Println(beers) 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/cli/beers.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strconv" 7 | 8 | "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal/fetching" 9 | "github.com/spf13/cobra" 10 | ) 11 | 12 | // CobraFn function definion of run cobra command 13 | type CobraFn func(cmd *cobra.Command, args []string) 14 | 15 | const idFlag = "id" 16 | 17 | // InitBeersCmd initialize beers command 18 | func InitBeersCmd(service fetching.Service) *cobra.Command { 19 | beersCmd := &cobra.Command{ 20 | Use: "beers", 21 | Short: "Print data about beers", 22 | Run: runBeersFn(service), 23 | } 24 | 25 | beersCmd.Flags().StringP(idFlag, "i", "", "id of the beer") 26 | 27 | return beersCmd 28 | } 29 | 30 | func runBeersFn(service fetching.Service) CobraFn { 31 | return func(cmd *cobra.Command, args []string) { 32 | 33 | id, _ := cmd.Flags().GetString(idFlag) 34 | if id != "" { 35 | i, _ := strconv.Atoi(id) 36 | beer, err := service.FetchByID(i) 37 | if err != nil { 38 | log.Fatal(err) 39 | } 40 | 41 | fmt.Println(beer) 42 | return 43 | } 44 | 45 | beers, err := service.FetchBeers() 46 | if err != nil { 47 | log.Fatal(err) 48 | } 49 | fmt.Println(beers) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /10-profiling/internal/storage/ontario/repository.go: -------------------------------------------------------------------------------- 1 | package ontario 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/10-profiling/internal" 10 | "github.com/CodelyTV/golang-examples/10-profiling/internal/errors" 11 | ) 12 | 13 | const ( 14 | productsEndpoint = "/products" 15 | ontarioURL = "http://localhost:3000" 16 | ) 17 | 18 | type beerRepo struct { 19 | url string 20 | } 21 | 22 | // NewOntarioRepository fetch beers data from csv 23 | func NewOntarioRepository() beerscli.BeerRepo { 24 | return &beerRepo{url: ontarioURL} 25 | } 26 | 27 | func (b *beerRepo) GetBeers() (beers []beerscli.Beer, err error) { 28 | response, err := http.Get(fmt.Sprintf("%v%v", b.url, productsEndpoint)) 29 | if err != nil { 30 | return nil, errors.WrapDataUnreacheable(err, "error getting response to %s", productsEndpoint) 31 | } 32 | 33 | contents, err := ioutil.ReadAll(response.Body) 34 | if err != nil { 35 | return nil, errors.WrapDataUnreacheable(err, "error reading the response from %s", productsEndpoint) 36 | } 37 | 38 | err = json.Unmarshal(contents, &beers) 39 | if err != nil { 40 | return nil, errors.WrapDataUnreacheable(err, "can't parsing response into beers") 41 | } 42 | return 43 | } 44 | -------------------------------------------------------------------------------- /08-automated_tests/internal/storage/ontario/repository.go: -------------------------------------------------------------------------------- 1 | package ontario 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" 10 | "github.com/CodelyTV/golang-examples/08-automated_tests/internal/errors" 11 | ) 12 | 13 | const ( 14 | productsEndpoint = "/products" 15 | ontarioURL = "http://ontariobeerapi.ca" 16 | ) 17 | 18 | type beerRepo struct { 19 | url string 20 | } 21 | 22 | // NewOntarioRepository fetch beers data from csv 23 | func NewOntarioRepository() beerscli.BeerRepo { 24 | return &beerRepo{url: ontarioURL} 25 | } 26 | 27 | func (b *beerRepo) GetBeers() (beers []beerscli.Beer, err error) { 28 | response, err := http.Get(fmt.Sprintf("%v%v", b.url, productsEndpoint)) 29 | if err != nil { 30 | return nil, errors.WrapDataUnreacheable(err, "error getting response to %s", productsEndpoint) 31 | } 32 | 33 | contents, err := ioutil.ReadAll(response.Body) 34 | if err != nil { 35 | return nil, errors.WrapDataUnreacheable(err, "error reading the response from %s", productsEndpoint) 36 | } 37 | 38 | err = json.Unmarshal(contents, &beers) 39 | if err != nil { 40 | return nil, errors.WrapDataUnreacheable(err, "can't parsing response into beers") 41 | } 42 | return 43 | } 44 | -------------------------------------------------------------------------------- /07-behaviour_error_handling/internal/storage/ontario/repository.go: -------------------------------------------------------------------------------- 1 | package ontario 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/07-behaviour_error_handling/internal" 10 | "github.com/CodelyTV/golang-examples/07-behaviour_error_handling/internal/errors" 11 | ) 12 | 13 | const ( 14 | productsEndpoint = "/products" 15 | ontarioURL = "http://ontariobeerapi.ca" 16 | ) 17 | 18 | type beerRepo struct { 19 | url string 20 | } 21 | 22 | // NewOntarioRepository fetch beers data from csv 23 | func NewOntarioRepository() beerscli.BeerRepo { 24 | return &beerRepo{url: ontarioURL} 25 | } 26 | 27 | func (b *beerRepo) GetBeers() (beers []beerscli.Beer, err error) { 28 | response, err := http.Get(fmt.Sprintf("%v%v", b.url, productsEndpoint)) 29 | if err != nil { 30 | return nil, errors.WrapDataUnreacheable(err, "error getting response to %s", productsEndpoint) 31 | } 32 | 33 | contents, err := ioutil.ReadAll(response.Body) 34 | if err != nil { 35 | return nil, errors.WrapDataUnreacheable(err, "error reading the response from %s", productsEndpoint) 36 | } 37 | 38 | err = json.Unmarshal(contents, &beers) 39 | if err != nil { 40 | return nil, errors.WrapDataUnreacheable(err, "can't parsing response into beers") 41 | } 42 | return 43 | } 44 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/storage/ontario/repository.go: -------------------------------------------------------------------------------- 1 | package ontario 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal" 10 | "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal/errors" 11 | ) 12 | 13 | const ( 14 | productsEndpoint = "/products" 15 | ontarioURL = "http://localhost:3000" 16 | ) 17 | 18 | type beerRepo struct { 19 | url string 20 | } 21 | 22 | // NewOntarioRepository fetch beers data from csv 23 | func NewOntarioRepository() beerscli.BeerRepo { 24 | return &beerRepo{url: ontarioURL} 25 | } 26 | 27 | func (b *beerRepo) GetBeers() (beers []beerscli.Beer, err error) { 28 | response, err := http.Get(fmt.Sprintf("%v%v", b.url, productsEndpoint)) 29 | if err != nil { 30 | return nil, errors.WrapDataUnreacheable(err, "error getting response to %s", productsEndpoint) 31 | } 32 | 33 | contents, err := ioutil.ReadAll(response.Body) 34 | if err != nil { 35 | return nil, errors.WrapDataUnreacheable(err, "error reading the response from %s", productsEndpoint) 36 | } 37 | 38 | err = json.Unmarshal(contents, &beers) 39 | if err != nil { 40 | return nil, errors.WrapDataUnreacheable(err, "can't parsing response into beers") 41 | } 42 | return 43 | } 44 | -------------------------------------------------------------------------------- /10-profiling/cmd/beers-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | beerscli "github.com/CodelyTV/golang-examples/10-profiling/internal" 7 | "github.com/CodelyTV/golang-examples/10-profiling/internal/cli" 8 | "github.com/CodelyTV/golang-examples/10-profiling/internal/fetching" 9 | "github.com/CodelyTV/golang-examples/10-profiling/internal/storage/csv" 10 | "github.com/CodelyTV/golang-examples/10-profiling/internal/storage/ontario" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | func main() { 15 | // CPU profiling code starts here 16 | //f, _ := os.Create("beers.cpu.prof") 17 | //defer f.Close() 18 | //pprof.StartCPUProfile(f) 19 | //defer pprof.StopCPUProfile() 20 | // CPU profiling code ends here 21 | 22 | csvData := flag.Bool("csv", false, "load data from csv") 23 | flag.Parse() 24 | var repo beerscli.BeerRepo 25 | repo = csv.NewRepository() 26 | 27 | if !*csvData { 28 | repo = ontario.NewOntarioRepository() 29 | } 30 | 31 | fetchingService := fetching.NewService(repo) 32 | 33 | rootCmd := &cobra.Command{Use: "beers-cli"} 34 | rootCmd.AddCommand(cli.InitBeersCmd(fetchingService)) 35 | rootCmd.Execute() 36 | 37 | // Memory profiling code starts here 38 | //f2, _ := os.Create("beers.mem.prof") 39 | //defer f2.Close() 40 | //pprof.WriteHeapProfile(f2) 41 | // Memory profiling code ends here 42 | } 43 | -------------------------------------------------------------------------------- /07-behaviour_error_handling/internal/cli/beers.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strconv" 7 | 8 | "github.com/CodelyTV/golang-examples/07-behaviour_error_handling/internal/errors" 9 | 10 | beerscli "github.com/CodelyTV/golang-examples/07-behaviour_error_handling/internal" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | // CobraFn function definion of run cobra command 15 | type CobraFn func(cmd *cobra.Command, args []string) 16 | 17 | const idFlag = "id" 18 | 19 | // InitBeersCmd initialize beers command 20 | func InitBeersCmd(repository beerscli.BeerRepo) *cobra.Command { 21 | beersCmd := &cobra.Command{ 22 | Use: "beers", 23 | Short: "Print data about beers", 24 | Run: runBeersFn(repository), 25 | } 26 | 27 | beersCmd.Flags().StringP(idFlag, "i", "", "id of the beer") 28 | 29 | return beersCmd 30 | } 31 | 32 | func runBeersFn(repository beerscli.BeerRepo) CobraFn { 33 | return func(cmd *cobra.Command, args []string) { 34 | beers, err := repository.GetBeers() 35 | if errors.IsDataUnreacheable(err) { 36 | log.Fatal(err) 37 | } 38 | 39 | id, _ := cmd.Flags().GetString(idFlag) 40 | 41 | if id != "" { 42 | i, _ := strconv.Atoi(id) 43 | for _, beer := range beers { 44 | if beer.ProductID == i { 45 | fmt.Println(beer) 46 | return 47 | } 48 | } 49 | } else { 50 | fmt.Println(beers) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /03-reading_files/internal/cli/beers.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "strconv" 8 | "strings" 9 | 10 | "github.com/spf13/cobra" 11 | ) 12 | 13 | // CobraFn function definion of run cobra command 14 | type CobraFn func(cmd *cobra.Command, args []string) 15 | 16 | const idFlag = "id" 17 | 18 | // InitBeersCmd initialize beers command 19 | func InitBeersCmd() *cobra.Command { 20 | beersCmd := &cobra.Command{ 21 | Use: "beers", 22 | Short: "Print data about beers", 23 | Run: runBeersFn(), 24 | } 25 | 26 | beersCmd.Flags().StringP(idFlag, "i", "", "id of the beer") 27 | 28 | return beersCmd 29 | } 30 | 31 | func runBeersFn() CobraFn { 32 | return func(cmd *cobra.Command, args []string) { 33 | 34 | f, _ := os.Open("03-reading_files/data/beers.csv") 35 | reader := bufio.NewReader(f) 36 | 37 | var beers = make(map[int]string) 38 | 39 | for line := readLine(reader); line != nil; line = readLine(reader) { 40 | values := strings.Split(string(line), ",") 41 | 42 | productID, _ := strconv.Atoi(values[0]) 43 | beers[productID] = values[1] 44 | } 45 | 46 | id, _ := cmd.Flags().GetString(idFlag) 47 | 48 | if id != "" { 49 | i, _ := strconv.Atoi(id) 50 | fmt.Println(beers[i]) 51 | } else { 52 | fmt.Println(beers) 53 | } 54 | } 55 | } 56 | 57 | func readLine(reader *bufio.Reader) (line []byte) { 58 | line, _, _ = reader.ReadLine() 59 | return 60 | } 61 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/cmd/beers-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | 6 | beerscli "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal" 7 | "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal/cli" 8 | "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal/fetching" 9 | "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal/storage/csv" 10 | "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal/storage/ontario" 11 | "github.com/spf13/cobra" 12 | ) 13 | 14 | func main() { 15 | // CPU profiling code starts here 16 | //f, _ := os.Create("beers.cpu.prof") 17 | //defer f.Close() 18 | //pprof.StartCPUProfile(f) 19 | //defer pprof.StopCPUProfile() 20 | // CPU profiling code ends here 21 | 22 | csvData := flag.Bool("csv", false, "load data from csv") 23 | flag.Parse() 24 | var repo beerscli.BeerRepo 25 | repo = csv.NewRepository() 26 | 27 | if !*csvData { 28 | repo = ontario.NewOntarioRepository() 29 | } 30 | 31 | fetchingService := fetching.NewService(repo) 32 | 33 | rootCmd := &cobra.Command{Use: "beers-cli"} 34 | rootCmd.AddCommand(cli.InitBeersCmd(fetchingService)) 35 | rootCmd.Execute() 36 | 37 | // Memory profiling code starts here 38 | //f2, _ := os.Create("beers.mem.prof") 39 | //defer f2.Close() 40 | //pprof.WriteHeapProfile(f2) 41 | // Memory profiling code ends here 42 | } 43 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodelyTV and Friends of Go Present: Go Command Line Tool 2 | 3 | 4 | 5 | 6 | Project showing up how you could implement a entire command line application with **GO**. 7 | 8 | With this project you will be capable of implementing an application with **Go**. For this project you don't need previous experience on the language, but you do need a minimal background as a developer. 9 | 10 | We will explain all the features that go with it including the famous `goroutines`. 11 | 12 | ## Contents 13 | 14 | **Lesson 1.** Go Flags: introduction to "flags" package. 15 | 16 | **Lesson 2.** Cobra: refactor from "flags" package to Cobra library. 17 | 18 | **Lesson 3.** Reading files: retrieving beers from file. 19 | 20 | **Lesson 4.** Modeling data: modeling our beers (structs, defined types, etc). 21 | 22 | 23 | ## Environment setup 24 | 25 | See the environment setup instructions below. 26 | 27 | ### Requirements 28 | 29 | To compile & run the source code of this project you just need to have [Go](https://golang.org/) properly installed. 30 | 31 | ### Installation 32 | 33 | Binary distributions of Go are [available](https://golang.org/dl/) for Linux, macOS, Windows and more. 34 | 35 | Otherwise you can [download](https://dl.google.com/go/go1.12.5.src.tar.gz) the source code and compile it for your platform. 36 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/fetching/service.go: -------------------------------------------------------------------------------- 1 | package fetching 2 | 3 | import ( 4 | "math" 5 | "sync" 6 | 7 | beerscli "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal" 8 | ) 9 | 10 | // Service provides beer fetching operations 11 | type Service interface { 12 | // FetchBeers fetch all beers from repository 13 | FetchBeers() ([]beerscli.Beer, error) 14 | // FetchByID filter all beers and get only the beer that match with given id 15 | FetchByID(id int) (beerscli.Beer, error) 16 | } 17 | 18 | type service struct { 19 | bR beerscli.BeerRepo 20 | } 21 | 22 | // NewService creates an adding service with the necessary dependencies 23 | func NewService(r beerscli.BeerRepo) Service { 24 | return &service{r} 25 | } 26 | 27 | func (s *service) FetchBeers() ([]beerscli.Beer, error) { 28 | return s.bR.GetBeers() 29 | } 30 | 31 | func (s *service) FetchByID(id int) (beerscli.Beer, error) { 32 | beers, err := s.FetchBeers() 33 | if err != nil { 34 | return beerscli.Beer{}, err 35 | } 36 | 37 | beersPerRoutine := 10 38 | numRoutines := numOfRoutines(len(beers), beersPerRoutine) 39 | 40 | wg := &sync.WaitGroup{} 41 | wg.Add(numRoutines) 42 | 43 | var b beerscli.Beer 44 | 45 | for i := 0; i < numRoutines; i++ { 46 | go func(id, begin, end int, beers []beerscli.Beer, b *beerscli.Beer, wg *sync.WaitGroup) { 47 | for i := begin; i <= end; i++ { 48 | if beers[i].ProductID == id { 49 | *b = beers[i] 50 | } 51 | } 52 | wg.Done() 53 | }(id, i, i+beersPerRoutine, beers, &b, wg) 54 | } 55 | 56 | wg.Wait() 57 | 58 | return b, nil 59 | } 60 | 61 | func numOfRoutines(numOfBeers, beersPerRoutine int) int { 62 | return int(math.Ceil(float64(numOfBeers) / float64(beersPerRoutine))) 63 | } 64 | -------------------------------------------------------------------------------- /04-modeling_data/internal/beer.go: -------------------------------------------------------------------------------- 1 | package beerscli 2 | 3 | // Beer representation of beer into data struct 4 | type Beer struct { 5 | ProductID int 6 | Name string 7 | Price float64 8 | Category string 9 | Type *BeerType 10 | Brewer string 11 | Country string 12 | } 13 | 14 | type BeerType int 15 | 16 | const ( 17 | Unknown BeerType = iota 18 | Lager 19 | Malt 20 | Ale 21 | FlavouredMalt 22 | Stout 23 | Porter 24 | NonAlcoholic 25 | ) 26 | 27 | func (t BeerType) String() string { 28 | return toString[t] 29 | } 30 | 31 | // NewBeerType initialize a type from enum beerTypes 32 | func NewBeerType(t string) *BeerType { 33 | beerType := toID[t] 34 | return &beerType 35 | } 36 | 37 | var toString = map[BeerType]string{ 38 | Lager: "Lager", 39 | Malt: "Malt", 40 | Ale: "Ale", 41 | FlavouredMalt: "Flavoured Malt", 42 | Stout: "Stout", 43 | Porter: "Stout", 44 | NonAlcoholic: "Non-Alcoholic", 45 | Unknown: "unknown", 46 | } 47 | 48 | var toID = map[string]BeerType{ 49 | "Lager": Lager, 50 | "Malt": Malt, 51 | "Ale": Ale, 52 | "Flavoured Malt": FlavouredMalt, 53 | "Stout": Stout, 54 | "Porter": Porter, 55 | "Non-Alcoholic": NonAlcoholic, 56 | "unknown": Unknown, 57 | } 58 | 59 | // BeerRepo definiton of methods to access a data beer 60 | type BeerRepo interface { 61 | GetBeers() ([]Beer, error) 62 | } 63 | 64 | // NewBeer initialize struct beer 65 | func NewBeer(productID int, name, category, brewer, country string, beerType *BeerType, price float64) (b Beer) { 66 | b = Beer{ 67 | ProductID: productID, 68 | Name: name, 69 | Category: category, 70 | Type: beerType, 71 | Brewer: brewer, 72 | Country: country, 73 | Price: price, 74 | } 75 | return 76 | } 77 | -------------------------------------------------------------------------------- /09-benchmarking/internal/storage/ontario/repository.go: -------------------------------------------------------------------------------- 1 | package ontario 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/09-benchmarking/internal" 10 | "github.com/CodelyTV/golang-examples/09-benchmarking/internal/errors" 11 | jsoniter "github.com/json-iterator/go" 12 | ) 13 | 14 | const ( 15 | productsEndpoint = "/products" 16 | ontarioURL = "http://localhost:3000" 17 | ) 18 | 19 | type beerRepo struct { 20 | url string 21 | } 22 | 23 | // NewOntarioRepository fetch beers data from csv 24 | func NewOntarioRepository() beerscli.BeerRepo { 25 | return &beerRepo{url: ontarioURL} 26 | } 27 | 28 | func (b *beerRepo) GetBeers() (beers []beerscli.Beer, err error) { 29 | response, err := http.Get(fmt.Sprintf("%v%v", b.url, productsEndpoint)) 30 | if err != nil { 31 | return nil, errors.WrapDataUnreacheable(err, "error getting response to %s", productsEndpoint) 32 | } 33 | 34 | contents, err := ioutil.ReadAll(response.Body) 35 | if err != nil { 36 | return nil, errors.WrapDataUnreacheable(err, "error reading the response from %s", productsEndpoint) 37 | } 38 | 39 | err = b.betterUnmarshal(contents, &beers) 40 | if err != nil { 41 | return nil, errors.WrapDataUnreacheable(err, "can't parsing response into beers") 42 | } 43 | return 44 | } 45 | 46 | func (b *beerRepo) standardUnmarshal(data []byte, beers *[]beerscli.Beer) error { 47 | err := json.Unmarshal(data, &beers) 48 | if err != nil { 49 | return errors.WrapDataUnreacheable(err, "can't parsing response into beers") 50 | } 51 | return nil 52 | } 53 | 54 | func (b *beerRepo) betterUnmarshal(data []byte, beers *[]beerscli.Beer) error { 55 | var js = jsoniter.ConfigCompatibleWithStandardLibrary 56 | 57 | err := js.Unmarshal(data, &beers) 58 | if err != nil { 59 | return errors.WrapDataUnreacheable(err, "can't parsing response into beers") 60 | } 61 | 62 | return nil 63 | } 64 | -------------------------------------------------------------------------------- /10-profiling/internal/fetching/service_test.go: -------------------------------------------------------------------------------- 1 | package fetching 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | beerscli "github.com/CodelyTV/golang-examples/10-profiling/internal" 8 | "github.com/CodelyTV/golang-examples/10-profiling/internal/storage/mock" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestFetchByID(t *testing.T) { 13 | 14 | tests := map[string]struct { 15 | repo beerscli.BeerRepo 16 | input int 17 | want int 18 | err error 19 | }{ 20 | "valid beer": {repo: buildMockBeers(), input: 127, want: 127, err: nil}, 21 | "not found beer": {repo: buildMockBeers(), input: 99999, err: errors.New("error")}, 22 | "error with repository": {repo: buildMockError(), err: errors.New("error")}, 23 | } 24 | 25 | for name, tc := range tests { 26 | t.Run(name, func(t *testing.T) { 27 | service := NewService(tc.repo) 28 | 29 | b, err := service.FetchByID(tc.input) 30 | 31 | if tc.err != nil { 32 | assert.Error(t, err) 33 | } 34 | 35 | if tc.err == nil { 36 | assert.Nil(t, err) 37 | } 38 | 39 | assert.Equal(t, tc.want, b.ProductID) 40 | }) 41 | } 42 | } 43 | 44 | func buildMockBeers() beerscli.BeerRepo { 45 | mockedRepo := &mock.BeerRepoMock{ 46 | GetBeersFunc: func() ([]beerscli.Beer, error) { 47 | return []beerscli.Beer{ 48 | beerscli.NewBeer( 49 | 127, 50 | "Mad Jack Mixer", 51 | "Domestic Specialty", 52 | "Molson", 53 | "Canada", 54 | "23.95", 55 | beerscli.NewBeerType("Lager"), 56 | ), 57 | beerscli.NewBeer( 58 | 8520130, 59 | "Grolsch 0.0", 60 | "Non-Alcoholic Beer", 61 | "Grolsch Export B.V.", 62 | "Canada", 63 | "49.50", 64 | beerscli.NewBeerType("Non-Alcoholic Beer"), 65 | ), 66 | }, nil 67 | }, 68 | } 69 | 70 | return mockedRepo 71 | } 72 | 73 | func buildMockError() beerscli.BeerRepo { 74 | mockedRepo := &mock.BeerRepoMock{ 75 | GetBeersFunc: func() ([]beerscli.Beer, error) { 76 | return []beerscli.Beer{}, errors.New("error") 77 | }, 78 | } 79 | 80 | return mockedRepo 81 | } 82 | -------------------------------------------------------------------------------- /09-benchmarking/internal/fetching/service_test.go: -------------------------------------------------------------------------------- 1 | package fetching 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | beerscli "github.com/CodelyTV/golang-examples/09-benchmarking/internal" 8 | "github.com/CodelyTV/golang-examples/09-benchmarking/internal/storage/mock" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestFetchByID(t *testing.T) { 14 | 15 | tests := map[string]struct { 16 | repo beerscli.BeerRepo 17 | input int 18 | want int 19 | err error 20 | }{ 21 | "valid beer": {repo: buildMockBeers(), input: 127, want: 127, err: nil}, 22 | "not found beer": {repo: buildMockBeers(), input: 99999, err: errors.New("error")}, 23 | "error with repository": {repo: buildMockError(), err: errors.New("error")}, 24 | } 25 | 26 | for name, tc := range tests { 27 | t.Run(name, func(t *testing.T) { 28 | service := NewService(tc.repo) 29 | 30 | b, err := service.FetchByID(tc.input) 31 | 32 | if tc.err != nil { 33 | assert.Error(t, err) 34 | } 35 | 36 | if tc.err == nil { 37 | assert.Nil(t, err) 38 | } 39 | 40 | assert.Equal(t, tc.want, b.ProductID) 41 | }) 42 | } 43 | } 44 | 45 | func buildMockBeers() beerscli.BeerRepo { 46 | mockedRepo := &mock.BeerRepoMock{ 47 | GetBeersFunc: func() ([]beerscli.Beer, error) { 48 | return []beerscli.Beer{ 49 | beerscli.NewBeer( 50 | 127, 51 | "Mad Jack Mixer", 52 | "Domestic Specialty", 53 | "Molson", 54 | "Canada", 55 | "23.95", 56 | beerscli.NewBeerType("Lager"), 57 | ), 58 | beerscli.NewBeer( 59 | 8520130, 60 | "Grolsch 0.0", 61 | "Non-Alcoholic Beer", 62 | "Grolsch Export B.V.", 63 | "Canada", 64 | "49.50", 65 | beerscli.NewBeerType("Non-Alcoholic Beer"), 66 | ), 67 | }, nil 68 | }, 69 | } 70 | 71 | return mockedRepo 72 | } 73 | 74 | func buildMockError() beerscli.BeerRepo { 75 | mockedRepo := &mock.BeerRepoMock{ 76 | GetBeersFunc: func() ([]beerscli.Beer, error) { 77 | return []beerscli.Beer{}, errors.New("error") 78 | }, 79 | } 80 | 81 | return mockedRepo 82 | } 83 | -------------------------------------------------------------------------------- /08-automated_tests/internal/fetching/service_test.go: -------------------------------------------------------------------------------- 1 | package fetching 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" 8 | "github.com/CodelyTV/golang-examples/08-automated_tests/internal/storage/mock" 9 | 10 | "github.com/stretchr/testify/assert" 11 | ) 12 | 13 | func TestFetchByID(t *testing.T) { 14 | 15 | tests := map[string]struct { 16 | repo beerscli.BeerRepo 17 | input int 18 | want int 19 | err error 20 | }{ 21 | "valid beer": {repo: buildMockBeers(), input: 127, want: 127, err: nil}, 22 | "not found beer": {repo: buildMockBeers(), input: 99999, err: errors.New("error")}, 23 | "error with repository": {repo: buildMockError(), err: errors.New("error")}, 24 | } 25 | 26 | for name, tc := range tests { 27 | t.Run(name, func(t *testing.T) { 28 | service := NewService(tc.repo) 29 | 30 | b, err := service.FetchByID(tc.input) 31 | 32 | if tc.err != nil { 33 | assert.Error(t, err) 34 | } 35 | 36 | if tc.err == nil { 37 | assert.Nil(t, err) 38 | } 39 | 40 | assert.Equal(t, tc.want, b.ProductID) 41 | }) 42 | } 43 | } 44 | 45 | func buildMockBeers() beerscli.BeerRepo { 46 | mockedRepo := &mock.BeerRepoMock{ 47 | GetBeersFunc: func() ([]beerscli.Beer, error) { 48 | return []beerscli.Beer{ 49 | beerscli.NewBeer( 50 | 127, 51 | "Mad Jack Mixer", 52 | "Domestic Specialty", 53 | "Molson", 54 | "Canada", 55 | "23.95", 56 | beerscli.NewBeerType("Lager"), 57 | ), 58 | beerscli.NewBeer( 59 | 8520130, 60 | "Grolsch 0.0", 61 | "Non-Alcoholic Beer", 62 | "Grolsch Export B.V.", 63 | "Canada", 64 | "49.50", 65 | beerscli.NewBeerType("Non-Alcoholic Beer"), 66 | ), 67 | }, nil 68 | }, 69 | } 70 | 71 | return mockedRepo 72 | } 73 | 74 | func buildMockError() beerscli.BeerRepo { 75 | mockedRepo := &mock.BeerRepoMock{ 76 | GetBeersFunc: func() ([]beerscli.Beer, error) { 77 | return []beerscli.Beer{}, errors.New("error") 78 | }, 79 | } 80 | 81 | return mockedRepo 82 | } 83 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/fetching/service_test.go: -------------------------------------------------------------------------------- 1 | package fetching 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | 7 | beerscli "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal" 8 | "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal/storage/mock" 9 | "github.com/stretchr/testify/assert" 10 | ) 11 | 12 | func TestFetchByID(t *testing.T) { 13 | 14 | tests := map[string]struct { 15 | repo beerscli.BeerRepo 16 | input int 17 | want int 18 | err error 19 | }{ 20 | "valid beer": {repo: buildMockBeers(), input: 127, want: 127, err: nil}, 21 | "not found beer": {repo: buildMockBeers(), input: 99999, err: errors.New("error")}, 22 | "error with repository": {repo: buildMockError(), err: errors.New("error")}, 23 | } 24 | 25 | for name, tc := range tests { 26 | t.Run(name, func(t *testing.T) { 27 | service := NewService(tc.repo) 28 | 29 | b, err := service.FetchByID(tc.input) 30 | 31 | if tc.err != nil { 32 | assert.Error(t, err) 33 | } 34 | 35 | if tc.err == nil { 36 | assert.Nil(t, err) 37 | } 38 | 39 | assert.Equal(t, tc.want, b.ProductID) 40 | }) 41 | } 42 | } 43 | 44 | func buildMockBeers() beerscli.BeerRepo { 45 | mockedRepo := &mock.BeerRepoMock{ 46 | GetBeersFunc: func() ([]beerscli.Beer, error) { 47 | return []beerscli.Beer{ 48 | beerscli.NewBeer( 49 | 127, 50 | "Mad Jack Mixer", 51 | "Domestic Specialty", 52 | "Molson", 53 | "Canada", 54 | "23.95", 55 | beerscli.NewBeerType("Lager"), 56 | ), 57 | beerscli.NewBeer( 58 | 8520130, 59 | "Grolsch 0.0", 60 | "Non-Alcoholic Beer", 61 | "Grolsch Export B.V.", 62 | "Canada", 63 | "49.50", 64 | beerscli.NewBeerType("Non-Alcoholic Beer"), 65 | ), 66 | }, nil 67 | }, 68 | } 69 | 70 | return mockedRepo 71 | } 72 | 73 | func buildMockError() beerscli.BeerRepo { 74 | mockedRepo := &mock.BeerRepoMock{ 75 | GetBeersFunc: func() ([]beerscli.Beer, error) { 76 | return []beerscli.Beer{}, errors.New("error") 77 | }, 78 | } 79 | 80 | return mockedRepo 81 | } 82 | -------------------------------------------------------------------------------- /10-profiling/internal/mock/repository.go: -------------------------------------------------------------------------------- 1 | // Code generated by moq; DO NOT EDIT. 2 | // github.com/matryer/moq 3 | 4 | package mock 5 | 6 | import ( 7 | "sync" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/10-profiling/internal" 10 | ) 11 | 12 | var ( 13 | lockBeerRepoMockGetBeers sync.RWMutex 14 | ) 15 | 16 | // Ensure, that BeerRepoMock does implement BeerRepo. 17 | // If this is not the case, regenerate this file with moq. 18 | var _ beerscli.BeerRepo = &BeerRepoMock{} 19 | 20 | // BeerRepoMock is a mock implementation of BeerRepo. 21 | // 22 | // func TestSomethingThatUsesBeerRepo(t *testing.T) { 23 | // 24 | // // make and configure a mocked BeerRepo 25 | // mockedBeerRepo := &BeerRepoMock{ 26 | // GetBeersFunc: func() ([]beerscli.Beer, error) { 27 | // panic("mock out the GetBeers method") 28 | // }, 29 | // } 30 | // 31 | // // use mockedBeerRepo in code that requires BeerRepo 32 | // // and then make assertions. 33 | // 34 | // } 35 | type BeerRepoMock struct { 36 | // GetBeersFunc mocks the GetBeers method. 37 | GetBeersFunc func() ([]beerscli.Beer, error) 38 | 39 | // calls tracks calls to the methods. 40 | calls struct { 41 | // GetBeers holds details about calls to the GetBeers method. 42 | GetBeers []struct { 43 | } 44 | } 45 | } 46 | 47 | // GetBeers calls GetBeersFunc. 48 | func (mock *BeerRepoMock) GetBeers() ([]beerscli.Beer, error) { 49 | if mock.GetBeersFunc == nil { 50 | panic("BeerRepoMock.GetBeersFunc: method is nil but BeerRepo.GetBeers was just called") 51 | } 52 | callInfo := struct { 53 | }{} 54 | lockBeerRepoMockGetBeers.Lock() 55 | mock.calls.GetBeers = append(mock.calls.GetBeers, callInfo) 56 | lockBeerRepoMockGetBeers.Unlock() 57 | return mock.GetBeersFunc() 58 | } 59 | 60 | // GetBeersCalls gets all the calls that were made to GetBeers. 61 | // Check the length with: 62 | // len(mockedBeerRepo.GetBeersCalls()) 63 | func (mock *BeerRepoMock) GetBeersCalls() []struct { 64 | } { 65 | var calls []struct { 66 | } 67 | lockBeerRepoMockGetBeers.RLock() 68 | calls = mock.calls.GetBeers 69 | lockBeerRepoMockGetBeers.RUnlock() 70 | return calls 71 | } 72 | -------------------------------------------------------------------------------- /09-benchmarking/internal/mock/repository.go: -------------------------------------------------------------------------------- 1 | // Code generated by moq; DO NOT EDIT. 2 | // github.com/matryer/moq 3 | 4 | package mock 5 | 6 | import ( 7 | "sync" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/09-benchmarking/internal" 10 | ) 11 | 12 | var ( 13 | lockBeerRepoMockGetBeers sync.RWMutex 14 | ) 15 | 16 | // Ensure, that BeerRepoMock does implement BeerRepo. 17 | // If this is not the case, regenerate this file with moq. 18 | var _ beerscli.BeerRepo = &BeerRepoMock{} 19 | 20 | // BeerRepoMock is a mock implementation of BeerRepo. 21 | // 22 | // func TestSomethingThatUsesBeerRepo(t *testing.T) { 23 | // 24 | // // make and configure a mocked BeerRepo 25 | // mockedBeerRepo := &BeerRepoMock{ 26 | // GetBeersFunc: func() ([]beerscli.Beer, error) { 27 | // panic("mock out the GetBeers method") 28 | // }, 29 | // } 30 | // 31 | // // use mockedBeerRepo in code that requires BeerRepo 32 | // // and then make assertions. 33 | // 34 | // } 35 | type BeerRepoMock struct { 36 | // GetBeersFunc mocks the GetBeers method. 37 | GetBeersFunc func() ([]beerscli.Beer, error) 38 | 39 | // calls tracks calls to the methods. 40 | calls struct { 41 | // GetBeers holds details about calls to the GetBeers method. 42 | GetBeers []struct { 43 | } 44 | } 45 | } 46 | 47 | // GetBeers calls GetBeersFunc. 48 | func (mock *BeerRepoMock) GetBeers() ([]beerscli.Beer, error) { 49 | if mock.GetBeersFunc == nil { 50 | panic("BeerRepoMock.GetBeersFunc: method is nil but BeerRepo.GetBeers was just called") 51 | } 52 | callInfo := struct { 53 | }{} 54 | lockBeerRepoMockGetBeers.Lock() 55 | mock.calls.GetBeers = append(mock.calls.GetBeers, callInfo) 56 | lockBeerRepoMockGetBeers.Unlock() 57 | return mock.GetBeersFunc() 58 | } 59 | 60 | // GetBeersCalls gets all the calls that were made to GetBeers. 61 | // Check the length with: 62 | // len(mockedBeerRepo.GetBeersCalls()) 63 | func (mock *BeerRepoMock) GetBeersCalls() []struct { 64 | } { 65 | var calls []struct { 66 | } 67 | lockBeerRepoMockGetBeers.RLock() 68 | calls = mock.calls.GetBeers 69 | lockBeerRepoMockGetBeers.RUnlock() 70 | return calls 71 | } 72 | -------------------------------------------------------------------------------- /10-profiling/internal/storage/mock/repository.go: -------------------------------------------------------------------------------- 1 | // Code generated by moq; DO NOT EDIT. 2 | // github.com/matryer/moq 3 | 4 | package mock 5 | 6 | import ( 7 | "sync" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/10-profiling/internal" 10 | ) 11 | 12 | var ( 13 | lockBeerRepoMockGetBeers sync.RWMutex 14 | ) 15 | 16 | // Ensure, that BeerRepoMock does implement BeerRepo. 17 | // If this is not the case, regenerate this file with moq. 18 | var _ beerscli.BeerRepo = &BeerRepoMock{} 19 | 20 | // BeerRepoMock is a mock implementation of BeerRepo. 21 | // 22 | // func TestSomethingThatUsesBeerRepo(t *testing.T) { 23 | // 24 | // // make and configure a mocked BeerRepo 25 | // mockedBeerRepo := &BeerRepoMock{ 26 | // GetBeersFunc: func() ([]beerscli.Beer, error) { 27 | // panic("mock out the GetBeers method") 28 | // }, 29 | // } 30 | // 31 | // // use mockedBeerRepo in code that requires BeerRepo 32 | // // and then make assertions. 33 | // 34 | // } 35 | type BeerRepoMock struct { 36 | // GetBeersFunc mocks the GetBeers method. 37 | GetBeersFunc func() ([]beerscli.Beer, error) 38 | 39 | // calls tracks calls to the methods. 40 | calls struct { 41 | // GetBeers holds details about calls to the GetBeers method. 42 | GetBeers []struct { 43 | } 44 | } 45 | } 46 | 47 | // GetBeers calls GetBeersFunc. 48 | func (mock *BeerRepoMock) GetBeers() ([]beerscli.Beer, error) { 49 | if mock.GetBeersFunc == nil { 50 | panic("BeerRepoMock.GetBeersFunc: method is nil but BeerRepo.GetBeers was just called") 51 | } 52 | callInfo := struct { 53 | }{} 54 | lockBeerRepoMockGetBeers.Lock() 55 | mock.calls.GetBeers = append(mock.calls.GetBeers, callInfo) 56 | lockBeerRepoMockGetBeers.Unlock() 57 | return mock.GetBeersFunc() 58 | } 59 | 60 | // GetBeersCalls gets all the calls that were made to GetBeers. 61 | // Check the length with: 62 | // len(mockedBeerRepo.GetBeersCalls()) 63 | func (mock *BeerRepoMock) GetBeersCalls() []struct { 64 | } { 65 | var calls []struct { 66 | } 67 | lockBeerRepoMockGetBeers.RLock() 68 | calls = mock.calls.GetBeers 69 | lockBeerRepoMockGetBeers.RUnlock() 70 | return calls 71 | } 72 | -------------------------------------------------------------------------------- /09-benchmarking/internal/storage/mock/repository.go: -------------------------------------------------------------------------------- 1 | // Code generated by moq; DO NOT EDIT. 2 | // github.com/matryer/moq 3 | 4 | package mock 5 | 6 | import ( 7 | "sync" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/09-benchmarking/internal" 10 | ) 11 | 12 | var ( 13 | lockBeerRepoMockGetBeers sync.RWMutex 14 | ) 15 | 16 | // Ensure, that BeerRepoMock does implement BeerRepo. 17 | // If this is not the case, regenerate this file with moq. 18 | var _ beerscli.BeerRepo = &BeerRepoMock{} 19 | 20 | // BeerRepoMock is a mock implementation of BeerRepo. 21 | // 22 | // func TestSomethingThatUsesBeerRepo(t *testing.T) { 23 | // 24 | // // make and configure a mocked BeerRepo 25 | // mockedBeerRepo := &BeerRepoMock{ 26 | // GetBeersFunc: func() ([]beerscli.Beer, error) { 27 | // panic("mock out the GetBeers method") 28 | // }, 29 | // } 30 | // 31 | // // use mockedBeerRepo in code that requires BeerRepo 32 | // // and then make assertions. 33 | // 34 | // } 35 | type BeerRepoMock struct { 36 | // GetBeersFunc mocks the GetBeers method. 37 | GetBeersFunc func() ([]beerscli.Beer, error) 38 | 39 | // calls tracks calls to the methods. 40 | calls struct { 41 | // GetBeers holds details about calls to the GetBeers method. 42 | GetBeers []struct { 43 | } 44 | } 45 | } 46 | 47 | // GetBeers calls GetBeersFunc. 48 | func (mock *BeerRepoMock) GetBeers() ([]beerscli.Beer, error) { 49 | if mock.GetBeersFunc == nil { 50 | panic("BeerRepoMock.GetBeersFunc: method is nil but BeerRepo.GetBeers was just called") 51 | } 52 | callInfo := struct { 53 | }{} 54 | lockBeerRepoMockGetBeers.Lock() 55 | mock.calls.GetBeers = append(mock.calls.GetBeers, callInfo) 56 | lockBeerRepoMockGetBeers.Unlock() 57 | return mock.GetBeersFunc() 58 | } 59 | 60 | // GetBeersCalls gets all the calls that were made to GetBeers. 61 | // Check the length with: 62 | // len(mockedBeerRepo.GetBeersCalls()) 63 | func (mock *BeerRepoMock) GetBeersCalls() []struct { 64 | } { 65 | var calls []struct { 66 | } 67 | lockBeerRepoMockGetBeers.RLock() 68 | calls = mock.calls.GetBeers 69 | lockBeerRepoMockGetBeers.RUnlock() 70 | return calls 71 | } 72 | -------------------------------------------------------------------------------- /08-automated_tests/internal/storage/mock/repository.go: -------------------------------------------------------------------------------- 1 | // Code generated by moq; DO NOT EDIT. 2 | // github.com/matryer/moq 3 | 4 | package mock 5 | 6 | import ( 7 | "sync" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/08-automated_tests/internal" 10 | ) 11 | 12 | var ( 13 | lockBeerRepoMockGetBeers sync.RWMutex 14 | ) 15 | 16 | // Ensure, that BeerRepoMock does implement BeerRepo. 17 | // If this is not the case, regenerate this file with moq. 18 | var _ beerscli.BeerRepo = &BeerRepoMock{} 19 | 20 | // BeerRepoMock is a mock implementation of BeerRepo. 21 | // 22 | // func TestSomethingThatUsesBeerRepo(t *testing.T) { 23 | // 24 | // // make and configure a mocked BeerRepo 25 | // mockedBeerRepo := &BeerRepoMock{ 26 | // GetBeersFunc: func() ([]beerscli.Beer, error) { 27 | // panic("mock out the GetBeers method") 28 | // }, 29 | // } 30 | // 31 | // // use mockedBeerRepo in code that requires BeerRepo 32 | // // and then make assertions. 33 | // 34 | // } 35 | type BeerRepoMock struct { 36 | // GetBeersFunc mocks the GetBeers method. 37 | GetBeersFunc func() ([]beerscli.Beer, error) 38 | 39 | // calls tracks calls to the methods. 40 | calls struct { 41 | // GetBeers holds details about calls to the GetBeers method. 42 | GetBeers []struct { 43 | } 44 | } 45 | } 46 | 47 | // GetBeers calls GetBeersFunc. 48 | func (mock *BeerRepoMock) GetBeers() ([]beerscli.Beer, error) { 49 | if mock.GetBeersFunc == nil { 50 | panic("BeerRepoMock.GetBeersFunc: method is nil but BeerRepo.GetBeers was just called") 51 | } 52 | callInfo := struct { 53 | }{} 54 | lockBeerRepoMockGetBeers.Lock() 55 | mock.calls.GetBeers = append(mock.calls.GetBeers, callInfo) 56 | lockBeerRepoMockGetBeers.Unlock() 57 | return mock.GetBeersFunc() 58 | } 59 | 60 | // GetBeersCalls gets all the calls that were made to GetBeers. 61 | // Check the length with: 62 | // len(mockedBeerRepo.GetBeersCalls()) 63 | func (mock *BeerRepoMock) GetBeersCalls() []struct { 64 | } { 65 | var calls []struct { 66 | } 67 | lockBeerRepoMockGetBeers.RLock() 68 | calls = mock.calls.GetBeers 69 | lockBeerRepoMockGetBeers.RUnlock() 70 | return calls 71 | } 72 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/mock/repository.go: -------------------------------------------------------------------------------- 1 | // Code generated by moq; DO NOT EDIT. 2 | // github.com/matryer/moq 3 | 4 | package mock 5 | 6 | import ( 7 | "sync" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal" 10 | ) 11 | 12 | var ( 13 | lockBeerRepoMockGetBeers sync.RWMutex 14 | ) 15 | 16 | // Ensure, that BeerRepoMock does implement BeerRepo. 17 | // If this is not the case, regenerate this file with moq. 18 | var _ beerscli.BeerRepo = &BeerRepoMock{} 19 | 20 | // BeerRepoMock is a mock implementation of BeerRepo. 21 | // 22 | // func TestSomethingThatUsesBeerRepo(t *testing.T) { 23 | // 24 | // // make and configure a mocked BeerRepo 25 | // mockedBeerRepo := &BeerRepoMock{ 26 | // GetBeersFunc: func() ([]beerscli.Beer, error) { 27 | // panic("mock out the GetBeers method") 28 | // }, 29 | // } 30 | // 31 | // // use mockedBeerRepo in code that requires BeerRepo 32 | // // and then make assertions. 33 | // 34 | // } 35 | type BeerRepoMock struct { 36 | // GetBeersFunc mocks the GetBeers method. 37 | GetBeersFunc func() ([]beerscli.Beer, error) 38 | 39 | // calls tracks calls to the methods. 40 | calls struct { 41 | // GetBeers holds details about calls to the GetBeers method. 42 | GetBeers []struct { 43 | } 44 | } 45 | } 46 | 47 | // GetBeers calls GetBeersFunc. 48 | func (mock *BeerRepoMock) GetBeers() ([]beerscli.Beer, error) { 49 | if mock.GetBeersFunc == nil { 50 | panic("BeerRepoMock.GetBeersFunc: method is nil but BeerRepo.GetBeers was just called") 51 | } 52 | callInfo := struct { 53 | }{} 54 | lockBeerRepoMockGetBeers.Lock() 55 | mock.calls.GetBeers = append(mock.calls.GetBeers, callInfo) 56 | lockBeerRepoMockGetBeers.Unlock() 57 | return mock.GetBeersFunc() 58 | } 59 | 60 | // GetBeersCalls gets all the calls that were made to GetBeers. 61 | // Check the length with: 62 | // len(mockedBeerRepo.GetBeersCalls()) 63 | func (mock *BeerRepoMock) GetBeersCalls() []struct { 64 | } { 65 | var calls []struct { 66 | } 67 | lockBeerRepoMockGetBeers.RLock() 68 | calls = mock.calls.GetBeers 69 | lockBeerRepoMockGetBeers.RUnlock() 70 | return calls 71 | } 72 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/storage/mock/repository.go: -------------------------------------------------------------------------------- 1 | // Code generated by moq; DO NOT EDIT. 2 | // github.com/matryer/moq 3 | 4 | package mock 5 | 6 | import ( 7 | "sync" 8 | 9 | beerscli "github.com/CodelyTV/golang-examples/11-sharing_memory_concurrency/internal" 10 | ) 11 | 12 | var ( 13 | lockBeerRepoMockGetBeers sync.RWMutex 14 | ) 15 | 16 | // Ensure, that BeerRepoMock does implement BeerRepo. 17 | // If this is not the case, regenerate this file with moq. 18 | var _ beerscli.BeerRepo = &BeerRepoMock{} 19 | 20 | // BeerRepoMock is a mock implementation of BeerRepo. 21 | // 22 | // func TestSomethingThatUsesBeerRepo(t *testing.T) { 23 | // 24 | // // make and configure a mocked BeerRepo 25 | // mockedBeerRepo := &BeerRepoMock{ 26 | // GetBeersFunc: func() ([]beerscli.Beer, error) { 27 | // panic("mock out the GetBeers method") 28 | // }, 29 | // } 30 | // 31 | // // use mockedBeerRepo in code that requires BeerRepo 32 | // // and then make assertions. 33 | // 34 | // } 35 | type BeerRepoMock struct { 36 | // GetBeersFunc mocks the GetBeers method. 37 | GetBeersFunc func() ([]beerscli.Beer, error) 38 | 39 | // calls tracks calls to the methods. 40 | calls struct { 41 | // GetBeers holds details about calls to the GetBeers method. 42 | GetBeers []struct { 43 | } 44 | } 45 | } 46 | 47 | // GetBeers calls GetBeersFunc. 48 | func (mock *BeerRepoMock) GetBeers() ([]beerscli.Beer, error) { 49 | if mock.GetBeersFunc == nil { 50 | panic("BeerRepoMock.GetBeersFunc: method is nil but BeerRepo.GetBeers was just called") 51 | } 52 | callInfo := struct { 53 | }{} 54 | lockBeerRepoMockGetBeers.Lock() 55 | mock.calls.GetBeers = append(mock.calls.GetBeers, callInfo) 56 | lockBeerRepoMockGetBeers.Unlock() 57 | return mock.GetBeersFunc() 58 | } 59 | 60 | // GetBeersCalls gets all the calls that were made to GetBeers. 61 | // Check the length with: 62 | // len(mockedBeerRepo.GetBeersCalls()) 63 | func (mock *BeerRepoMock) GetBeersCalls() []struct { 64 | } { 65 | var calls []struct { 66 | } 67 | lockBeerRepoMockGetBeers.RLock() 68 | calls = mock.calls.GetBeers 69 | lockBeerRepoMockGetBeers.RUnlock() 70 | return calls 71 | } 72 | -------------------------------------------------------------------------------- /10-profiling/internal/beer.go: -------------------------------------------------------------------------------- 1 | package beerscli 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // Beer representation of beer into data struct 8 | type Beer struct { 9 | ProductID int `json:"product_id"` 10 | Name string `json:"name"` 11 | Price string `json:"price"` 12 | BeerID int `json:"beer_id"` 13 | Category string `json:"category"` 14 | Type *BeerType `json:"type"` 15 | Brewer string `json:"brewer"` 16 | Country string `json:"country"` 17 | } 18 | 19 | type BeerType int 20 | 21 | const ( 22 | Unknown BeerType = iota 23 | Lager 24 | Malt 25 | Ale 26 | FlavouredMalt 27 | Stout 28 | Porter 29 | NonAlcoholic 30 | ) 31 | 32 | func (t BeerType) String() string { 33 | return toString[t] 34 | } 35 | 36 | // NewBeerType initialize a type from enum beerTypes 37 | func NewBeerType(t string) *BeerType { 38 | beerType := toID[t] 39 | return &beerType 40 | } 41 | 42 | var toString = map[BeerType]string{ 43 | Lager: "Lager", 44 | Malt: "Malt", 45 | Ale: "Ale", 46 | FlavouredMalt: "Flavoured Malt", 47 | Stout: "Stout", 48 | Porter: "Stout", 49 | NonAlcoholic: "Non-Alcoholic", 50 | Unknown: "unknown", 51 | } 52 | 53 | var toID = map[string]BeerType{ 54 | "Lager": Lager, 55 | "Malt": Malt, 56 | "Ale": Ale, 57 | "Flavoured Malt": FlavouredMalt, 58 | "Stout": Stout, 59 | "Porter": Porter, 60 | "Non-Alcoholic": NonAlcoholic, 61 | "unknown": Unknown, 62 | } 63 | 64 | // UnmarshalJSON convert type from json to beerType 65 | func (t *BeerType) UnmarshalJSON(b []byte) error { 66 | var j string 67 | err := json.Unmarshal(b, &j) 68 | if err != nil { 69 | return err 70 | } 71 | *t = toID[j] 72 | return nil 73 | } 74 | 75 | // BeerRepo definiton of methods to access a data beer 76 | type BeerRepo interface { 77 | GetBeers() ([]Beer, error) 78 | } 79 | 80 | // NewBeer initialize struct beer 81 | func NewBeer(productID int, name, category, brewer, country, price string, beerType *BeerType) (b Beer) { 82 | b = Beer{ 83 | ProductID: productID, 84 | Name: name, 85 | Category: category, 86 | Type: beerType, 87 | Brewer: brewer, 88 | Country: country, 89 | Price: price, 90 | } 91 | return 92 | } 93 | -------------------------------------------------------------------------------- /06-error_handling/internal/beer.go: -------------------------------------------------------------------------------- 1 | package beerscli 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // Beer representation of beer into data struct 8 | type Beer struct { 9 | ProductID int `json:"product_id"` 10 | Name string `json:"name"` 11 | Price string `json:"price"` 12 | BeerID int `json:"beer_id"` 13 | Category string `json:"category"` 14 | Type *BeerType `json:"type"` 15 | Brewer string `json:"brewer"` 16 | Country string `json:"country"` 17 | } 18 | 19 | type BeerType int 20 | 21 | const ( 22 | Unknown BeerType = iota 23 | Lager 24 | Malt 25 | Ale 26 | FlavouredMalt 27 | Stout 28 | Porter 29 | NonAlcoholic 30 | ) 31 | 32 | func (t BeerType) String() string { 33 | return toString[t] 34 | } 35 | 36 | // NewBeerType initialize a type from enum beerTypes 37 | func NewBeerType(t string) *BeerType { 38 | beerType := toID[t] 39 | return &beerType 40 | } 41 | 42 | var toString = map[BeerType]string{ 43 | Lager: "Lager", 44 | Malt: "Malt", 45 | Ale: "Ale", 46 | FlavouredMalt: "Flavoured Malt", 47 | Stout: "Stout", 48 | Porter: "Stout", 49 | NonAlcoholic: "Non-Alcoholic", 50 | Unknown: "unknown", 51 | } 52 | 53 | var toID = map[string]BeerType{ 54 | "Lager": Lager, 55 | "Malt": Malt, 56 | "Ale": Ale, 57 | "Flavoured Malt": FlavouredMalt, 58 | "Stout": Stout, 59 | "Porter": Porter, 60 | "Non-Alcoholic": NonAlcoholic, 61 | "unknown": Unknown, 62 | } 63 | 64 | // UnmarshalJSON convert type from json to beerType 65 | func (t *BeerType) UnmarshalJSON(b []byte) error { 66 | var j string 67 | err := json.Unmarshal(b, &j) 68 | if err != nil { 69 | return err 70 | } 71 | *t = toID[j] 72 | return nil 73 | } 74 | 75 | // BeerRepo definiton of methods to access a data beer 76 | type BeerRepo interface { 77 | GetBeers() ([]Beer, error) 78 | } 79 | 80 | // NewBeer initialize struct beer 81 | func NewBeer(productID int, name, category, brewer, country, price string, beerType *BeerType) (b Beer) { 82 | b = Beer{ 83 | ProductID: productID, 84 | Name: name, 85 | Category: category, 86 | Type: beerType, 87 | Brewer: brewer, 88 | Country: country, 89 | Price: price, 90 | } 91 | return 92 | } 93 | -------------------------------------------------------------------------------- /08-automated_tests/internal/beer.go: -------------------------------------------------------------------------------- 1 | package beerscli 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // Beer representation of beer into data struct 8 | type Beer struct { 9 | ProductID int `json:"product_id"` 10 | Name string `json:"name"` 11 | Price string `json:"price"` 12 | BeerID int `json:"beer_id"` 13 | Category string `json:"category"` 14 | Type *BeerType `json:"type"` 15 | Brewer string `json:"brewer"` 16 | Country string `json:"country"` 17 | } 18 | 19 | type BeerType int 20 | 21 | const ( 22 | Unknown BeerType = iota 23 | Lager 24 | Malt 25 | Ale 26 | FlavouredMalt 27 | Stout 28 | Porter 29 | NonAlcoholic 30 | ) 31 | 32 | func (t BeerType) String() string { 33 | return toString[t] 34 | } 35 | 36 | // NewBeerType initialize a type from enum beerTypes 37 | func NewBeerType(t string) *BeerType { 38 | beerType := toID[t] 39 | return &beerType 40 | } 41 | 42 | var toString = map[BeerType]string{ 43 | Lager: "Lager", 44 | Malt: "Malt", 45 | Ale: "Ale", 46 | FlavouredMalt: "Flavoured Malt", 47 | Stout: "Stout", 48 | Porter: "Stout", 49 | NonAlcoholic: "Non-Alcoholic", 50 | Unknown: "unknown", 51 | } 52 | 53 | var toID = map[string]BeerType{ 54 | "Lager": Lager, 55 | "Malt": Malt, 56 | "Ale": Ale, 57 | "Flavoured Malt": FlavouredMalt, 58 | "Stout": Stout, 59 | "Porter": Porter, 60 | "Non-Alcoholic": NonAlcoholic, 61 | "unknown": Unknown, 62 | } 63 | 64 | // UnmarshalJSON convert type from json to beerType 65 | func (t *BeerType) UnmarshalJSON(b []byte) error { 66 | var j string 67 | err := json.Unmarshal(b, &j) 68 | if err != nil { 69 | return err 70 | } 71 | *t = toID[j] 72 | return nil 73 | } 74 | 75 | // BeerRepo definiton of methods to access a data beer 76 | type BeerRepo interface { 77 | GetBeers() ([]Beer, error) 78 | } 79 | 80 | // NewBeer initialize struct beer 81 | func NewBeer(productID int, name, category, brewer, country, price string, beerType *BeerType) (b Beer) { 82 | b = Beer{ 83 | ProductID: productID, 84 | Name: name, 85 | Category: category, 86 | Type: beerType, 87 | Brewer: brewer, 88 | Country: country, 89 | Price: price, 90 | } 91 | return 92 | } 93 | -------------------------------------------------------------------------------- /09-benchmarking/internal/beer.go: -------------------------------------------------------------------------------- 1 | package beerscli 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // Beer representation of beer into data struct 8 | type Beer struct { 9 | ProductID int `json:"product_id"` 10 | Name string `json:"name"` 11 | Price string `json:"price"` 12 | BeerID int `json:"beer_id"` 13 | Category string `json:"category"` 14 | Type *BeerType `json:"type"` 15 | Brewer string `json:"brewer"` 16 | Country string `json:"country"` 17 | } 18 | 19 | type BeerType int 20 | 21 | const ( 22 | Unknown BeerType = iota 23 | Lager 24 | Malt 25 | Ale 26 | FlavouredMalt 27 | Stout 28 | Porter 29 | NonAlcoholic 30 | ) 31 | 32 | func (t BeerType) String() string { 33 | return toString[t] 34 | } 35 | 36 | // NewBeerType initialize a type from enum beerTypes 37 | func NewBeerType(t string) *BeerType { 38 | beerType := toID[t] 39 | return &beerType 40 | } 41 | 42 | var toString = map[BeerType]string{ 43 | Lager: "Lager", 44 | Malt: "Malt", 45 | Ale: "Ale", 46 | FlavouredMalt: "Flavoured Malt", 47 | Stout: "Stout", 48 | Porter: "Stout", 49 | NonAlcoholic: "Non-Alcoholic", 50 | Unknown: "unknown", 51 | } 52 | 53 | var toID = map[string]BeerType{ 54 | "Lager": Lager, 55 | "Malt": Malt, 56 | "Ale": Ale, 57 | "Flavoured Malt": FlavouredMalt, 58 | "Stout": Stout, 59 | "Porter": Porter, 60 | "Non-Alcoholic": NonAlcoholic, 61 | "unknown": Unknown, 62 | } 63 | 64 | // UnmarshalJSON convert type from json to beerType 65 | func (t *BeerType) UnmarshalJSON(b []byte) error { 66 | var j string 67 | err := json.Unmarshal(b, &j) 68 | if err != nil { 69 | return err 70 | } 71 | *t = toID[j] 72 | return nil 73 | } 74 | 75 | // BeerRepo definiton of methods to access a data beer 76 | type BeerRepo interface { 77 | GetBeers() ([]Beer, error) 78 | } 79 | 80 | // NewBeer initialize struct beer 81 | func NewBeer(productID int, name, category, brewer, country, price string, beerType *BeerType) (b Beer) { 82 | b = Beer{ 83 | ProductID: productID, 84 | Name: name, 85 | Category: category, 86 | Type: beerType, 87 | Brewer: brewer, 88 | Country: country, 89 | Price: price, 90 | } 91 | return 92 | } 93 | -------------------------------------------------------------------------------- /05-parsing_http_response/internal/beer.go: -------------------------------------------------------------------------------- 1 | package beerscli 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // Beer representation of beer into data struct 8 | type Beer struct { 9 | ProductID int `json:"product_id"` 10 | Name string `json:"name"` 11 | Price string `json:"price"` 12 | BeerID int `json:"beer_id"` 13 | Category string `json:"category"` 14 | Type *BeerType `json:"type"` 15 | Brewer string `json:"brewer"` 16 | Country string `json:"country"` 17 | } 18 | 19 | type BeerType int 20 | 21 | const ( 22 | Unknown BeerType = iota 23 | Lager 24 | Malt 25 | Ale 26 | FlavouredMalt 27 | Stout 28 | Porter 29 | NonAlcoholic 30 | ) 31 | 32 | func (t BeerType) String() string { 33 | return toString[t] 34 | } 35 | 36 | // NewBeerType initialize a type from enum beerTypes 37 | func NewBeerType(t string) *BeerType { 38 | beerType := toID[t] 39 | return &beerType 40 | } 41 | 42 | var toString = map[BeerType]string{ 43 | Lager: "Lager", 44 | Malt: "Malt", 45 | Ale: "Ale", 46 | FlavouredMalt: "Flavoured Malt", 47 | Stout: "Stout", 48 | Porter: "Stout", 49 | NonAlcoholic: "Non-Alcoholic", 50 | Unknown: "unknown", 51 | } 52 | 53 | var toID = map[string]BeerType{ 54 | "Lager": Lager, 55 | "Malt": Malt, 56 | "Ale": Ale, 57 | "Flavoured Malt": FlavouredMalt, 58 | "Stout": Stout, 59 | "Porter": Porter, 60 | "Non-Alcoholic": NonAlcoholic, 61 | "unknown": Unknown, 62 | } 63 | 64 | // UnmarshalJSON convert type from json to beerType 65 | func (t *BeerType) UnmarshalJSON(b []byte) error { 66 | var j string 67 | err := json.Unmarshal(b, &j) 68 | if err != nil { 69 | return err 70 | } 71 | *t = toID[j] 72 | return nil 73 | } 74 | 75 | // BeerRepo definiton of methods to access a data beer 76 | type BeerRepo interface { 77 | GetBeers() ([]Beer, error) 78 | } 79 | 80 | // NewBeer initialize struct beer 81 | func NewBeer(productID int, name, category, brewer, country, price string, beerType *BeerType) (b Beer) { 82 | b = Beer{ 83 | ProductID: productID, 84 | Name: name, 85 | Category: category, 86 | Type: beerType, 87 | Brewer: brewer, 88 | Country: country, 89 | Price: price, 90 | } 91 | return 92 | } 93 | -------------------------------------------------------------------------------- /07-behaviour_error_handling/internal/beer.go: -------------------------------------------------------------------------------- 1 | package beerscli 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // Beer representation of beer into data struct 8 | type Beer struct { 9 | ProductID int `json:"product_id"` 10 | Name string `json:"name"` 11 | Price string `json:"price"` 12 | BeerID int `json:"beer_id"` 13 | Category string `json:"category"` 14 | Type *BeerType `json:"type"` 15 | Brewer string `json:"brewer"` 16 | Country string `json:"country"` 17 | } 18 | 19 | type BeerType int 20 | 21 | const ( 22 | Unknown BeerType = iota 23 | Lager 24 | Malt 25 | Ale 26 | FlavouredMalt 27 | Stout 28 | Porter 29 | NonAlcoholic 30 | ) 31 | 32 | func (t BeerType) String() string { 33 | return toString[t] 34 | } 35 | 36 | // NewBeerType initialize a type from enum beerTypes 37 | func NewBeerType(t string) *BeerType { 38 | beerType := toID[t] 39 | return &beerType 40 | } 41 | 42 | var toString = map[BeerType]string{ 43 | Lager: "Lager", 44 | Malt: "Malt", 45 | Ale: "Ale", 46 | FlavouredMalt: "Flavoured Malt", 47 | Stout: "Stout", 48 | Porter: "Stout", 49 | NonAlcoholic: "Non-Alcoholic", 50 | Unknown: "unknown", 51 | } 52 | 53 | var toID = map[string]BeerType{ 54 | "Lager": Lager, 55 | "Malt": Malt, 56 | "Ale": Ale, 57 | "Flavoured Malt": FlavouredMalt, 58 | "Stout": Stout, 59 | "Porter": Porter, 60 | "Non-Alcoholic": NonAlcoholic, 61 | "unknown": Unknown, 62 | } 63 | 64 | // UnmarshalJSON convert type from json to beerType 65 | func (t *BeerType) UnmarshalJSON(b []byte) error { 66 | var j string 67 | err := json.Unmarshal(b, &j) 68 | if err != nil { 69 | return err 70 | } 71 | *t = toID[j] 72 | return nil 73 | } 74 | 75 | // BeerRepo definiton of methods to access a data beer 76 | type BeerRepo interface { 77 | GetBeers() ([]Beer, error) 78 | } 79 | 80 | // NewBeer initialize struct beer 81 | func NewBeer(productID int, name, category, brewer, country, price string, beerType *BeerType) (b Beer) { 82 | b = Beer{ 83 | ProductID: productID, 84 | Name: name, 85 | Category: category, 86 | Type: beerType, 87 | Brewer: brewer, 88 | Country: country, 89 | Price: price, 90 | } 91 | return 92 | } 93 | -------------------------------------------------------------------------------- /11-sharing_memory_concurrency/internal/beer.go: -------------------------------------------------------------------------------- 1 | package beerscli 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // Beer representation of beer into data struct 8 | type Beer struct { 9 | ProductID int `json:"product_id"` 10 | Name string `json:"name"` 11 | Price string `json:"price"` 12 | BeerID int `json:"beer_id"` 13 | Category string `json:"category"` 14 | Type *BeerType `json:"type"` 15 | Brewer string `json:"brewer"` 16 | Country string `json:"country"` 17 | } 18 | 19 | type BeerType int 20 | 21 | const ( 22 | Unknown BeerType = iota 23 | Lager 24 | Malt 25 | Ale 26 | FlavouredMalt 27 | Stout 28 | Porter 29 | NonAlcoholic 30 | ) 31 | 32 | func (t BeerType) String() string { 33 | return toString[t] 34 | } 35 | 36 | // NewBeerType initialize a type from enum beerTypes 37 | func NewBeerType(t string) *BeerType { 38 | beerType := toID[t] 39 | return &beerType 40 | } 41 | 42 | var toString = map[BeerType]string{ 43 | Lager: "Lager", 44 | Malt: "Malt", 45 | Ale: "Ale", 46 | FlavouredMalt: "Flavoured Malt", 47 | Stout: "Stout", 48 | Porter: "Stout", 49 | NonAlcoholic: "Non-Alcoholic", 50 | Unknown: "unknown", 51 | } 52 | 53 | var toID = map[string]BeerType{ 54 | "Lager": Lager, 55 | "Malt": Malt, 56 | "Ale": Ale, 57 | "Flavoured Malt": FlavouredMalt, 58 | "Stout": Stout, 59 | "Porter": Porter, 60 | "Non-Alcoholic": NonAlcoholic, 61 | "unknown": Unknown, 62 | } 63 | 64 | // UnmarshalJSON convert type from json to beerType 65 | func (t *BeerType) UnmarshalJSON(b []byte) error { 66 | var j string 67 | err := json.Unmarshal(b, &j) 68 | if err != nil { 69 | return err 70 | } 71 | *t = toID[j] 72 | return nil 73 | } 74 | 75 | // BeerRepo definiton of methods to access a data beer 76 | type BeerRepo interface { 77 | GetBeers() ([]Beer, error) 78 | } 79 | 80 | // NewBeer initialize struct beer 81 | func NewBeer(productID int, name, category, brewer, country, price string, beerType *BeerType) (b Beer) { 82 | b = Beer{ 83 | ProductID: productID, 84 | Name: name, 85 | Category: category, 86 | Type: beerType, 87 | Brewer: brewer, 88 | Country: country, 89 | Price: price, 90 | } 91 | return 92 | } 93 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 4 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 5 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 6 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 7 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 8 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 9 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 10 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 11 | github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 12 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 13 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 14 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 15 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 16 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 17 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 18 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 19 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 20 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 21 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 22 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 23 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 24 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 25 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 26 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 27 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 28 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 29 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 30 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 31 | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 32 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 33 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 34 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 35 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 36 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 37 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 38 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 39 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 40 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 41 | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 42 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 43 | github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= 44 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 45 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 46 | github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= 47 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 48 | github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 49 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 50 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 51 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 52 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 53 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 54 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 55 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 56 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 57 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 58 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 59 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 60 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 61 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 62 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 63 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 64 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 65 | github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= 66 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 67 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 68 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 69 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 70 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 71 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= 72 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 73 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 74 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 75 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 76 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 77 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 78 | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= 79 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 80 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 81 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 82 | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 83 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 84 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 85 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 86 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 87 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 88 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 89 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 90 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 91 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 92 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 93 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 94 | github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= 95 | github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 96 | github.com/spf13/cobra v0.0.7 h1:FfTH+vuMXOas8jmfb5/M7dzEYx7LpcLb7a0LPe34uOU= 97 | github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= 98 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 99 | github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= 100 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 101 | github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= 102 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 103 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 104 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 105 | github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= 106 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 107 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 108 | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 109 | github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= 110 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 111 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 112 | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 113 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 114 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 115 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 116 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 117 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 118 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 119 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 120 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 121 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 122 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 123 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 124 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 125 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 126 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 127 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 128 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 129 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 130 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 131 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 132 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 133 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 134 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 135 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 136 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 137 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 138 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 139 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 140 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 141 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 142 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 143 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 144 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 145 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 146 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 147 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 148 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 149 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 150 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 151 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 152 | --------------------------------------------------------------------------------