forked from miekg/gobook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
go-packages.tex
374 lines (331 loc) · 15.1 KB
/
go-packages.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
\epi{``\lstinline{^}''}{\textit{Answer to whether there is a bit wise negation
operator.}\\\textsc{KEN THOMPSON}}
\noindent{}Packages are a collection of functions and data.
You declare a package with the
\first{\key{package}}{keyword!package} keyword. The file name does not
have to match the package name.
The convention for package names is to use
lowercase characters.
Go packages may consist of multiple files,
but they share the \lstinline{package <name>} line.
Let's define a package \package{even}\index{package!even} in the file \prog{even.go}.
\lstinputlisting[label=src:even,caption=A small package]{src/even.go}
Names that start with a capital letter are \emph{exported} and may be used
outside your package, more on that later.
Now we just need to build the package. We create a directory under \var{\$GOPATH},
copy the \file{even.go} to there (see ``\titleref{sec:building a program}'' in chapter \ref{chap:basics}).
\begin{display}
\pr \user{mkdir $GOPATH/src/even} \coderemark{Create top-level directory}
\pr \user{cp even.go $GOPATH/src/even} \coderemark{Copy the package file}
\pr \user{go build even} \coderemark{Build it}
\end{display}
Next we can use the package in our own program \prog{myeven.go}:
\lstinputlisting[label=src:myeven,caption=Use of the even package]{src/myeven.go}
\showremarks
\begin{display}
\pr \user{go build myeven.go}
\pr \user{./myeven}
Is 5 even? false
\end{display}
In Go, a function from a package is exported (visible
outside the package, i.e. public) when the first letter of the function name is a capital, hence
the function name \func{\emph{E}ven}. If we change our \prog{myeven.go} on line
10 to using the unexported function \func{even.odd}:
\noindent\lstinline{fmt.Printf("Is %d even? %v\n", i, even.odd(i))}
We get an error when compiling, because we are trying to use a
\emph{private} function:
\begin{display}
myeven.go:10: cannot refer to unexported name even.odd
\end{display}
\noindent{}To summarize:
\begin{itemize}
\item Public functions have a name starting with a \emph{capital}
letter;
\index{public}
\item Private function have a name starting with a \emph{lowercase} letter.
\index{private}
\end{itemize}
This convention also holds true for other names (new types, global
variables) you define in a package. Note that the term ``capital'' is not limited
to US ASCII, it extends into the entire Unicode range. So capital Greek, Coptic, etc. is OK too.
\section{Identifiers}
Names are as important in Go as in any other language. In some cases
they even have semantic effect: for instance, the visibility of a name
outside a package is determined by whether its first character is upper
case. It's therefore worth spending a little time talking about naming
conventions in Go programs.
The convention that is used was to leave well-known legacy
not-quite-words alone rather than try to figure out where
the capital letters go. \lstinline{Atoi}, \lstinline{Getwd},
\lstinline{Chmod}.
Camelcasing works best when you have whole words
to work with: \lstinline{ReadFile, NewWriter, MakeSlice}.
\subsection{Package names}
When a package is imported (with \first{\key{import}}{keyword!import}), the package name becomes
an accessor for the contents. After\index{package!bytes}
\begin{lstlisting}
import "bytes"
\end{lstlisting}
the importing package can talk about \func{bytes.Buffer}. It's helpful if
everyone using the package can use the same name to refer to its
contents, which implies that the package name should be good: short,
concise, and evocative. By convention, packages are given lower case,
single-word names; there should be no need for underscores or mixedCaps.
Err on the side of brevity, since everyone using your package will be
typing that name. And don't worry about collisions a priori. The package
name is only the default name for imports. With the above import
you can use \lstinline{bytes.Buffer}. With
\begin{lstlisting}
import bar "bytes"
\end{lstlisting}
it becomes \lstinline{bar.Buffer}.
So it does need not be unique across
all source code, and in the rare case of a collision the importing
package can choose a different name to use locally. In any case,
confusion is rare because the file name in the import determines just
which package is being used.
Another convention is that the package name is the base name of its
source directory; the package in \package{src/pkg/compress/gzip} is imported as
\var{compress/gzip} but has name \package{gzip}, not
\package{compress\_gzip} and not
\package{compressGzip}.\index{package!compress/gzip}
The importer of a package will use the name to refer to its contents, so
exported names in the package can use that fact to avoid
stutter. For instance, the buffered reader type in the
\package{bufio}\index{package!bufio}
package is
called \func{Reader}, not \func{BufReader}, because users see it as
\func{bufio.Reader},
which is a clear, concise name. Moreover, because imported entities are
always addressed with their package name, \func{bufio.Reader} does not conflict
with \func{io.Reader}. Similarly, the function to make new instances of
\func{ring.Ring} (package \package{container/ring}) ---which is the definition of a constructor in Go---would normally
be called \func{NewRing}, but since \type{Ring} is the only type exported by the
package, and since the package is called
\package{ring}\index{package!ring}, it's called
just \func{New}.
Clients of the package see that as \func{ring.New}. Use the package structure
to help you choose good names.
Another short example is \func{once.Do} (see package \package{sync}); \func{once.Do(setup)} reads well and would
not be improved by writing \lstinline{once.DoOrWaitUntilDone(setup)}. Long names
don't automatically make things more readable. If the name represents
something intricate or subtle, it's usually better to write a helpful
doc comment than to attempt to put all the information into the name.
Finally, the convention in Go is to use \first{MixedCaps}{MixedCaps} or mixedCaps rather
than underscores to write multi-word names.
%% Advanced Go, leave it
%%\section{Initialization}
%%Every source file in a package can define an \func{init()} function. This function is
%%called after the variables in the package have gotten their value. The
%%\func{init()} function can be used to setup state before the execution
%%begins.
\section{Documenting packages}
\gomarginpar{This text is copied from \cite{effective_go}.}
Every package should have a \emph{package comment}, a block comment preceding the
\key{package} clause. For multi-file packages, the package comment only needs to be
present in one file, and any one will do. The package comment should introduce
the package and provide information relevant to the package as a whole. It will
appear first on the \prog{go doc} page and should set up the detailed documentation
that follows. An example from the official \package{regexp} package:
\begin{display}
/*
The regexp package implements a simple library for
regular expressions.
The syntax of the regular expressions accepted is:
regexp:
concatenation { '|' concatenation }
*/
package regexp
\end{display}
Each defined (and exported) function should have a small line of text
documenting the behavior of the function. An example from the \package{fmt}
package:
\begin{display}
// Printf formats according to a format specifier and writes to standard
// output. It returns the number of bytes written and any write error
// encountered.
func Printf(format string, a ...interface{}) (n int, err error)
\end{display}
\section{Testing packages}
In Go it is customary to write (unit) tests for your package. Writing
tests involves the \package{testing} package and the program
\first{\prog{go test}}{tooling!go!test}. Both
have excellent documentation. When you include tests with your package
keep in mind that they have to build using the standard \file{Makefile}
(see section ``\titleref{sec:building a package}'').
%% CLEANFILES+=hello fib chain run.out
%%
The testing itself is carried out with \prog{go test}.
The \prog{go test} program runs all the test functions. Without any
defined tests for our \package{even} package, \prog{go test} yields:
\begin{display}
\pr \user{go test}
? even [no test files]
\end{display}
Let us fix this by defining a test in a test file. Test files reside
in the package directory and are named \file{*\_test.go}. Those test
files are just like other Go programs, but \prog{go test} will only
execute the test functions.
Each test function has the same signature and its name should start
with \lstinline{Test}:
\begin{lstlisting}
func TestXxx(t *testing.T) |\coderemark{Test<Capital>restOftheName}|
\end{lstlisting}
When writing test you will need to tell \prog{go test} that a test has
failed or was successful. A successful test function just returns. When
the test fails you can signal this with the following
functions \cite{go_doc}. These are the most important ones (see \prog{go doc testing}
for more):
\begin{lstlisting}[numbers=none]
func (t *T) Fail()
\end{lstlisting}
\func{Fail} marks the test function as having failed but continues execution.
\begin{lstlisting}[numbers=none]
func (t *T) FailNow()
\end{lstlisting}
\func{FailNow} marks the test function as having failed and stops its execution.
Execution will continue at the next test. So any other test in
\emph{this} file are skipped too.
\begin{lstlisting}[numbers=none]
func (t *T) Log(args ...interface{})
\end{lstlisting}
\func{Log} formats its arguments using default formatting, analogous to
\func{Print()}, and records the text in the error log.
\begin{lstlisting}[numbers=none]
func (t *T) Fatal(args ...interface{})
\end{lstlisting}
\func{Fatal} is equivalent to \func{Log()} followed by \func{FailNow()}.
Putting all this together we can write our test. First
we pick a name: \file{even\_test.go}. Then we add the following contents:
\lstinputlisting[label=src:eventest,caption=Test file for even
package,numbers=right]{src/even_test.go}
Note that we use \lstinline{package even} on line 1, the tests fall in the same
namespace as the package we are testing. This not only convenient, but
also allows tests of unexported function and structures. We then import
the \package{testing} package and on line 5 we define the only test
function in this file. The displayed Go code should not hold any
surprises: we check if the \func{Even} function works OK.
Now, the moment we've been waiting for, executing the test:
\begin{display}
\pr \user{go test}
ok even 0.001s
\end{display}
\noindent{}Our test ran and reported \texttt{ok}. Success!
To show how a failed test looks we redefine our test function:
\begin{lstlisting}
// Entering the twilight zone
func TestEven(t *testing.T) {
if Even(2) {
t.Log("2 should be odd!")
t.Fail()
}
}
\end{lstlisting}
We now get:
\begin{display}
FAIL even 0.004s
--- FAIL: TestEven (0.00 seconds)
\qquad\qquad2 should be odd!
FAIL
\end{display}
\noindent{}And you can act accordingly (by fixing the test for instance).
\begin{lbar}
Writing new packages should go hand in hand with writing (some)
documentation and test functions. It will make your code better and it
shows that you really put in the effort.
\end{lbar}
\section{Useful packages}
The standard Go repository includes a huge number of packages and it is
even possible to install more along side your current Go installation.
It is very enlightening to browse the \file{\$GOROOT/src/pkg} directory and
look at the packages.
We cannot comment on each package, but the following are worth a mention:
\footnote{The descriptions are copied from the packages' \prog{go doc}. Extra
remarks are type set in italic.}
\begin{description}
\item[\package{fmt}]{\index{package!fmt}
Package \package{fmt} implements formatted I/O with functions analogous
to C's \func{printf} and \func{scanf}. The format verbs are derived
from C's but are simpler. Some verbs (\%-sequences) that can be used:
\begin{description}
\item[\%v]{The value in a default format.
when printing structs, the plus flag (\%+v) adds field names;}
\item[\%\#v]{a Go-syntax representation of the value.}
\item[\%T]{a Go-syntax representation of the type of the value;}
\end{description}
}
\item[\package{io}]{\index{package!io}
This package provides basic interfaces to I/O primitives.
Its primary job is to wrap existing implementations of such primitives,
such as those in package os, into shared public interfaces that
abstract the functionality, plus some other related primitives.
}
\item[\package{bufio}]{\index{package!bufio}
This package implements buffered I/O. It wraps an
\lstinline{io.Reader}
or
\lstinline{io.Writer}
object, creating another object (Reader or Writer) that also implements
the interface but provides buffering and some help for textual I/O.
}
\item[\package{sort}]{\index{package!sort}
The \package{sort} package provides primitives for sorting arrays
and user-defined collections.
}
\item[\package{strconv}]{\index{package!strconv}
The \package{strconv} package implements conversions to and from
string representations of basic data types.
}
\item[\package{os}]{\index{package!os}
The \package{os} package provides a platform-independent interface to operating
system functionality. The design is Unix-like.
}
\item[\package{sync}]{\index{package!sync}
The package \package{sync} provides basic synchronization primitives such as mutual
exclusion locks.
}
\item[\package{flag}]{\index{package!flag}
The \package{flag} package implements command-line flag parsing.
\emph{See ``\titleref{sec:option parsing}''
on page \pageref{sec:option parsing}.}
}
\item[\package{json}]{\index{package!json}
The \package{json} package implements encoding and decoding of JSON objects as
defined in RFC 4627 \cite{RFC4627}.
}
\item[\package{template}]{\index{package!template}
Data-driven templates for generating textual output such as HTML.
Templates are executed by applying them to a data structure. Annotations in
the template refer to elements of the data structure (typically a field of a
struct or a key in a map) to control execution and derive values to be
displayed. The template walks the structure as it executes and the ``cursor'' @
represents the value at the current location in the structure.
}
\item[\package{http}]{\index{package!http}
The \package{http} package implements parsing of HTTP requests, replies,
and URLs and provides an extensible HTTP server and a basic
HTTP client.
}
\item[\package{unsafe}]{\index{package!unsafe}
The \package{unsafe} package contains operations that step around the type safety of Go programs.
\emph{Normally you don't need this package.}
}
\item[\package{reflect}]{\index{package!reflect}
The \package{reflect} package implements run-time reflection, allowing a program to
manipulate objects with arbitrary types. The typical use is to take a
value with static type \lstinline|interface{}| and extract its dynamic type
information by calling \func{TypeOf}, which returns an object with interface
type \type{Type}.
\emph{See chapter \ref{chap:interfaces},
section ``\titleref{sec:introspection and reflection}''}.
}
\item[\package{exec}]{\index{package!exec}
The \package{exec} package runs external commands.
}
\end{description}
\section{Exercises}
\input{ex-packages/ex-stack-package.tex}
\input{ex-packages/ex-calc.tex}
\cleardoublepage
\section{Answers}
\shipoutAnswer