Slide 1

Slide 1 text

Packages & Modules Oleg Kovalov

Slide 2

Slide 2 text

Agenda

Slide 3

Slide 3 text

In this talk 3 - About me - Packages - Modules - Summary - Q&A

Slide 4

Slide 4 text

In this talk + extra 4 - About me - Packages - Modules - Summary - Q&A Interfaces

Slide 5

Slide 5 text

About me

Slide 6

Slide 6 text

I don’t have a Soundcloud... 6

Slide 7

Slide 7 text

- Gopher for ~4 years I don’t have a Soundcloud...but 7

Slide 8

Slide 8 text

I don’t have a Soundcloud...but 8 - Gopher for ~4 years - Open-source contributor - Go-critic - static analysis tool - Go-advice - list of Go tips @ GoGoConf 2018

Slide 9

Slide 9 text

I don’t have a Soundcloud...but 9 - Gopher for ~4 years - Open-source contributor - Go-critic - static analysis tool - Go-advice - list of Go tips @ GoGoConf 2018 - Engineer at allegro.pl core team

Slide 10

Slide 10 text

- Gopher for ~4 years - Open-source contributor - Go-critic - static analysis tool - Go-advice - list of Go tips @ GoGoConf 2018 - Engineer at allegro.pl core team Website: https://olegk.dev Twitter: @oleg_kovalov Github: @cristaloleg I don’t have a Soundcloud...but 10 Twitter & slides

Slide 11

Slide 11 text

Packages

Slide 12

Slide 12 text

Naming 12

Slide 13

Slide 13 text

- Short and clear Naming 13

Slide 14

Slide 14 text

- Short and clear - May be abbreviated when the abbreviation is familiar Naming 14

Slide 15

Slide 15 text

- Short and clear - May be abbreviated when the abbreviation is familiar - Abbrv name is easy to understand Naming 15

Slide 16

Slide 16 text

Naming - Short and clear - May be abbreviated when the abbreviation is familiar - Abbrv name is easy to understand See standard packages for good examples - io (input and output) 16

Slide 17

Slide 17 text

- Short and clear - May be abbreviated when the abbreviation is familiar - Abbrv name is easy to understand See standard packages for good examples - io (input and output) - strconv (string conversion) Naming 17

Slide 18

Slide 18 text

- Short and clear - May be abbreviated when the abbreviation is familiar - Abbrv name is easy to understand See standard packages for good examples - io (input and output) - strconv (string conversion) - syscall (system call) Naming 18

Slide 19

Slide 19 text

Naming don’ts 19

Slide 20

Slide 20 text

- If abbreviating is unclear Naming don’ts 20

Slide 21

Slide 21 text

- If abbreviating is unclear - If name is ambiguous Naming don’ts 21

Slide 22

Slide 22 text

- If abbreviating is unclear - If name is ambiguous - snake_case or camelCase Naming don’ts 22

Slide 23

Slide 23 text

Naming don’ts - If abbreviating is unclear - If name is ambiguous - snake_case or camelCase - psdb (Postgres? Parallel search?) 23

Slide 24

Slide 24 text

- If abbreviating is unclear - If name is ambiguous - snake_case or camelCase - psdb (Postgres? Parallel search?) - srv (service? server? surviving?) Naming don’ts 24

Slide 25

Slide 25 text

- If abbreviating is unclear - If name is ambiguous - snake_case or camelCase - psdb (Postgres? Parallel search?) - srv (service? server? surviving?) - buf (buffer? buffer what? WoW buff?) Naming don’ts 25

Slide 26

Slide 26 text

- Avoid giving a package a name that is commonly used in client code Don’t steal good names 26

Slide 27

Slide 27 text

- Avoid giving a package a name that is commonly used in client code - buf is a good variable name for a buffer - the buffered I/O package is called bufio (buffer + io) Don’t steal good names 27

Slide 28

Slide 28 text

- Avoid giving a package a name that is commonly used in client code - buf is a good variable name for a buffer - the buffered I/O package is called bufio (buffer + io) - client is a good name for...client - but not a package name Don’t steal good names 28

Slide 29

Slide 29 text

- Avoid giving a package a name that is commonly used in client code - buf is a good variable name for a buffer - the buffered I/O package is called bufio (buffer + io) - client is a good name for...client - but not a package name - imagine a replacement for it Don’t steal good names 29 c ? clnt ? cli ? clientHTTP ?

Slide 30

