# public miekg /gobook

### Subversion checkout URL

You can clone with HTTPS or Subversion.

Fetching contributors…

Cannot retrieve contributors at this time

file 370 lines (327 sloc) 15.361 kb
 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 \epi{\lstinline{^}''}{\textit{Answer to whether there is a bit wise negationoperator.}\\\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 nothave to match the package name.The convention for package names is to uselowercase characters.Go packages may consist of multiple files,but they share the \lstinline{package } 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 usedoutside 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} \coderemark{Build it}\pr \user{go install} \coderemark{Install it to \file{../pkg}}\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 (visibleoutside the package, i.e. public) when the first letter of the function name is a capital, hencethe function name \func{\emph{E}ven}. If we change our \prog{myeven.go} on line10 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, globalvariables) you define in a package. Note that the term capital'' is not limitedto 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 casesthey even have semantic effect: for instance, the visibility of a nameoutside a package is determined by whether its first character is uppercase. It's therefore worth spending a little time talking about namingconventions in Go programs.The convention that is used was to leave well-known legacynot-quite-words alone rather than try to figure out wherethe capital letters go. \lstinline{Atoi}, \lstinline{Getwd},\lstinline{Chmod}.Camelcasing works best when you have whole wordsto 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 ifeveryone using the package can use the same name to refer to itscontents, 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 betyping that name. And don't worry about collisions a priori. The packagename 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 acrossall source code, and in the rare case of a collision the importingpackage can choose a different name to use locally. In any case,confusion is rare because the file name in the import determines justwhich package is being used.Another convention is that the package name is the base name of itssource 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 avoidstutter. For instance, the buffered reader type in the\package{bufio}\index{package!bufio}package iscalled \func{Reader}, not \func{BufReader}, because users see it as\func{bufio.Reader},which is a clear, concise name. Moreover, because imported entities arealways addressed with their package name, \func{bufio.Reader} does not conflictwith \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 normallybe called \func{NewRing}, but since \type{Ring} is the only type exported by thepackage, and since the package is called\package{ring}\index{package!ring}, it's calledjust \func{New}.Clients of the package see that as \func{ring.New}. Use the package structureto help you choose good names.Another short example is \func{once.Do} (see package \package{sync}); \func{once.Do(setup)} reads well and wouldnot be improved by writing \lstinline{once.DoOrWaitUntilDone(setup)}. Long namesdon't automatically make things more readable. If the name representssomething intricate or subtle, it's usually better to write a helpfuldoc 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 ratherthan 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 bepresent in one file, and any one will do. The package comment should introducethe package and provide information relevant to the package as a whole. It willappear first on the \prog{go doc} page and should set up the detailed documentationthat 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 textdocumenting 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. Writingtests involves the \package{testing} package and the program\first{\prog{go test}}{tooling!go!test}. Bothhave excellent documentation. The \prog{go test} program runs all the test functions. Without anydefined 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 residein the package directory and are named \file{*\_test.go}. Those testfiles are just like other Go programs, but \prog{go test} will onlyexecute the test functions.Each test function has the same signature and its name should startwith \lstinline{Test}:\begin{lstlisting}func TestXxx(t *testing.T) |\coderemark{TestrestOftheName}|\end{lstlisting}When writing test you will need to tell \prog{go test} that a test hasfailed or was successful. A successful test function just returns. Whenthe test fails you can signal this with the followingfunctions \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. Firstwe pick a name: \file{even\_test.go}. Then we add the following contents:\lstinputlisting[label=src:eventest,caption=Test file for evenpackage,numbers=right]{src/even_test.go}Note that we use \lstinline{package even} on line 1, the tests fall in the samenamespace as the package we are testing. This not only convenient, butalso allows tests of unexported function and structures. We then importthe \package{testing} package and on line 5 we define the only testfunction in this file. The displayed Go code should not hold anysurprises: 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 zonefunc 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 itshows that you really put in the effort.\end{lbar}\section{Useful packages}The standard Go repository includes a huge number of packages and it iseven possible to install more along side your current Go installation. It is very enlightening to browse the \file{\$GOROOT/src/pkg} directory andlook 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}. Extraremarks are type set in italic.}\begin{description}\item[\package{fmt}]{\index{package!fmt}Package \package{fmt} implements formatted I/O with functions analogousto C's \func{printf} and \func{scanf}. The format verbs are derivedfrom 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 thatabstract 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 implementsthe 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 arraysand user-defined collections.}\item[\package{strconv}]{\index{package!strconv}The \package{strconv} package implements conversions to and fromstring representations of basic data types.}\item[\package{os}]{\index{package!os}The \package{os} package provides a platform-independent interface to operatingsystem functionality. The design is Unix-like.}\item[\package{sync}]{\index{package!sync}The package \package{sync} provides basic synchronization primitives such as mutualexclusion 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{encoding/json}]{\index{package!encoding/json}The \package{encoding/json} package implements encoding and decoding of JSON objects asdefined in RFC 4627 \cite{RFC4627}.}\item[\package{text/template}]{\index{package!text/template}Data-driven templates for generating textual output such as HTML.Templates are executed by applying them to a data structure. Annotations inthe template refer to elements of the data structure (typically a field of astruct or a key in a map) to control execution and derive values to bedisplayed. The template walks the structure as it executes and the cursor'' @represents the value at the current location in the structure.}\item[\package{net/http}]{\index{package!net/http}The \package{net/http} package implements parsing of HTTP requests, replies,and URLs and provides an extensible HTTP server and a basicHTTP 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 tomanipulate objects with arbitrary types. The typical use is to take avalue with static type \lstinline|interface{}| and extract its dynamic typeinformation by calling \func{TypeOf}, which returns an object with interfacetype \type{Type}.\emph{See chapter \ref{chap:interfaces}, section \titleref{sec:introspection and reflection}''}.}\item[\package{os/exec}]{\index{package!os/exec}The \package{os/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
Something went wrong with that request. Please try again.