# publicmiekg/gobook

### Subversion checkout URL

You can clone with HTTPS or Subversion.

Fetching contributors…

Cannot retrieve contributors at this time

file 362 lines (320 sloc) 13.741 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 \epi{I'm always delighted by the light touch and stillness ofearly programming languages. Not much text; a lot getsdone. Old programs read like quiet conversationsbetween a well-spoken research worker and a well-studied mechanical colleague, not as a debate with acompiler. Who'd have guessed sophistication boughtsuch noise?''}{\textsc{RICHARD P. GABRIEL}}\noindent{}Functions are the basic building blocks of Go programs; all interestingstuff happens in them. A function is declared as follows:\input{fig/function.tex}\showremarksHere are two examples. The first is a function without a return value,while the bottom one is a simple function that returns its input.\begin{lstlisting}func subroutine(in int) { return }\end{lstlisting}\begin{lstlisting}func identity(in int) int { return in }\end{lstlisting}Functions can be declared in any order you wish. The compiler scans theentire file before execution, so function prototyping is a thing of thepast in Go. Go disallows nested functions, but you can work around this withanonymous functions. See section \titleref{sec:functions as values}'' on page\pageref{sec:functions as values} in this chapter.Recursive functions work just as in other languages:\begin{lstlisting}[caption=Recursive function]func rec(i int) {   if i == 10 {        return   }   rec(i+1)   fmt.Printf("%d ", i)}\end{lstlisting}This prints: \texttt{9 8 7 6 5 4 3 2 1 0}.%%\newpage %% TODO don't want a newpage here actually\section{Scope}Variables declared outside any functions are \first{global}{scope!local} in Go, thosedefined in functions are \first{local}{scope!local} to those functions. If names overlap --- alocal variable is declared with the same name as a global one --- thelocal variable hides the global one when the current function isexecuted.\begin{minipage}{.5\textwidth}\input{fig/scope1.tex}\hfill\vfill\end{minipage}\hfill\begin{minipage}{.5\textwidth}\input{fig/scope2.tex}\hfill\vfill\end{minipage}In listing \ref{src:scope1} we introduce a local variable \var{a}in the function \func{q()}.The local \var{a} is only visible in \func{q()}. This iswhy the code will print: \texttt{656}.In listing \ref{src:scope2} no new variables are introduced, thereis only a global \var{a}.Assigning a new value to \var{a} will be globally visible. This code willprint: \texttt{655}In the following example we call \func{g()} from \func{f()}:\lstinputlisting[caption=Scope when calling functions from functions]{src/scope3.go}The output will be: \texttt{565}. A \emph{local} variable is \emph{only}valid when we are executing the function in which it is defined. %%Finally, one can create a \first{"function literal"}{function literal} in which you essentially %%define a function inside another%%function, i.e. a \first{nested function}{nested function}. %%The following figure should clarify why it prints: \texttt{565757}. %%\input{fig/scope3.tex}\section{Multiple return values}\label{sec:multiple return}One of Go's unusual (for compiled languages) features is that functions and methods can return multiplevalues (Python and Perl can do this too). This can be used to improve on a couple of clumsy idioms in C programs:in-band error returns (such as -1 for \texttt{EOF}) and modifying an argument.In Go, \lstinline{Write} returns a count and anerror: Yes, you wrote some bytes but not all of them because you filled thedevice''. The signature of \lstinline{*File.Write} in package\package{os} is:\begin{lstlisting}func (file *File) Write(b []byte) (n int, err error)\end{lstlisting}and as the documentation says, it returns the number of bytes written and anon-\lstinline{nil} \var{error} when \lstinline{n != len(b)}. This is a commonstyle in Go.In the absence of tuples as a native type, multiple return values are the nextbest thing. You can return precisely what you want withoutoverloading the domain space with special values to signal errors.\section{Named result parameters}\label{sec:named result parameters}The return or result parameters of a Go function can be given names and usedas regular variables, just like the incoming parameters. When named, they areinitialized to the zero values for their types when the function begins. If thefunction executes a \key{return} statement with no arguments, the current values ofthe result parameters are returned. Using thesefeatures enables you (again) to do more with less code \footnote{This isa motto of Go; Do \emph{more} with \emph{less} code''}.The names are not mandatory but they can make code shorter and clearer:\emph{they are documentation}. If we name the results of \lstinline{nextInt} it becomes obvious whichreturned \type{int} is which.\begin{lstlisting}func nextInt(b []byte, pos int) (value, nextPos int) { /* ... */ }\end{lstlisting}Because named results are initialized and tied to an unadorned\key{return},they can simplify as well as clarify. Here's a version of\lstinline{io.ReadFull} that uses them well:\begin{lstlisting}func ReadFull(r Reader, buf []byte) (n int, err error) {    for len(buf) > 0 && err == nil {        var nr int        nr, err = r.Read(buf)        n += nr        buf = buf[nr:len(buf)]    }    return}\end{lstlisting}\section{Deferred code}\label{sec:deferred code}Suppose you have a function in which you open a file and perform variouswrites and reads on it. In such a function there are often spots whereyou want to return early. If you do that, you will need to close the filedescriptor you are working on. This often leads to the following code:\begin{lstlisting}[caption=Without defer]func ReadWrite() bool {    file.Open("file")    // Do your thing    if failureX { file.Close() |\coderemark{}| return false    }    if failureY { file.Close() |\coderemark{}| return false    }    file.Close() |\coderemark{}|    return true}\end{lstlisting}A lot of code is repeated here. To overcome this Go has the\first{\key{defer}}{keyword!defer} statement. After\key{defer} you specify a function which is called just \emph{before}the current function exits.The code above could be rewritten as follows. This makes the function more readable, shorter and puts the \func{Close} right next to the \func{Open}.\begin{lstlisting}[caption=With defer]func ReadWrite() bool {    file.Open("file")    defer file.Close() |\coderemark{\func{file.Close()} is added to defer list}|    // Do your thing    if failureX { return false |\coderemark{\func{Close()} is now done automatically}|    }    if failureY { return false |\coderemark{And here too}|    }    return true}\end{lstlisting}You can put multiple functions on the deferred list''\index{deferred list}, like thisexample from \cite{effective_go}:\begin{lstlisting}for i := 0; i < 5; i++ {     defer fmt.Printf("%d ", i) } \end{lstlisting}Deferred functions are executed in LIFO order, so the above codeprints: \lstinline{4 3 2 1 0}. With \func{defer} you can even change return values, provided thatyou are using named result parameters and a functionliteral\index{function!literal}\footnote{A function literalis sometimes called a \index{closure} closure.}, i.e:\begin{lstlisting}[caption=Function literal]defer func() { /* ... */}() |\coderemark{() is needed here}|\end{lstlisting}Or this example which makes it easier to understand why and whereyou need the braces:\begin{lstlisting}[caption=Function literal with parameters]defer func(x int) { /* ... */}(5) |\coderemark{Give the input variable \var{x} the value 5}|\end{lstlisting}In this (unnamed) function you can access any named returnparameter:\begin{lstlisting}[caption=Access return values within defer]func f() (ret int) {|\coderemark{\var{ret} is initialized with zero}| defer func() { ret++|\coderemark{Increment \var{ret} with 1}| }() return 0|\coderemark{1 \emph{not} 0 will be returned!}|}\end{lstlisting}\section{Variadic parameters}Functions that take a variable number of parameters are known as variadic functions.To declare a function as variadic:\begin{lstlisting}func myfunc(arg ...int) {}\end{lstlisting}The \lstinline{arg ...int} instructs Go to see this as a function thattakes a variable number of arguments. Note that these arguments allhave the type \type{int}. Inside your function's body the variable\var{arg} is a slice of ints:\begin{lstlisting}for _, n := range arg {    fmt.Printf("And the number is: %d\n", n)}\end{lstlisting}If you don't specify the type of the variadic argument it defaults to theempty interface \var{interface\{\}} (see chapter\ref{chap:interfaces}).Suppose we have another variadic function called \func{myfunc2}, the following example shows how to pass variadic arguments to it:\begin{lstlisting}func myfunc(arg ...int) {    myfunc2(arg...) |\coderemark{Pass it as-is}|    myfunc2(arg[:2]...) |\coderemark{Slice it}|}\end{lstlisting}\section{Functions as values}\label{sec:functions as values}\index{function!as values}\index{function!literals}As with almost everything in Go, functions are also \emph{just} values.They can be assigned to variables as follows:\lstinputlisting[label=src:anonfunc,caption=Anonymous function,linerange={3,}]{src/anon-func.go}If we use \lstinline{fmt.Printf("%T\n", a)} to print the type of\var{a}, it prints \func{func()}.Functions--as--values may be used in other places, for example maps.Here we convert from integers to functions:\begin{lstlisting}[caption=Functions as values in maps]var xs = map[int]func() int{    1: func() int { return 10 },    2: func() int { return 20 },    3: func() int { return 30 }, |\coderemark{Mandatory ,}|    /* ... */}\end{lstlisting}Or you can write a function that takes a function as its parameter, forexample a \func{Map} function that works on \type{int} slices. This isleft as an exercise for the reader (see exercise Q\ref{ex:map function}on page \pageref{ex:map function}).\section{Callbacks}\label{sec:callbacks}Because functions are values they are easy to pass to functions, from wherethey can be used as callbacks. First define a function thatdoes something'' with an integer value:\begin{lstlisting}func printit(x int) {|\coderemark{Function returns nothing}|    fmt.Printf("%v\n", x)|\coderemark{Just print it}|}\end{lstlisting}The signature of this function is: \lstinline{func printit(int)}, orwithout the function name: \mbox{\lstinline{func(int)}}. To create a new functionthat uses this one as a callback we need to use this signature:\begin{lstlisting}func callback(y int, f func(int)) {|\coderemark{\func{f} has the function}|    f(y) |\coderemark{Call the callback \func{f} with \var{y}}|}\end{lstlisting}\section{Panic and recovering}\label{sec:panic}Go does not have an exception mechanism, like that in Java for instance: you cannot throw exceptions.Instead it uses a panic-and-recover mechanism. It is worth remembering that you should use this asa last resort, your code will not look, or be, better if it is littered with panics. It's a powerful tool:use it wisely. So, how do you use it?The following description was taken from \cite{go_blog_panic}:\begin{description}\item[Panic]{is a built-in function that stops the ordinary flow of control and begins panicking. When the function \func{F} calls \key{panic},execution of \func{F} stops, any deferred functions in \func{F} are executed normally, and then \func{F} returns to its caller. To the caller, \func{F} thenbehaves like a call to \key{panic}. The process continues up the stack until all functions in the current goroutine have returned, at which point the program crashes. Panics can be initiated by invoking \func{panic} directly. They can also be caused by \emph{runtime errors}, suchas out-of-bounds array accesses.}\item[Recover]{is a built-in function that regains control of a panicking goroutine. Recover is \emph{only} useful inside \emph{deferred} functions.During normal execution, a call to \func{recover} will return \type{nil} and have no other effect. If the current goroutine is panicking, a callto \func{recover} will capture the value given to \func{panic} and resume normal execution.}\end{description}This function checks if the function it gets as argument will panic when it isexecuted\footnote{Copied from a presentation of Eleanor McHugh.}:\begin{lstlisting}func throwsPanic(f func()) (b bool) { |\longremark{We define a new function \func{throwsPanic} that takes %a function as an argument (see \titleref{sec:functions as values}''). It returns true if \func{f} panics %when run, else false;}|    defer func() { |\longremark{We define a \func{defer} function that utilizes \func{recover}. If the %current goroutine panics, this defer function will notice that. If \func{recover()} returns non-\var{nil} we set \var{b} %to true;}|        if x := recover(); x != nil {            b = true        }    }()    f() |\longremark{Execute the function we received as the argument;}|    return |\longremark{Return the value of \var{b}. Because \var{b} is a named return parameter (page %\pageref{sec:named result parameters}), we don't specify \var{b}.}|}\end{lstlisting}\showremarks\section{Exercises}\input{ex-functions/ex-average.tex}\input{ex-functions/ex-order.tex}\input{ex-functions/ex-scope.tex}\input{ex-functions/ex-stack.tex}\input{ex-functions/ex-vararg.tex}\input{ex-functions/ex-fib.tex}\input{ex-functions/ex-map.tex}\input{ex-functions/ex-minmax.tex}\input{ex-functions/ex-bubblesort.tex}\input{ex-functions/ex-funcfunc.tex}\cleardoublepage\section{Answers}\shipoutAnswer
Something went wrong with that request. Please try again.