├── .circleci └── config.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── errors.go ├── go.mod ├── go.sum ├── init.go ├── proverbs.go └── proverbs_test.go /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/golang:1.12 6 | steps: 7 | - checkout 8 | - run: go get -v -t -d ./... 9 | - run: go test -v ./... -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | .vscode 14 | .envrc 15 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Johnny Boursiquot 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | cover: 2 | go test -coverprofile=coverage.out 3 | go tool cover -html=coverage.out 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go Proverbs 2 | 3 | In 2015, Rob Pike (one of Go's creators) gave a talk at Gopherfest SV 2015 where he outlined what have become known as "Go Proverbs", a set of principles that every Go developer should keep in mind when working with the programming language. 4 | 5 | This package simply exposes those proverbs and their relevant locations in the talk [video](https://www.youtube.com/watch?v=PAAkCSZUG1c). 6 | 7 | [![Go Report Card](https://goreportcard.com/badge/github.com/jboursiquot/go-proverbs)](https://goreportcard.com/report/github.com/jboursiquot/go-proverbs) [![GoDoc](https://godoc.org/github.com/jboursiquot/go-proverbs?status.svg)](https://godoc.org/github.com/jboursiquot/go-proverbs) [![CircleCI](https://circleci.com/gh/jboursiquot/go-proverbs.svg?style=svg)](https://circleci.com/gh/jboursiquot/go-proverbs) 8 | 9 | ## Usage 10 | 11 | ### Random Proverb 12 | 13 | ```go 14 | package main 15 | 16 | import "github.com/jboursiquot/go-proverbs" 17 | 18 | func main() { 19 | fmt.Println(proverbs.Random()) 20 | fmt.Println(proverbs.Random()) 21 | fmt.Println(proverbs.Random()) 22 | } 23 | ``` 24 | 25 | #### Result 26 | ```plain 27 | &{With the unsafe package there are no guarantees. https://www.youtube.com/watch?v=PAAkCSZUG1c&t=13m49s} 28 | &{Reflection is never clear. https://www.youtube.com/watch?v=PAAkCSZUG1c&t=15m22s} 29 | &{A little copying is better than a little dependency. https://www.youtube.com/watch?v=PAAkCSZUG1c&t=9m28s} 30 | ``` 31 | 32 | ### Nth Proverb 33 | 34 | ```go 35 | package main 36 | 37 | import "github.com/jboursiquot/go-proverbs" 38 | 39 | func main() { 40 | p, err := proverbs.Nth(4) 41 | if err != nil { 42 | fmt.Println(err) 43 | } 44 | fmt.Printf("%+v\n", p) 45 | } 46 | ``` 47 | #### Result 48 | ```plain 49 | &{Saying:Make the zero value useful. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=6m25s} 50 | ``` 51 | 52 | ### All Proverbs 53 | 54 | ```go 55 | package main 56 | 57 | import "github.com/jboursiquot/go-proverbs" 58 | 59 | func main() { 60 | list, err := proverbs.All() 61 | if err != nil { 62 | fmt.Println(err) 63 | } 64 | for _, p := range list { 65 | fmt.Printf("%+v\n", p) 66 | } 67 | } 68 | 69 | ``` 70 | #### Result 71 | ```plain 72 | &{Saying:The bigger the interface, the weaker the abstraction. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=5m17s} 73 | &{Saying:Syscall must always be guarded with build tags. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=11m10s} 74 | &{Saying:Cgo must always be guarded with build tags. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=11m53s} 75 | &{Saying:Errors are values. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=16m13s} 76 | &{Saying:Concurrency is not parallelism. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=3m42s} 77 | &{Saying:Channels orchestrate; mutexes serialize. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=4m20s} 78 | &{Saying:Ggo is not Go. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=12m37s} 79 | &{Saying:A little copying is better than a little dependency. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=9m28s} 80 | &{Saying:Documentation is for users. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=19m07s} 81 | &{Saying:Don't panic. Link:https://github.com/golang/go/wiki/CodeReviewComments#dont-panic} 82 | &{Saying:Make the zero value useful. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=6m25s} 83 | &{Saying:Gofmt's style is no one's favorite, yet gofmt is everyone's favorite. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=8m43s} 84 | &{Saying:With the unsafe package there are no guarantees. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=13m49s} 85 | &{Saying:Clear is better than clever. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=14m35s} 86 | &{Saying:Reflection is never clear. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=15m22s} 87 | &{Saying:Don't just check errors, handle them gracefully. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=17m25s} 88 | &{Saying:Design the architecture, name the components, document the details. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=18m09s} 89 | &{Saying:Don't communicate by sharing memory, share memory by communicating. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=2m48s} 90 | &{Saying:interface{} says nothing. Link:https://www.youtube.com/watch?v=PAAkCSZUG1c&t=7m36s} 91 | ``` 92 | 93 | ## License 94 | MIT 95 | -------------------------------------------------------------------------------- /errors.go: -------------------------------------------------------------------------------- 1 | package proverbs 2 | 3 | import "fmt" 4 | 5 | // ErrNthProverbNotFound is returned when the requested nth proverb isn't found in the dictionary of proverbs. 6 | type ErrNthProverbNotFound struct { 7 | N int 8 | } 9 | 10 | func (e *ErrNthProverbNotFound) Error() string { 11 | return fmt.Sprintf("proverb %d not found", e.N) 12 | } 13 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/jboursiquot/go-proverbs 2 | 3 | go 1.12 4 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jboursiquot/go-proverbs/4f144663856efcbac3ef61869f3d5d92f1a1534a/go.sum -------------------------------------------------------------------------------- /init.go: -------------------------------------------------------------------------------- 1 | package proverbs 2 | 3 | import ( 4 | "encoding/csv" 5 | "strings" 6 | ) 7 | 8 | const data = `"Don't communicate by sharing memory, share memory by communicating.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=2m48s" 9 | "Concurrency is not parallelism.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=3m42s" 10 | "Channels orchestrate; mutexes serialize.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=4m20s" 11 | "The bigger the interface, the weaker the abstraction.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=5m17s" 12 | "Make the zero value useful.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=6m25s" 13 | "interface{} says nothing.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=7m36s" 14 | "Gofmt's style is no one's favorite, yet gofmt is everyone's favorite.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=8m43s" 15 | "A little copying is better than a little dependency.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=9m28s" 16 | "Syscall must always be guarded with build tags.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=11m10s" 17 | "Cgo must always be guarded with build tags.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=11m53s" 18 | "Cgo is not Go.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=12m37s" 19 | "With the unsafe package there are no guarantees.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=13m49s" 20 | "Clear is better than clever.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=14m35s" 21 | "Reflection is never clear.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=15m22s" 22 | "Errors are values.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=16m13s" 23 | "Don't just check errors, handle them gracefully.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=17m25s" 24 | "Design the architecture, name the components, document the details.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=18m09s" 25 | "Documentation is for users.","https://www.youtube.com/watch?v=PAAkCSZUG1c&t=19m07s" 26 | "Don't panic.","https://github.com/golang/go/wiki/CodeReviewComments#dont-panic" 27 | ` 28 | 29 | // init initializes the package-global dictionary of proverbs. 30 | func init() { 31 | r := csv.NewReader(strings.NewReader(data)) 32 | r.FieldsPerRecord = 2 33 | r.TrimLeadingSpace = true 34 | records, _ := r.ReadAll() // safely ignoring error here 35 | 36 | dict = make(map[int]*Proverb, len(records)) 37 | for i, r := range records { 38 | dict[i] = &Proverb{Saying: r[0], Link: r[1]} 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /proverbs.go: -------------------------------------------------------------------------------- 1 | // Package proverbs is inpired by a talk given from Rob Pike (co-creator of Go) at Gopherfest SV 2015. 2 | // Each proverb contains a link to the position in the recorded talk where the saying is talked about. 3 | package proverbs 4 | 5 | import ( 6 | "math/rand" 7 | "time" 8 | ) 9 | 10 | // Proverb includes the proverb and a link to the talk at the position where it's talked about. 11 | type Proverb struct { 12 | Saying string 13 | Link string 14 | } 15 | 16 | // initialized through init() 17 | var dict map[int]*Proverb 18 | var list []*Proverb 19 | 20 | // Random returns a random Proverb. 21 | func Random() *Proverb { 22 | n := rand.New(rand.NewSource(time.Now().UnixNano())).Intn(len(dict)) 23 | p, _ := Nth(n) // safely ignoring errror here 24 | return p 25 | } 26 | 27 | // All returns all the Proverbs. 28 | func All() ([]*Proverb, error) { 29 | if list != nil { 30 | return list, nil 31 | } 32 | 33 | list := []*Proverb{} 34 | for _, p := range dict { 35 | list = append(list, p) 36 | } 37 | return list, nil 38 | } 39 | 40 | // Nth returns the nth proverb from the list. 41 | func Nth(n int) (*Proverb, error) { 42 | if n > len(dict)-1 { 43 | return nil, &ErrNthProverbNotFound{N: n} 44 | } 45 | 46 | p, found := dict[n] 47 | if !found { 48 | return nil, &ErrNthProverbNotFound{N: n} 49 | } 50 | return p, nil 51 | } 52 | -------------------------------------------------------------------------------- /proverbs_test.go: -------------------------------------------------------------------------------- 1 | package proverbs_test 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | 7 | "github.com/jboursiquot/go-proverbs" 8 | ) 9 | 10 | func TestRandom(t *testing.T) { 11 | if p := proverbs.Random(); p == nil { 12 | t.Fail() 13 | } 14 | } 15 | 16 | func TestNth(t *testing.T) { 17 | cases := map[string]struct { 18 | input int 19 | want string 20 | err error 21 | }{ 22 | "second": {input: 1, want: "Concurrency is not parallelism."}, 23 | "fifth": {input: 4, want: "Make the zero value useful."}, 24 | "error": {input: 20, want: "", err: &proverbs.ErrNthProverbNotFound{}}, 25 | } 26 | 27 | for name, tc := range cases { 28 | t.Run(name, func(t *testing.T) { 29 | if p, err := proverbs.Nth(tc.input); err != nil { 30 | if reflect.TypeOf(tc.err) != reflect.TypeOf(err) { 31 | t.Fail() 32 | } 33 | } else { 34 | if tc.want != p.Saying { 35 | t.Fail() 36 | } 37 | } 38 | }) 39 | } 40 | } 41 | 42 | func TestAll(t *testing.T) { 43 | list, err := proverbs.All() 44 | if err != nil { 45 | t.Fail() 46 | } 47 | if len(list) <= 0 { 48 | t.Fail() 49 | } 50 | } 51 | --------------------------------------------------------------------------------