golang.org/toolchain@v0.0.1-go1.9rc2.windows-amd64/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 "context" // package context 129 "fmt" // package fmt 130 "golang.org/x/time/rate" // package rate 131 "os/exec" // package exec 132 ) 133 134 Build tools map package paths onto directories. 135 The go tool uses the [[https://golang.org/doc/code.html#GOPATH][GOPATH]] 136 environment variable to find the source files for path `"github.com/user/hello"` 137 in directory `$GOPATH/src/github.com/user/hello`. 138 (This situation should be familiar, of course, but it's important to be clear 139 about the terminology and structure of packages.) 140 141 *Directories.* 142 The standard library uses like directories `crypto`, `container`, `encoding`, 143 and `image` to group packages for related protocols and algorithms. 144 There is no actual relationship among the packages in one of these directories; 145 a directory just provides a way to arrange the files. 146 Any package can import any other package provided the import does not create a 147 cycle. 148 149 Just as types in different packages can have the same name without ambiguity, 150 packages in different directories can have the same name. 151 For example, 152 [[https://golang.org/pkg/runtime/pprof][runtime/pprof]] provides profiling data 153 in the format expected by the [[https://github.com/google/pprof][pprof]] 154 profiling tool, while [[https://golang.org/pkg/net/http/pprof][net/http/pprof]] 155 provides HTTP endpoints to present profiling data in this format. 156 Client code uses the package path to import the package, so there is no 157 confusion. 158 If a source file needs to import both `pprof` packages, it can 159 [[https://golang.org/ref/spec#Import_declarations][rename]] one or both locally. 160 When renaming an imported package, the local name should follow the same 161 guidelines as package names (lower case, no `under_scores` or `mixedCaps`). 162 163 * Bad package names 164 165 Bad package names make code harder to navigate and maintain. 166 Here are some guidelines for recognizing and fixing bad names. 167 168 *Avoid*meaningless*package*names.* 169 Packages named `util`, `common`, or `misc` provide clients with no sense of what 170 the package contains. 171 This makes it harder for clients to use the package and makes it harder for 172 maintainers to keep the package focused. 173 Over time, they accumulate dependencies that can make compilation significantly 174 and unnecessarily slower, especially in large programs. 175 And since such package names are generic, they are more likely to collide with 176 other packages imported by client code, forcing clients to invent names to 177 distinguish them. 178 179 *Break*up*generic*packages.* 180 To fix such packages, look for types and functions with common name elements and 181 pull them into their own package. 182 For example, if you have 183 184 package util 185 func NewStringSet(...string) map[string]bool {...} 186 func SortStringSet(map[string]bool) []string {...} 187 188 then client code looks like 189 190 set := util.NewStringSet("c", "a", "b") 191 fmt.Println(util.SortStringSet(set)) 192 193 Pull these functions out of `util` into a new package, choosing a name that fits 194 the contents: 195 196 package stringset 197 func New(...string) map[string]bool {...} 198 func Sort(map[string]bool) []string {...} 199 200 then the client code becomes 201 202 set := stringset.New("c", "a", "b") 203 fmt.Println(stringset.Sort(set)) 204 205 Once you've made this change, its easier to see how to improve the new package: 206 207 package stringset 208 type Set map[string]bool 209 func New(...string) Set {...} 210 func (s Set) Sort() []string {...} 211 212 which yields even simpler client code: 213 214 set := stringset.New("c", "a", "b") 215 fmt.Println(set.Sort()) 216 217 The name of the package is a critical piece of its design. 218 Work to eliminate meaningless package names from your projects. 219 220 *Don't*use*a*single*package*for*all*your*APIs.* 221 Many well-intentioned programmers put all the interfaces exposed by their 222 program into a single package named `api`, `types`, or `interfaces`, thinking it 223 makes it easier to find the entry points to their code base. 224 This is a mistake. 225 Such packages suffer from the same problems as those named `util` or `common`, 226 growing without bound, providing no guidance to users, accumulating 227 dependencies, and colliding with other imports. 228 Break them up, perhaps using directories to separate public packages from 229 implementation. 230 231 *Avoid*unnecessary*package*name*collisions.* 232 While packages in different directories may have the same name, packages that 233 are frequently used together should have distinct names. 234 This reduces confusion and the need for local renaming in client code. 235 For the same reason, avoid using the same name as popular standard packages like 236 `io` or `http`. 237 238 * Conclusion 239 240 Package names are central to good naming in Go programs. 241 Take the time to choose good package names and organize your code well. 242 This helps clients understand and use your packages and helps maintainers to 243 grow them gracefully. 244 245 * Further reading 246 247 - [[https://golang.org/doc/effective_go.html][Effective Go]] 248 - [[https://golang.org/doc/code.html][How to Write Go Code]] 249 - [[https://blog.golang.org/organizing-go-code][Organizing Go Code (2012 blog post)]] 250 - [[https://talks.golang.org/2014/organizeio.slide][Organizing Go Code (2014 Google I/O talk)]]