github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/package-names.article (about) 1 Package names 2 4 Feb 2015 3 Tags: package, names, style 4 5 Sameer Ajmani 6 7 * Introduction 8 9 Go code is organized into packages. 10 Within a package, code can refer to any identifier (name) defined within, while 11 clients of the package may only reference the package's exported types, 12 functions, constants, and variables. 13 Such references always include the package name as a prefix: `foo.Bar` refers to 14 the exported name `Bar` in the imported package named `foo`. 15 16 Good package names make code better. 17 A package's name provides context for its contents, making it easier for clients 18 to understand what the package is for and how to use it. 19 The name also helps package maintainers determine what does and does not belong 20 in the package as it evolves. 21 Well-named packages make it easier to find the code you need. 22 23 Effective Go provides 24 [[https://golang.org/doc/effective_go.html#names][guidelines]] for naming 25 packages, types, functions, and variables. 26 This article expands on that discussion and surveys names found in the standard 27 library. 28 It also discusses bad package names and how to fix them. 29 30 * Package names 31 32 Good package names are short and clear. 33 They are lower case, with no `under_scores` or `mixedCaps`. 34 They are often simple nouns, such as: 35 36 - `time` (provides functionality for measuring and displaying time) 37 - `list` (implements a doubly linked list) 38 - `http` (provides HTTP client and server implementations) 39 40 The style of names typical of another language might not be idiomatic in a Go 41 program. 42 Here are two examples of names that might be good style in other languages but 43 do not fit well in Go: 44 45 - `computeServiceClient` 46 - `priority_queue` 47 48 A Go package may export several types and functions. 49 For example, a `compute` package could export a `Client` type with methods for 50 using the service as well as functions for partitioning a compute task across 51 several clients. 52 53 *Abbreviate*judiciously.* 54 Package names may be abbreviated when the abbreviation is familiar to the 55 programmer. 56 Widely-used packages often have compressed names: 57 58 - `strconv` (string conversion) 59 - `syscall` (system call) 60 - `fmt` (formatted I/O) 61 62 On the other hand, if abbreviating a package name makes it ambiguous or unclear, 63 don't do it. 64 65 *Don't*steal*good*names*from*the*user.* 66 Avoid giving a package a name that is commonly used in client code. 67 For example, the buffered I/O package is called `bufio`, not `buf`, since `buf` 68 is a good variable name for a buffer. 69 70 * Naming package contents 71 72 A package name and its contents' names are coupled, since client code uses them 73 together. 74 When designing a package, take the client's point of view. 75 76 *Avoid*stutter.* 77 Since client code uses the package name as a prefix when referring to the 78 package contents, the names for those contents need not repeat the package name. 79 The HTTP server provided by the `http` package is called `Server`, not 80 `HTTPServer`. 81 Client code refers to this type as `http.Server`, so there is no ambiguity. 82 83 *Simplify*function*names.* 84 When a function in package pkg returns a value of type `pkg.Pkg` (or 85 `*pkg.Pkg`), the function name can often omit the type name without confusion: 86 87 start := time.Now() // start is a time.Time 88 t, err := time.Parse(time.Kitchen, "6:06PM") // t is a time.Time 89 ctx = context.WithTimeout(ctx, 10*time.Millisecond) // ctx is a context.Context 90 ip, ok := userip.FromContext(ctx) // ip is a net.IP 91 92 A function named `New` in package `pkg` returns a value of type `pkg.Pkg`. 93 This is a standard entry point for client code using that type: 94 95 q := list.New() // q is a *list.List 96 97 When a function returns a value of type `pkg.T`, where `T` is not `Pkg`, the 98 function name may include `T` to make client code easier to understand. 99 A common situation is a package with multiple New-like functions: 100 101 d, err := time.ParseDuration("10s") // d is a time.Duration 102 elapsed := time.Since(start) // elapsed is a time.Duration 103 ticker := time.NewTicker(d) // ticker is a *time.Ticker 104 timer := time.NewTimer(d) // timer is a *time.Timer 105 106 Types in different packages can have the same name, because from the client's 107 point of view such names are discriminated by the package name. 108 For example, the standard library includes several types named `Reader`, 109 including `jpeg.Reader`, `bufio.Reader`, and `csv.Reader`. 110 Each package name fits with `Reader` to yield a good type name. 111 112 If you cannot come up with a package name that's a meaningful prefix for the 113 package's contents, the package abstraction boundary may be wrong. 114 Write code that uses your package as a client would, and restructure your 115 packages if the result seems poor. 116 This approach will yield packages that are easier for clients to understand and 117 for the package developers to maintain. 118 119 * Package paths 120 121 A Go package has both a name and a path. 122 The package name is specified in the package statement of its source files; 123 client code uses it as the prefix for the package's exported names. 124 Client code uses the package path when importing the package. 125 By convention, the last element of the package path is the package name: 126 127 import ( 128 "fmt" // package fmt 129 "os/exec" // package exec 130 "golang.org/x/net/context" // package context 131 ) 132 133 Build tools map package paths onto directories. 134 The go tool uses the [[https://golang.org/doc/code.html#GOPATH][GOPATH]] 135 environment variable to find the source files for path `"github.com/user/hello"` 136 in directory `$GOPATH/src/github.com/user/hello`. 137 (This situation should be familiar, of course, but it's important to be clear 138 about the terminology and structure of packages.) 139 140 *Directories.* 141 The standard library uses like directories `crypto`, `container`, `encoding`, 142 and `image` to group packages for related protocols and algorithms. 143 There is no actual relationship among the packages in one of these directories; 144 a directory just provides a way to arrange the files. 145 Any package can import any other package provided the import does not create a 146 cycle. 147 148 Just as types in different packages can have the same name without ambiguity, 149 packages in different directories can have the same name. 150 For example, 151 [[https://golang.org/pkg/runtime/pprof][runtime/pprof]] provides profiling data 152 in the format expected by the [[https://code.google.com/p/gperftools][pprof]] 153 profiling tool, while [[https://golang.org/pkg/net/http/pprof][net/http/pprof]] 154 provides HTTP endpoints to present profiling data in this format. 155 Client code uses the package path to import the package, so there is no 156 confusion. 157 If a source file needs to import both `pprof` packages, it can 158 [[https://golang.org/ref/spec#Import_declarations][rename]] one or both locally. 159 When renaming an imported package, the local name should follow the same 160 guidelines as package names (lower case, no `under_scores` or `mixedCaps`). 161 162 * Bad package names 163 164 Bad package names make code harder to navigate and maintain. 165 Here are some guidelines for recognizing and fixing bad names. 166 167 *Avoid*meaningless*package*names.* 168 Packages named `util`, `common`, or `misc` provide clients with no sense of what 169 the package contains. 170 This makes it harder for clients to use the package and makes it harder for 171 maintainers to keep the package focused. 172 Over time, they accumulate dependencies that can make compilation significantly 173 and unnecessarily slower, especially in large programs. 174 And since such package names are generic, they are more likely to collide with 175 other packages imported by client code, forcing clients to invent names to 176 distinguish them. 177 178 *Break*up*generic*packages.* 179 To fix such packages, look for types and functions with common name elements and 180 pull them into their own package. 181 For example, if you have 182 183 package util 184 func NewStringSet(...string) map[string]bool {...} 185 func SortStringSet(map[string]bool) []string {...} 186 187 then client code looks like 188 189 set := util.NewStringSet("c", "a", "b") 190 fmt.Println(util.SortStringSet(set)) 191 192 Pull these functions out of `util` into a new package, choosing a name that fits 193 the contents: 194 195 package stringset 196 func New(...string) map[string]bool {...} 197 func Sort(map[string]bool) []string {...} 198 199 then the client code becomes 200 201 set := stringset.New("c", "a", "b") 202 fmt.Println(stringset.Sort(set)) 203 204 Once you've made this change, its easier to see how to improve the new package: 205 206 package stringset 207 type Set map[string]bool 208 func New(...string) Set {...} 209 func (s Set) Sort() []string {...} 210 211 which yields even simpler client code: 212 213 set := stringset.New("c", "a", "b") 214 fmt.Println(set.Sort()) 215 216 The name of the package is a critical piece of its design. 217 Work to eliminate meaningless package names from your projects. 218 219 *Don't*use*a*single*package*for*all*your*APIs.* 220 Many well-intentioned programmers put all the interfaces exposed by their 221 program into a single package named `api`, `types`, or `interfaces`, thinking it 222 makes it easier to find the entry points to their code base. 223 This is a mistake. 224 Such packages suffer from the same problems as those named `util` or `common`, 225 growing without bound, providing no guidance to users, accumulating 226 dependencies, and colliding with other imports. 227 Break them up, perhaps using directories to separate public packages from 228 implementation. 229 230 *Avoid*unnecessary*package*name*collisions.* 231 While packages in different directories may have the same name, packages that 232 are frequently used together should have distinct names. 233 This reduces confusion and the need for local renaming in client code. 234 For the same reason, avoid using the same name as popular standard packages like 235 `io` or `http`. 236 237 * Conclusion 238 239 Package names are central to good naming in Go programs. 240 Take the time to choose good package names and organize your code well. 241 This helps clients understand and use your packages and helps maintainers to 242 grow them gracefully. 243 244 * Further reading 245 246 - [[https://golang.org/doc/effective_go.html][Effective Go]] 247 - [[https://golang.org/doc/code.html][How to Write Go Code]] 248 - [[https://blog.golang.org/organizing-go-code][Organizing Go Code (2012 blog post)]] 249 - [[https://talks.golang.org/2014/organizeio.slide][Organizing Go Code (2014 Google I/O talk)]]