Slide 30 text

...and few from std packages 30

Slide 31

Slide 31 text

These std packages are a good names thiefs: - path - path/filepath - net/url And you cannot use your variable url easily, oh :( ...and few from std packages 31

Slide 32

Slide 32 text

...and few from std packages 32 These std packages are a good names thiefs: - path - path/filepath - net/url And you cannot use your variable url easily, oh :( But there are good examples: - strings - bytes - net/urls instead of net/url looks good enough

Slide 33

Slide 33 text

Most of the projects in Go are flat and this is fine Try to keep clean import paths 33

Slide 34

Slide 34 text

Most of the projects in Go are flat and this is fine - Try to keep it clean github.com/foo/bar/pl/goava/src/main/code/go/validation Try to keep clean import paths 34

Slide 35

Slide 35 text

Most of the projects in Go are flat and this is fine - Try to keep it clean github.com/foo/bar/pl/goava/src/main/code/go/validation - Avoid do src/ or pkg/ (in most cases) gitlab.com/foo/bar/pkg/process Try to keep clean import paths 35

Slide 36

Slide 36 text

Write shy code - modules that don’t reveal anything unnecessary to other modules and that don’t rely on other modules' implementations. --- Dave Thomas (with Andy Hunt, he co-authored The Pragmatic Programmer) Shy packages 36

Slide 37

Slide 37 text

Write shy code - modules that don’t reveal anything unnecessary to other modules and that don’t rely on other modules' implementations. --- Dave Thomas (with Andy Hunt, he co-authored The Pragmatic Programmer) And shy also means: 1 package = 1 thing Shy packages 37

Slide 38

Slide 38 text

Let’s put all structs into model(s) package 38

Slide 39

Slide 39 text

Nice 39

Slide 40

Slide 40 text

Yeah! 40

Slide 41

Slide 41 text

Oh wait... 41

Slide 42

Slide 42 text

... 42

Slide 43

Slide 43 text

PLZ STAHP 43

Slide 44

Slide 44 text

Models package is a weak idea 44

Slide 45

Slide 45 text

- Organize by functional responsibility Models package is a weak idea, so 45

Slide 46

Slide 46 text

- Organize by functional responsibility - Don’t put all the type into models package Models package is a weak idea, so 46

Slide 47

Slide 47 text

Models package is a weak idea, so 47 - Organize by functional responsibility - Don’t put all the type into models package - Keeping them in one gives nothing

Slide 48

Slide 48 text

Models package is a weak idea, so 48 - Organize by functional responsibility - Don’t put all the type into models package - Keeping them in one gives nothing - In the end this will be a spaghetti code

Slide 49

Slide 49 text

Models package is a weak idea, so 49 - Organize by functional responsibility - Don’t put all the type into models package - Keeping them in one gives nothing - In the end this will be a spaghetti code - (The same applies to the interfaces, implementations and so on)

Slide 50

Slide 50 text

One of the possible structures 50 . ├── app ├── cmd │ └── ├── blog ├── comment ├── mock ├── pkg │ ├── superpay │ └── validation ├── store │ └── postgres ├── user └── .go

Slide 51

Slide 51 text

One of the possible structures 51 . ├── app ├── cmd │ └── ├── blog ├── comment ├── mock ├── pkg │ ├── superpay │ └── validation ├── store │ └── postgres ├── user └── .go

Slide 52

Slide 52 text

One of the possible structures 52 . ├── app ├── cmd │ └── ├── blog ├── comment ├── mock ├── pkg │ ├── superpay │ └── validation ├── store │ └── postgres ├── user └── .go

Slide 53

Slide 53 text

One of the possible structures 53 mock.NewBlog(...) . ├── app ├── cmd │ └── ├── blog ├── comment ├── mock ├── pkg │ ├── superpay │ └── validation ├── store │ └── postgres ├── user └── .go

Slide 54

Slide 54 text

One of the possible structures 54 . ├── app ├── cmd │ └── ├── blog ├── comment ├── mock ├── pkg │ ├── superpay │ └── validation ├── store │ └── postgres ├── user └── .go

Slide 55

Slide 55 text

One of the possible structures 55 . ├── app ├── cmd │ └── ├── blog ├── comment ├── mock ├── pkg │ ├── superpay │ └── validation ├── store │ └── postgres ├── user └── .go

Slide 56

Slide 56 text

One of the possible structures 56 . ├── app ├── cmd │ └── ├── blog ├── comment ├── mock ├── pkg │ ├── superpay │ └── validation ├── store │ └── postgres ├── user └── .go

Slide 57

Slide 57 text

pkg, internal, misc or util Whatever works for your team and you One of the possible structures 57 . ├── app ├── cmd │ └── ├── blog ├── comment ├── mock ├── pkg │ ├── superpay │ └── validation ├── store │ └── postgres ├── user └── .go

Slide 58

Slide 58 text

One of the possible structures 58 . ├── app ├── cmd │ └── ├── blog ├── comment ├── mock ├── pkg │ ├── superpay │ └── validation ├── store │ └── postgres ├── user └── .go

Slide 59

Slide 59 text

Avoid util/common/base/helpers packages 59

Slide 60

Slide 60 text

- util.URLError Avoid util/common/base/helpers packages 60

Slide 61

Slide 61 text

- util.URLError - common.SanitizeMessage Avoid util/common/base/helpers packages 61

Slide 62

Slide 62 text

- util.URLError - common.SanitizeMessage - base.EnsureAbsolutePath Avoid util/common/base/helpers packages 62

Slide 63

Slide 63 text

- util.URLError - common.SanitizeMessage - base.EnsureAbsolutePath - helpers.IsEmail Avoid util/common/base/helpers packages 63

Slide 64

Slide 64 text

- util.URLError - common.SanitizeMessage - base.EnsureAbsolutePath - helpers.IsEmail Avoid util/common/base/helpers packages 64 These packages say nothing!

Slide 65

Slide 65 text

Avoid util/common/base/helpers packages 65 - util.URLError - common.SanitizeMessage - base.EnsureAbsolutePath - helpers.IsEmail type URLError = app.URLError These packages say nothing!

Slide 66

Slide 66 text

Avoid util/common/base/helpers packages 66 - util.URLError - common.SanitizeMessage - base.EnsureAbsolutePath - helpers.IsEmail type URLError = app.URLError var isEmail = validation.IsEmail These packages say nothing!

Slide 67

Slide 67 text

- Use multiple files - Do not separate structs and their methods (not a C/C++) - It’s okay to store few structs in one file (it’s not Java after all) - And keep test files next to code store ├── postgres │ ├── postgres.go │ ├── user.go │ └── user_test.go └── redis ├── redis.go └── comments.go Inside the package 67

Slide 68

Slide 68 text

- Use multiple files - Do not separate structs and their methods (not a C/C++) - It’s okay to store few structs in one file (it’s not Java after all) - And keep test files next to code store ├── postgres │ ├── postgres.go │ ├── user.go │ └── user_test.go └── redis ├── redis.go └── comments.go // type Comment and Comment.HasImage method Inside the package 68

Slide 69

Slide 69 text

- Use multiple files - Do not separate structs and their methods (not a C/C++) - It’s okay to store few structs in one file (it’s not Java after all) - And keep test files next to code store ├── postgres │ ├── postgres.go │ ├── user.go // type User and type Credentials │ └── user_test.go └── redis ├── redis.go └── comments.go Inside the package 69

Slide 70

Slide 70 text

- Use multiple files - Do not separate structs and their methods (not a C/C++) - It’s okay to store few structs in one file (it’s not Java after all) - And keep test files next to code store ├── postgres │ ├── postgres.go │ ├── user.go │ └── user_test.go └── redis ├── redis.go └── comments.go Inside the package 70

Slide 71

Slide 71 text

Is this storage? Stats? Cache? Benchmark suites? 71 postgres ├── postgres.go ├── user.go ├── stats.go └── user_test.go redis ├── redis.go ├── cache.go └── comments.go

Slide 72

Slide 72 text

Is this storage? Stats? Cache? Benchmark suites? 72 postgres ├── postgres.go ├── user.go ├── stats.go └── user_test.go redis ├── redis.go ├── cache.go └── comments.go cache ├── redis │ └── redis.go store ├── postgres │ ├── postgres.go │ ├── user.go │ └── user_test.go └── redis ├── redis.go └── comments.go

Slide 73

Slide 73 text

What about main package? 73

Slide 74

Slide 74 text

- Main packages are not importable What about main package? 74

Slide 75

Slide 75 text

- Main packages are not importable - Don’t export from main, it’s useless What about main package? 75

Slide 76

Slide 76 text

- Main packages are not importable - Don’t export from main, it’s useless - main package is hard to test (see above) What about main package? 76

Slide 77

Slide 77 text

Keep your main simple and testable 77 package main func init() { config.Load() }

Slide 78

Slide 78 text

Keep your main simple and testable 78 package main func init() { config.Load() } func main() { os.Exit(realMain()) } func realMain() int { log.SetOutput(ioutil.Discard) // ... }

Slide 79

Slide 79 text

package main func main() { log.Fatal(app.Run()) } Keep your main simpler 79

Slide 80

Slide 80 text

Keep your init() light 80

Slide 81

Slide 81 text

- 1 init() per package (pretty please) Keep your init() light 81

Slide 82

Slide 82 text

- 1 init() per package (pretty please) - Do not depend on init’s call order Keep your init() light 82

Slide 83

Slide 83 text

- 1 init() per package (pretty please) - Do not depend on init’s call order - No heavy tasks Keep your init() light 83

Slide 84

Slide 84 text

- 1 init() per package (pretty please) - Do not depend on init’s call order - No heavy tasks - Preferably no I/O, especially blocking Keep your init() light 84

Slide 85

Slide 85 text

- 1 init() per package (pretty please) - Do not depend on init’s call order - No heavy tasks - Preferably no I/O, especially blocking - Better to not have it at all Keep your init() light 85

Slide 86

Slide 86 text

# Python is quite flexible # try: import foo except: print(‘good try lol’) panic in init() 86

Slide 87

Slide 87 text

# Python is quite flexible # try: import foo except: print(‘good try lol’) // Go isn’t so… // package foo func init() { iCanPanicAndYouCanDoNothing() } panic in init() 87

Slide 88

Slide 88 text

// but wait, it can be flexible... package foo func Init() { iCanPanicButOoooohhYouCanCatchMe() } panic in init() 88

Slide 89

Slide 89 text

panic in init() // but wait, it can be flexible... package foo func Init() { iCanPanicButOoooohhYouCanCatchMe() } ----------- package bar func ... { defer func() { if r := recover(); r != nil { // process a panic } }() foo.Init() } 89

Slide 90

Slide 90 text

package foo func (s *Service) Process() { // let’s start a sweet goroutine go func() { iCanPanicAndYouCanDoNothing() }() } I heard you like goroutines 90

Slide 91

Slide 91 text

package foo func (s *Service) Process() { // let’s start a sweet goroutine go func() { iCanPanicAndYouCanDoNothing() }() } ----------- package bar func ... { // but internal goroutine // isn’t accessible here :( s.Process() } I heard you like goroutines 91

Slide 92

Slide 92 text

package foo func (s *Service) Process() { go func() { defer func() { // recovery process }() iCanPanicAndAuthorWillRecover() }() } I heard you like goroutines 92

Slide 93

Slide 93 text

package foo func (s *Service) Process() { iCanPanicButItDoesntMatter() } I heard you like goroutines 93

Slide 94

Slide 94 text

package foo func (s *Service) Process() { iCanPanicButItDoesntMatter() } ----------- package bar func ... { go func() { defer func() { // user defined recovery process }() s.Process() }() } I heard you like goroutines 94

Slide 95

Slide 95 text

Global state 95

Slide 96

Slide 96 text

- Exported package variable is mutable by everyone Global state 96

Slide 97

Slide 97 text

- Exported package variable is mutable by everyone - You have no power to control other packages Global state 97

Slide 98

Slide 98 text

- Exported package variable is mutable by everyone - You have no power to control other packages - Tight coupling makes code less flexible Global state 98

Slide 99

Slide 99 text

- Exported package variable is mutable by everyone - You have no power to control other packages - Tight coupling makes code less flexible - You cannot mock a package! Global state 99

Slide 100

Slide 100 text

- Exported package variable is mutable by everyone - You have no power to control other packages - Tight coupling makes code less flexible - You cannot mock a package! - Logger, metrics? - mmmmaybe Global state 100

Slide 101

Slide 101 text

- Exported package variable is mutable by everyone - You have no power to control other packages - Tight coupling makes code less flexible - You cannot mock a package! - Logger, metrics? - mmmmaybe - Config, flags? - better no Global state 101

Slide 102

Slide 102 text

- Exported package variable is mutable by everyone - You have no power to control other packages - Tight coupling makes code less flexible - You cannot mock a package! - Logger, metrics? - mmmmaybe - Config, flags? - better no - DB driver? - NONONO Global state 102

Slide 103

Slide 103 text

- Exported package variable is mutable by everyone - You have no power to control other packages - Tight coupling makes code less flexible - You cannot mock a package! - Logger, metrics? - mmmmaybe - Config, flags? - better no - DB driver? - NONONO Global state 103 by the way unexported variables are also bad :(

Slide 104

Slide 104 text

Good package == stateless container 104

Slide 105

Slide 105 text

- Should be simply a container for consts, types, funcs Good package == stateless container 105

Slide 106

Slide 106 text

- Should be simply a container for consts, types, funcs - Zero variables is brilliant (both exported and unexported) Good package == stateless container 106

Slide 107

Slide 107 text

- Should be simply a container for consts, types, funcs - Zero variables is brilliant (both exported and unexported) - Documentation and tests :) Good package == stateless container 107

Slide 108

Slide 108 text

Logging is cool 108

Slide 109

Slide 109 text

- log.Printf A safe action, might be noisy, but harmless Logging is cool, but... 109

Slide 110

Slide 110 text

- log.Printf A safe action, might be noisy, but harmless - log.Panicf Not idiomatic, but in an edge case might be fine Logging is cool, but... 110

Slide 111

Slide 111 text

Logging is cool, but... 111 - log.Printf A safe action, might be noisy, but harmless - log.Panicf Not idiomatic, but in an edge case might be fine - log.Fatalf Evil has no boundaries, omit it, no one can survive os.Exit(1) (even defer)

Slide 112

Slide 112 text

Forgotten doc.go 112

Slide 113

Slide 113 text

- doc.go is a README of your package Forgotten doc.go 113

Slide 114

Slide 114 text

- doc.go is a README of your package - Run godoc locally to see how it looks Forgotten doc.go 114

Slide 115

Slide 115 text

Forgotten doc.go 115 - doc.go is a README of your package - Run godoc locally to see how it looks - Also add package documentation // Package bytes implements functions for the manipulation of byte slices. // It is analogous to the facilities of the strings package. package bytes

Slide 116

Slide 116 text

Interfaces

Slide 117

Slide 117 text

Accept interfaces, return structs 117

Slide 118

Slide 118 text

Be conservative in what you send, be liberal in what you accept (с) Postel’s Law, Wikipedia Accept interfaces, return structs 118

Slide 119

Slide 119 text

Be conservative in what you send, be liberal in what you accept (с) Postel’s Law, Wikipedia TCP architecture: Accept interfaces, return structs 119

Slide 120

Slide 120 text

Accept interfaces, return structs Be conservative in what you send, be liberal in what you accept (с) Postel’s Law, Wikipedia TCP architecture: - We don’t care about how packets go through network 120

Slide 121

Slide 121 text

Be conservative in what you send, be liberal in what you accept (с) Postel’s Law, Wikipedia TCP architecture: - We don’t care about how packets go through network - but we expect them in a well defined order to process Accept interfaces, return structs 121

Slide 122

Slide 122 text

func FetchUsers(db Store) ([]*User, error) { ... } Accept interfaces, return structs 122

Slide 123

Slide 123 text

func FetchUsers(db Store) ([]*User, error) { ... } - We don’t care what is inside: Postgres, Redis, plain file or a mock Accept interfaces, return structs 123

Slide 124

Slide 124 text

func FetchUsers(db Store) ([]*User, error) { ... } - We don’t care what is inside: Postgres, Redis, plain file or a mock - Until it has desired API for us Accept interfaces, return structs 124

Slide 125

Slide 125 text

func FetchUsers(db Store) ([]*User, error) { ... } - We don’t care what is inside: Postgres, Redis, plain file or a mock - Until it has desired API for us - But we know for sure that we need a specific struct User Accept interfaces, return structs 125

Slide 126

Slide 126 text

func FetchUsers(db Store) ([]*User, error) { ... } - We don’t care what is inside: Postgres, Redis, plain file or a mock - Until it has desired API for us - But we know for sure that we need a specific struct User Tip: return error as interface, not as a struct Accept interfaces, return structs 126

Slide 127

Slide 127 text

Where to declare interfaces? 127

Slide 128

Slide 128 text

- There is the “Java-style” interface declaration Where to declare interfaces? 128

Slide 129

Slide 129 text

- There is the “Java-style” interface declaration - Define an interface Where to declare interfaces? 129

Slide 130

Slide 130 text

- There is the “Java-style” interface declaration - Define an interface - Create a type that implements it Where to declare interfaces? 130

Slide 131

Slide 131 text

Where to declare interfaces? 131 - There is the “Java-style” interface declaration - Define an interface - Create a type that implements it - Often you have one interface and one implementation

Slide 132

Slide 132 text

Where to declare interfaces? - There is the “Java-style” interface declaration - Define an interface - Create a type that implements it - Often you have one interface and one implementation That’s not a “Go style” ʕ◔ϖ◔ʔ 132

Slide 133

Slide 133 text

Where to declare Go interfaces? 133

Slide 134

Slide 134 text

- Go interfaces are in the package that uses it Where to declare Go interfaces? 134

Slide 135

Slide 135 text

- Go interfaces are in the package that uses it - And this makes Go code easy to extend Where to declare Go interfaces? 135

Slide 136

Slide 136 text

Modules

Slide 137

Slide 137 text

Long story short time 137 time Image credit: ©Istockphoto/JamesBrey

Slide 138

Slide 138 text

Pre-modules era 138

Slide 139

Slide 139 text

- GOPATH Pre-modules era (2012-...) Go 1.0 139

Slide 140

Slide 140 text

- GOPATH - godep Pre-modules era (2013-...) 140

Slide 141

Slide 141 text

- GOPATH - godep - gopkg.in Pre-modules era (2014-...) 141

Slide 142

Slide 142 text

- GOPATH - godep - gopkg.in - glide Pre-modules era (2014-...) 142

Slide 143

Slide 143 text

- GOPATH - godep - gopkg.in - glide - vendor dir Pre-modules era (2015-...) Go 1.5 143

Slide 144

Slide 144 text

- GOPATH - godep - gopkg.in - glide - vendor dir - dep Pre-modules era (2017-...) 144

Slide 145

Slide 145 text

Go modules (2018) 145

Slide 146

Slide 146 text

Go modules 146 - Modules - Semantic versioning - Import compatibility rule - go.mod

Slide 147

Slide 147 text

- A module is a collection of Go packages that are versioned as a single unit What is a module? 147

Slide 148

Slide 148 text

- A module is a collection of Go packages that are versioned as a single unit - A module is a tree/directory of Go source files with a go.mod file in the root ├── cmd │ └── main.go ├── consum │ ├── consum.go │ └── handlers.go ├── produce │ ├── handlers.go │ ├── handlers_test.go │ └── processing.go ├── go.mod └── go.sum What is a module? 148

Slide 149

Slide 149 text

- A module is a collection of Go packages that are versioned as a single unit - A module is a tree/directory of Go source files with a go.mod file in the root ├── cmd │ └── main.go ├── consum │ ├── consum.go │ └── handlers.go ├── produce │ ├── handlers.go │ ├── handlers_test.go │ └── processing.go ├── go.mod └── go.sum What is a module? 149 Can leave outside of GOPATH

Slide 150

Slide 150 text

Semantic versioning (https://semver.org) 150

Slide 151

Slide 151 text

Import compatibility rule 151 - If an old and a new package have the same import path - the new package must be backwards-compatible with the old package

Slide 152

Slide 152 text

Import compatibility rule 152 - If an old and a new package have the same import path - the new package must be backwards-compatible with the old package import ( "github.com/golang/hello/hey" // v0 or v1 "github.com/golang/hello/v2/hey" )

Slide 153

Slide 153 text

How to enable modules? 153 - auto(default) - on - off $ export GO111MODULE=on $ go build ./...

Slide 154

Slide 154 text

go mod commands 154 Usage: go mod [arguments] The commands are: download download modules to local cache edit edit go.mod from tools or scripts graph print module requirement graph init initialize new module in current directory tidy add missing and remove unused modules vendor make vendored copy of dependencies verify verify dependencies have expected content why explain why packages or modules are needed

Slide 155

Slide 155 text

$ mkdir /mygo/hello $ cd /mygo/hello Let’s start with modules 155

Slide 156

Slide 156 text

Let’s start with modules $ mkdir /mygo/hello $ cd /mygo/hello $ go mod init github.com/golang/hello go: creating new go.mod: module github.com/golang/hello $ ls go.mod 156

Slide 157

Slide 157 text

Let’s start with modules 157 $ mkdir /mygo/hello $ cd /mygo/hello $ go mod init github.com/golang/hello go: creating new go.mod: module github.com/golang/hello $ ls go.mod $ cat go.mod module github.com/golang/hello

Slide 158

Slide 158 text

$ git clone https://github.com/go-gitea/gitea Cloning into gitea... $ cd gitea Convert to modules 158

Slide 159

Slide 159 text

$ git clone https://github.com/go-gitea/gitea Cloning into gitea... $ cd gitea $ go mod init go: creating new go.mod: module github.com/go-gitea/gitea go: copying requirements from Gopkg.lock Convert to modules 159

Slide 160

Slide 160 text

Convert to modules 160 $ git clone https://github.com/go-gitea/gitea Cloning into gitea... $ cd gitea $ go mod init go: creating new go.mod: module github.com/go-gitea/gitea go: copying requirements from Gopkg.lock $ go mod tidy go: extracting github.com/PuerkitoBio/goquery v1.5.0 go: extracting github.com/blevesearch/bleve v0.7.0 go: finding github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57 go: finding golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961 go: finding golang.org/x/time v0.0.0-20181108054448-85acf8d2951c go: downloading github.com/facebookgo/grace v0.0.0-20180706040059-75cf19382434 ...

Slide 161

Slide 161 text

How to read go.mod? module github.com/hashicorp/consul go 1.12 ... 161

Slide 162

Slide 162 text

How to read go.mod? module github.com/hashicorp/consul go 1.12 require ( github.com/NYTimes/gziphandler v1.0.1 <...>/datadog-go v0.0.0-20160329135253-cc2f4770f4d6 // indirect github.com/go-redis/redis v6.15.2+incompatible ... ) 162

Slide 163

Slide 163 text

module github.com/hashicorp/consul go 1.12 require ( github.com/NYTimes/gziphandler v1.0.1 <...>/datadog-go v0.0.0-20160329135253-cc2f4770f4d6 // indirect github.com/go-redis/redis v6.15.2+incompatible ... ) How to read go.mod? 163

Slide 164

Slide 164 text

How to read go.mod? 164 module github.com/hashicorp/consul go 1.12 require ( github.com/NYTimes/gziphandler v1.0.1 <...>/datadog-go v0.0.0-20160329135253-cc2f4770f4d6 // indirect github.com/go-redis/redis v6.15.2+incompatible ... ) replace github.com/hashicorp/consul/api => ./api // can be fork or branch

Slide 165

Slide 165 text

How to read go.mod? 165 module github.com/hashicorp/consul go 1.12 require ( github.com/NYTimes/gziphandler v1.0.1 <...>/datadog-go v0.0.0-20160329135253-cc2f4770f4d6 // indirect github.com/go-redis/redis v6.15.2+incompatible ... ) replace github.com/hashicorp/consul/api => ./api // can be fork or branch exclude github.com/not-a-hacker/supergeil v1270.0.1

Slide 166

Slide 166 text

How to read go.sum? 166

Slide 167

Slide 167 text

How to read go.sum? 167

Slide 168

Slide 168 text

How to read go.sum? 168 cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/Azure/azure-sdk-for-go v16.0.0+incompatible h1:gr1qKY/Ll72VjFTZmaBwRK1yQHAxCnV25ekOKroc9ws= github.com/Azure/azure-sdk-for-go v16.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= // you might want to use go mod verify

Slide 169

Slide 169 text

go get understands versioning 169

Slide 170

Slide 170 text

# same (@latest is default for 'go get') $ go get github.com/gorilla/mux@latest go get understands versioning 170

Slide 171

Slide 171 text

# same (@latest is default for 'go get') $ go get github.com/gorilla/mux@latest # records v1.6.2 $ go get github.com/gorilla/[email protected] $ go get github.com/gorilla/mux@e3702bed2 go get understands versioning 171

Slide 172

Slide 172 text

go get understands versioning # same (@latest is default for 'go get') $ go get github.com/gorilla/mux@latest # records v1.6.2 $ go get github.com/gorilla/[email protected] $ go get github.com/gorilla/mux@e3702bed2 # records v0.0.0-20180517173623-c85619274f5d $ go get github.com/gorilla/mux@c856192 172

Slide 173

Slide 173 text

go get understands versioning 173 # same (@latest is default for 'go get') $ go get github.com/gorilla/mux@latest # records v1.6.2 $ go get github.com/gorilla/[email protected] $ go get github.com/gorilla/mux@e3702bed2 # records v0.0.0-20180517173623-c85619274f5d $ go get github.com/gorilla/mux@c856192 # records current meaning of master $ go get github.com/gorilla/mux@master

Slide 174

Slide 174 text

# go and get a repo $ go get github.com/go-gitea/gitea $ cd ~/go/src/github.com/go-gitea/gitea go mod why 174

Slide 175

Slide 175 text

# go and get a repo $ go get github.com/go-gitea/gitea $ cd ~/go/src/github.com/go-gitea/gitea # set a env var and check why do we use this dependency $ export GO111MODULE=on $ go mod why github.com/RoaringBitmap/roaring go mod why 175

Slide 176

Slide 176 text

go mod why 176 # go and get a repo $ go get github.com/go-gitea/gitea $ cd ~/go/src/github.com/go-gitea/gitea # set a env var and check why do we use this dependency $ export GO111MODULE=on $ go mod why github.com/RoaringBitmap/roaring # github.com/RoaringBitmap/roaring code.gitea.io/gitea/modules/indexer github.com/blevesearch/bleve github.com/blevesearch/bleve/index/scorch github.com/RoaringBitmap/roaring

Slide 177

Slide 177 text

# install $ go get github.com/rogpeppe/gohack gohack by Roger Peppe 177

Slide 178

Slide 178 text

# install $ go get github.com/rogpeppe/gohack $ gohack get example.com/foo/bar # will clone repo into $HOME/gohack/example.com/foo/bar # will add replace statement $ cat go.mod replace example.com/foo/bar => /home/rog/gohack/example.com/foo/bar gohack by Roger Peppe 178

Slide 179

Slide 179 text

gohack by Roger Peppe 179 # install $ go get github.com/rogpeppe/gohack $ gohack get example.com/foo/bar # will clone repo into $HOME/gohack/example.com/foo/bar # will add replace statement $ cat go.mod replace example.com/foo/bar => /home/rog/gohack/example.com/foo/bar # to remove specific replace: $ gohack undo example.com/foo/bar # to remove all replaces: $ gohack undo

Slide 180

Slide 180 text

GOPROXY 180

Slide 181

Slide 181 text

GOPROXY 181 - https://proxy.golang.org - https://github.com/gomods/athens - https://github.com/goproxy/goproxy - export GOPROXY=my.proxy.com - go get github.com/foo/bar

Slide 182

Slide 182 text

Why package management is hard? 182

Slide 183

Slide 183 text

*Remark

Slide 184

Slide 184 text

Application != Library 184

Slide 185

Slide 185 text

- Usability ~ Reusability Application != Library 185

Slide 186

Slide 186 text

- Usability ~ Reusability - Make application team-friendly Application != Library 186

Slide 187

Slide 187 text

- Usability ~ Reusability - Make application team-friendly - Keep library easy to use Application != Library 187

Slide 188

Slide 188 text

- Usability ~ Reusability - Make application team-friendly - Keep library easy to use Animated-emoji-colorful output in app - cool, whatever Application != Library 188

Slide 189

Slide 189 text

- Usability ~ Reusability - Make application team-friendly - Keep library easy to use Animated-emoji-colorful output in app - cool, whatever Math library with zero allocation HTTP router - thanks, but no Application != Library 189

Slide 190

Slide 190 text

Summary

Slide 191

Slide 191 text

Summary 191

Slide 192

Slide 192 text

- Simple and shy packages Summary 192

Slide 193

Slide 193 text

- Simple and shy packages - Clear naming is important Summary 193

Slide 194

Slide 194 text

- Simple and shy packages - Clear naming is important - No global state at all Summary 194

Slide 195

Slide 195 text

Summary - Simple and shy packages - Clear naming is important - No global state at all - Interfaces are for abstraction 195

Slide 196

Slide 196 text

Summary 196 - Simple and shy packages - Clear naming is important - No global state at all - Interfaces are for abstraction - Modules == Go ecosystem 2.0

Slide 197

Slide 197 text

Summary 197 - Simple and shy packages - Clear naming is important - No global state at all - Interfaces are for abstraction - Modules == Go ecosystem 2.0 - App != Lib

Slide 198

Slide 198 text

Q&A

Slide 199

Slide 199 text

- Ben Johnson @benbjohnson - Dave Cheney @davecheney - Jaana B. Dogan @rakyll - Go team ʕ◔ϖ◔ʔ - all the friends \o/ Thanks 199

Slide 200

Slide 200 text

Thank You