├── LICENSE
├── Makefile
├── README.md
├── basics.md
├── beyond.md
├── channels.md
├── communication.md
├── contributors.md
├── ex
├── basics
│ ├── average-no-func.md
│ ├── ex.md
│ ├── fizzbuzz.md
│ ├── for.md
│ ├── src
│ │ ├── fizzbuzz.go
│ │ ├── for-arr.go
│ │ ├── for.go
│ │ ├── string1.go
│ │ ├── string2.go
│ │ ├── string3.go
│ │ └── stringrev.go
│ └── strings.md
├── beyond
│ ├── cat.md
│ ├── doubly-linked-list.md
│ ├── ex.md
│ ├── map.md
│ ├── pointers-method.md
│ ├── pointers.md
│ └── src
│ │ ├── cat.go
│ │ ├── cat2.go
│ │ ├── doubly-linked-list-container.go
│ │ ├── doubly-linked-list.go
│ │ └── map.go
├── channels
│ ├── ex.md
│ ├── fib.md
│ ├── for-channels.md
│ └── src
│ │ ├── fib.go
│ │ ├── for-chan.go
│ │ └── for-quit-chan.go
├── communication
│ ├── copy.md
│ ├── echo.md
│ ├── ex.md
│ ├── finger.md
│ ├── numbercruncher.md
│ ├── processes.md
│ ├── quine.md
│ ├── src
│ │ ├── echo.go
│ │ ├── finger.go
│ │ ├── permrec.go
│ │ ├── proc.go
│ │ ├── proc.pl
│ │ ├── uniq.go
│ │ ├── uniq.pl
│ │ └── wc.go
│ ├── uniq.md
│ └── wordcount.md
├── functions
│ ├── average.md
│ ├── bubblesort.md
│ ├── ex.md
│ ├── fib.md
│ ├── for.md
│ ├── funcfunc.md
│ ├── map.md
│ ├── min.md
│ ├── src
│ │ ├── ave.go
│ │ ├── bubblesort.go
│ │ ├── fib.go
│ │ ├── for-func.go
│ │ ├── queen8.go
│ │ ├── stack-by-value.go
│ │ ├── stack.go
│ │ └── var-arg.go
│ ├── stack.md
│ └── vararg.md
├── interfaces
│ ├── ex.md
│ ├── minmax.md
│ └── pointers-and-reflect.md
└── packages
│ ├── calc.md
│ ├── ex.md
│ ├── src
│ ├── calc.go
│ ├── pushpop_test.go
│ └── stack-as-package.go
│ └── stack-package.md
├── fig
├── array-vs-slice.png
├── array-vs-slice.svg
├── bumper-inverse.png
├── reflection.png
├── reflection.svg
├── stack.png
└── stack.svg
├── functions.md
├── inc
├── bib.xml
├── head.html
├── jquery.waypoints.min.js
├── learninggo.css
├── orderedlist-minimal.css
├── orderedlist-minimal.scale.fix.js
├── prism-bold.css
└── prism.js
├── index.html
├── interfaces.md
├── introduction.md
├── learninggo-2.txt
├── learninggo.md
├── packages.md
├── preface.md
├── src
├── basics
│ ├── array-and-slices.go
│ ├── helloworld.go
│ └── types.go
├── beyond
│ └── struct.go
├── channels
│ ├── for-chan.go
│ ├── for-quit-chan.go
│ └── sleep.go
├── communication
│ ├── buffile.go
│ └── file.go
├── functions
│ └── anon-func.go
└── packages
│ ├── even.go
│ ├── even_test.go
│ └── myeven.go
└── tab
├── conversion.md
├── functions.md
├── keywords.md
└── precedence.md
/LICENSE:
--------------------------------------------------------------------------------
1 | This work is licensed under the Attribution-NonCommercial-ShareAlike 3.0 Unported License. To
2 | view a copy of this license, visit
3 |
4 | or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California,
5 | 94105, USA.
6 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | MMARK=~/src/github.com/mmarkdown/mmark/mmark
2 |
3 | all: learninggo.html
4 |
5 | .PHONY: learninggo.html
6 | learninggo.html:
7 | $(MMARK) -html -head inc/head.html -css inc/learninggo.css learninggo.md > learninggo.html
8 |
9 | .PHONY: learninggo.xml
10 | learninggo.xml:
11 | $(MMARK) learninggo.md > learninggo.xml
12 |
13 | .PHONY: learninggo.txt
14 | learninggo.txt: learninggo.xml
15 | xml2rfc --v3 learninggo.xml
16 |
17 | .PHONY: learninggo-2.xml
18 | learninggo-2.xml:
19 | $(MMARK) -2 learninggo.md > learninggo-2.xml
20 |
21 | .PHONY: learninggo-2.txt
22 | learninggo-2.txt: learninggo-2.xml
23 | xml2rfc --utf8 learninggo-2.xml
24 |
25 | .PHONY: ast
26 | ast:
27 | $(MMARK) -ast learninggo.md
28 |
29 | .PHONY: test
30 | test:
31 | $(MMARK) -html learninggo.md
32 |
33 | clean:
34 | rm -f learninggo.html
35 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Learning Go
2 |
3 | This is the "Learning Go" book in mmark markdown. It is translated
4 | to HTML with [mmark](https://github.com/mmarkdown/mmark).
5 |
6 | After some post processing (with some javascript) [the end result, can be found
7 | here](http://miek.nl/go/learninggo.html).
8 |
9 | ## To Build
10 |
11 | * Download or `go get` [mmark](https://github.com/mmarkdown/mmark).
12 | * `cd `
13 | * `go build`
14 | * `go install` - optional
15 |
16 | And then just `make` in this repository.
17 |
18 | ## Notes
19 |
20 | The stack exercise and solution uses `struct` which are not being dealt with yet.
21 |
--------------------------------------------------------------------------------
/beyond.md:
--------------------------------------------------------------------------------
1 | {.epigraph}
2 | > Go has pointers but not pointer arithmetic. You cannot use a pointer
3 | > variable to walk through the bytes of a string.
4 | ****
5 |
6 | Quote: Go For C++ Programmers -- Go Authors
7 |
8 | In this chapter we delve deeper into the language.
9 |
10 | Go has pointers. There is however no pointer arithmetic, so they act more like
11 | references than pointers that you may know from C. Pointers are useful. Remember
12 | that when you call a function in Go, the variables are
13 | *pass-by-value*. So, for efficiency and the possibility to modify a passed value
14 | *in* functions we have pointers.
15 |
16 | You declare a pointer by prefixing the type with an '`*`': `var p *int`. Now `p`
17 | is a pointer to an integer value. All newly declared variables are assigned
18 | their zero value and pointers are no different. A newly declared pointer, or
19 | just a pointer that points to nothing, has a nil-value (!nil). In other
20 | languages this is often called a NULL pointer in Go it is just `nil`. To make
21 | a pointer point to something you can use the address-of operator
22 | (!operators, address-of) (`&`), which we demonstrate here:
23 |
24 | ~~~go
25 | var p *int
26 | fmt.Printf("%v", p) //<<1>>
27 |
28 | var i int //<<2>>
29 | p = &i //<<3>>
30 |
31 | fmt.Printf("%v", p) //<<4>>
32 | ~~~
33 |
34 | This <<1>> Prints `nil`. Declare <<2>> an integer variable `i`. Make `p` point <<3>>
35 | to `i`, i.e. take the address of `i`. And this <<4>> will print something like
36 | `0x7ff96b81c000a`. De-referencing a pointer is done by prefixing the pointer
37 | variable with `*`.
38 |
39 | As said, there is no pointer arithmetic, so if you write: `*p++`, it is
40 | interpreted as `(*p)++`: first reference and then increment the
41 | value.(!operators, increment)
42 |
43 |
44 | ## Allocation
45 | Go also has garbage collection, meaning that you don't have to worry about
46 | memory deallocation.^[The downside is that you know have to worry about garbage
47 | collection. If you really need it garbage collection in a Go program can be
48 | disabled by running it with the environment variable `GOGC` set to `off`:
49 | `GOGC=off ./myprogram`.]
50 |
51 | To allocate memory Go has two primitives, `new` and `make`. They do different
52 | things and apply to different types, which can be confusing, but the rules are
53 | simple. The following sections show how to handle allocation in Go and hopefully
54 | clarifies the somewhat artificial distinction between `new` (!built-in, new)
55 | and `make` (!built-in,make).
56 |
57 |
58 | ### Allocation with new
59 | The built-in function `new` is essentially the same as its namesakes in other
60 | languages: `new(T)` allocates zeroed storage for a new item of type `T` and
61 | returns its address, a value of type `*T`. Or in other words, it returns
62 | a pointer to a newly allocated zero value of type `T`. This is important to
63 | remember.
64 |
65 | The documentation for `bytes.Buffer` states that "the zero value for Buffer is
66 | an empty buffer ready to use.". Similarly, `sync.Mutex` does not have an
67 | explicit constructor or Init method. Instead, the zero value for a `sync.Mutex`
68 | is defined to be an unlocked mutex.
69 |
70 |
71 | ### Allocation with make
72 | The built-in function `make(T, args)` serves a purpose different from `new(T)`.
73 | It creates slices, maps, and channels *only*, and it returns an initialized (not
74 | zero!) value of type `T`, and not a pointer: `*T`. The reason for the
75 | distinction is that these three types are, under the covers, references to data
76 | structures that must be initialized before use. A slice, for example, is
77 | a three-item descriptor containing a pointer to the data (inside an array), the
78 | length, and the capacity; until those items are initialized, the slice is `nil`.
79 | For slices, maps, and channels, `make` initializes the internal data structure
80 | and prepares the value for use.
81 |
82 | For instance, `make([]int, 10, 100)` allocates an array of 100 ints and then
83 | creates a slice structure with length 10 and a capacity of 100 pointing at the
84 | first 10 elements of the array. In contrast, `new([]int)` returns a pointer to
85 | a newly allocated, zeroed slice structure, that is, a pointer to a `nil` slice
86 | value. These examples illustrate the difference between `new` and `make`.
87 |
88 | ~~~go
89 | var p *[]int = new([]int) //<<1>>
90 | var v []int = make([]int, 100) //<<2>>
91 |
92 | var p *[]int = new([]int) //<<3>>
93 | *p = make([]int, 100, 100)
94 |
95 | v := make([]int, 100) //<<4>>
96 | ~~~
97 |
98 | Allocates <<1>> slice structure; rarely useful. `v` <<2>> refers to a new array of
99 | 100 ints. At <<3>> we make it unnecessarily complex, <<4>> is more idiomatic.
100 |
101 | Remember that `make` applies only to maps, slices and channels and does not
102 | return a pointer. To obtain an explicit pointer allocate with `new`.
103 |
104 | A> **new** allocates; **make** initializes.
105 | A>
106 | A> The above two paragraphs can be summarized as:
107 | A>
108 | A> * `new(T)` returns `*T` pointing to a zeroed `T`
109 | A> * `make(T)` returns an initialized `T`
110 | A>
111 | A> And of course `make` is only used for slices, maps and channels.
112 |
113 |
114 | ### Constructors and composite literals
115 | Sometimes the zero value isn't good enough and an initializing constructor is
116 | necessary, as in this example taken from the package `os`.
117 |
118 | ~~~go
119 | func NewFile(fd int, name string) *File {
120 | if fd < 0 {
121 | return nil
122 | }
123 | f := new(File)
124 | f.fd = fd
125 | f.name = name
126 | f.dirinfo = nil
127 | f.nepipe = 0
128 | return f
129 | }
130 | ~~~
131 |
132 | There's a lot of boiler plate in there. We can simplify it using a
133 | *composite literal* (!literal, composite), which is an expression that
134 | creates a new instance each time it is evaluated.
135 |
136 | ~~~go
137 | func NewFile(fd int, name string) *File {
138 | if fd < 0 {
139 | return nil
140 | }
141 | f := File{fd, name, nil, 0}
142 | return &f //<<1>>
143 | }
144 | ~~~
145 |
146 | It is OK to return the address of a local variable <<1>> the storage associated
147 | with the variable survives after the function returns.
148 |
149 | In fact, taking the address of a composite literal allocates a fresh instance
150 | each time it is evaluated, so we can combine these last two lines.^[Taking the
151 | address of a composite literal tells the compiler to allocate it on the heap,
152 | not the stack.]
153 |
154 | ~~~go
155 | return &File{fd, name, nil, 0}
156 | ~~~
157 |
158 | The items (called fields) of a composite literal are laid out in order and must
159 | all be present. However, by labeling the elements explicitly as field:value
160 | pairs, the initializers can appear in any order, with the missing ones left as
161 | their respective zero values. Thus we could say
162 |
163 | ~~~go
164 | return &File{fd: fd, name: name}
165 | ~~~
166 |
167 | As a limiting case, if a composite literal contains no fields at all, it creates
168 | a zero value for the type. The expressions `new(File)` and `&File{}` are
169 | equivalent. In fact the use of `new` is discouraged.
170 |
171 | Composite literals can also be created for arrays, slices, and maps, with the
172 | field labels being indices or map keys as appropriate. In these examples, the
173 | initializations work regardless of the values of `Enone`, and `Einval`, as long
174 | as they are distinct:
175 |
176 | ~~~go
177 | ar := [...]string{Enone: "no error", Einval: "invalid argument"}
178 | sl := []string{Enone: "no error", Einval: "invalid argument"}
179 | ma := map[int]string {Enone: "no error", Einval: "invalid argument"}
180 | ~~~
181 |
182 |
183 | ## Defining your own types
184 | Of course Go allows you to define new types, it does this with the
185 | `type`(!keywords, type) keyword: `type foo int`
186 |
187 | This creates a new type `foo` which acts like an `int`. Creating more sophisticated
188 | types is done with the `struct` (!keywords, struct) keyword. An example would
189 | be when we want record somebody's name (`string`) and age (`int`) in a single
190 | structure and make it a new type:
191 |
192 | <{{src/beyond/struct.go}}
193 |
194 | Apropos, the output of `fmt.Printf("%v\n", a)` is `&{Pete 42}`
195 |
196 | That is nice! Go knows how to print your structure. If you only want to print
197 | one, or a few, fields of the structure you'll need to use `.`. For
198 | example to only print the name:
199 |
200 | ~~~go
201 | fmt.Printf("%s", a.name)
202 | ~~~
203 |
204 |
205 |
206 | ### More on structure fields
207 | As said each item in a structure is called a field(!field). A struct with no
208 | fields: `struct {}`. Or one with four fields:
209 |
210 | ~~~go
211 | struct {
212 | x, y int
213 | A *[]int
214 | F func()
215 | }
216 | ~~~
217 |
218 | If you omit the name for a field, you create an anonymous field (((field,
219 | anonymous))), for instance:
220 |
221 | ~~~go
222 | struct {
223 | T1 // Field name is T1.
224 | *T2 // Field name is T2.
225 | P.T3 // Field name is T3.
226 | x, y int // Field names are x and y.
227 | }
228 | ~~~
229 |
230 | Note that field names that start with a capital letter are exported, i.e. can be
231 | set or read from other packages. Field names that start with a lowercase are
232 | private to the current package. The same goes for functions defined in packages,
233 | see (#packages) for the details.
234 |
235 |
236 | ### Methods
237 | If you create functions that work on your newly defined type, you can take two
238 | routes:
239 |
240 | 1. Create a function that takes the type as an argument.
241 |
242 | ~~~go
243 | func doSomething(n1 *NameAge, n2 int) { /* */ }
244 | ~~~
245 |
246 | 2. Create a function that works on the type (see *receiver* in (#functions)):
247 |
248 | ~~~go
249 | func (n1 *NameAge) doSomething(n2 int) { /* */ }
250 | ~~~
251 |
252 | This is a method call, which can be used as:
253 |
254 | ~~~go
255 | var n *NameAge
256 | n.doSomething(2)
257 | ~~~
258 |
259 | Whether to use a function or method is entirely up to the programmer, but if you
260 | want to satisfy an interface (see the next chapter) you must use methods. If no
261 | such requirement exists it is a matter of taste whether to use functions or
262 | methods.
263 |
264 | But keep the following in mind, this is quoted from [@go_spec]:
265 |
266 | > If `x` is
267 | > addressable and `&x`'s method set contains `m`,
268 | > `x.m()` is shorthand for `(&x).m()`.
269 |
270 | In the above case this means that the following is *not* an error:
271 |
272 | ~~~go
273 | var n NameAge // Not a pointer
274 | n.doSomething(2)
275 | ~~~
276 |
277 | Here Go will search the method list for `n` of type `NameAge`, come up empty and
278 | will then *also* search the method list for the type `*NameAge` and will
279 | translate this call to `(&n).doSomething(2)`.
280 |
281 | There is a subtle but major difference between the following type declarations.
282 | Also see the Section "Type Declarations" [@go_spec]. Suppose we have:
283 |
284 | ~~~go
285 | // A Mutex is a data type with two methods, Lock and Unlock.
286 | type Mutex struct { /* Mutex fields */ }
287 | func (m *Mutex) Lock() { /* Lock impl. */ }
288 | func (m *Mutex) Unlock() { /* Unlock impl. */ }
289 | ~~~
290 |
291 | We now create two types in two different manners:
292 |
293 | * `type NewMutex Mutex`.
294 | * `type PrintableMutex struct{Mutex}`.
295 |
296 | `NewMutex` is equal to `Mutex`, but it *does not* have *any* of the methods of
297 | `Mutex`. In other words its method set is empty. But `PrintableMutex` *has*
298 | *inherited* (!methods, inherited) the method set from `Mutex`. The Go term
299 | for this is *embedding* (!structures, embed). In the words of [@go_spec]:
300 |
301 | > The method set of `*PrintableMutex` contains the methods
302 | > `Lock` and `Unlock` bound to its anonymous field `Mutex`.
303 |
304 |
305 | ## Conversions
306 | Sometimes you want to convert a type to another type. This is possible in Go,
307 | but there are some rules. For starters, converting from one value to another is
308 | done by operators (that look like functions: `byte()`) and not all conversions
309 | are allowed.
310 |
311 | {#tab-conversion}
312 | {{tab/conversion.md}}
313 |
314 | * From a `string` to a slice of bytes or runes.
315 |
316 | ~~~go
317 | mystring := "hello this is string"
318 | byteslice := []byte(mystring)
319 | ~~~
320 |
321 | Converts to a `byte` slice, each `byte` contains the integer value of the
322 | corresponding byte in the string. Note that as strings in Go are encoded in
323 | UTF-8 some characters in the string may end up in 1, 2, 3 or 4 bytes.
324 |
325 | ~~~go
326 | runeslice := []rune(mystring)
327 | ~~~
328 |
329 | Converts to an `rune` slice, each `rune` contains a Unicode code point.
330 | Every character from the string corresponds to one rune.
331 |
332 | * From a slice of bytes or runes to a `string`.
333 |
334 | ~~~go
335 | b := []byte{'h','e','l','l','o'} // Composite literal.
336 | s := string(b)
337 | i := []rune{257,1024,65}
338 | r := string(i)
339 | ~~~
340 |
341 | For numeric values the following conversions are defined:
342 |
343 | * Convert to an integer with a specific (bit) length: `uint8(int)`
344 | * From floating point to an integer value: `int(float32)`. This discards the
345 | fraction part from the floating point value.
346 | * And the other way around: `float32(int)`.
347 |
348 |
349 | ### User defined types and conversions
350 | How can you convert between the types you have defined yourself? We create two
351 | types here `Foo` and `Bar`, where `Bar` is an alias for `Foo`:
352 |
353 | ~~~go
354 | type foo struct { int } // Anonymous struct field.
355 | type bar foo // bar is an alias for foo.
356 | ~~~
357 |
358 | Then we:
359 |
360 | ~~~go
361 | var b bar = bar{1} // Declare `b` to be a `bar`.
362 | var f foo = b // Assign `b` to `f`.
363 | ~~~
364 |
365 | Which fails on the last line with:
366 | `cannot use b (type bar) as type foo in assignment`
367 |
368 | This can be fixed with a conversion: `var f foo = foo(b)`
369 |
370 | Note that converting structures that are not identical in their fields is more
371 | difficult. Also note that converting `b` to a plain `int` also fails; an integer
372 | is not the same as a structure containing an integer.
373 |
374 | ## Exercises
375 | {{ex/beyond/ex.md}}
376 |
--------------------------------------------------------------------------------
/channels.md:
--------------------------------------------------------------------------------
1 | {.epigraph}
2 | > * Parallelism is about performance.
3 | > * Concurrency is about program design.
4 | >
5 | > ****
6 |
7 | Quote: Google I/O 2010 -- Rob Pike
8 |
9 | In this chapter we will show off Go's ability for concurrent programming using
10 | channels and goroutines. Goroutines are the central entity in Go's ability for
11 | concurrency.
12 |
13 | But what *is* a goroutine, from [@effective_go]:
14 |
15 | > They're called goroutines because the existing terms -- threads, coroutines,
16 | > processes, and so on -- convey inaccurate connotations. A goroutine has a simple
17 | > model: *it is a function executing in parallel with other goroutines in the same
18 | > address space*. It is lightweight, costing little more than the allocation of
19 | > stack space. And the stacks start small, so they are cheap, and grow by
20 | > allocating (and freeing) heap storage as required.
21 |
22 | A goroutine (!goroutine) is a normal function, except that you start
23 | it with the keyword `go`. (!keywords, go)
24 |
25 | ~~~go
26 | ready("Tea", 2) // Normal function call.
27 | go ready("Tea", 2) // ... as goroutine.
28 | ~~~
29 |
30 | <{{src/channels/sleep.go}}[8,18]
31 | Figure: Go routines in action.
32 |
33 | The following idea for a program was taken from [@go_course_day3]. We run
34 | a function as two goroutines, the goroutines wait for an amount of time and then
35 | print something to the screen. At <<1>> we start the goroutines. The `main`
36 | function waits long enough at <<2>>, so that both goroutines will have printed
37 | their text. Right now we wait for 5 seconds, but in fact we have no idea how
38 | long we should wait until all goroutines have exited. This outputs:
39 |
40 | ~~~go
41 | I'm waiting // Right away
42 | Coffee is ready! // After 1 second
43 | Tea is ready! // After 2 seconds
44 | ~~~
45 |
46 | If we did not wait for the goroutines (i.e. remove the last line at <<2>>) the
47 | program would be terminated immediately and any running goroutines would
48 | *die with it*.
49 |
50 | To fix this we need some kind of mechanism which allows us to
51 | communicate with the goroutines. This mechanism is available to us in the form
52 | of channels (!channels). A channel can be compared to a two-way pipe in Unix
53 | shells: you can send to and receive values from it. Those values can only be of
54 | a specific type: the type of the channel. If we define a channel, we must also
55 | define the type of the values we can send on the channel. Note that we must use
56 | `make` to create a channel:
57 |
58 | ~~~go
59 | ci := make(chan int)
60 | cs := make(chan string)
61 | cf := make(chan interface{})
62 | ~~~
63 |
64 | Makes `ci` a channel on which we can send and receive integers,
65 | makes `cs` a channel for strings and `cf` a channel for types
66 | that satisfy the empty interface.
67 | Sending on a channel and receiving from it, is done with the same operator:
68 | `<-`. (!operators, channel)
69 |
70 | Depending on the operands it figures out what to do:
71 |
72 | ~~~go
73 | ci <- 1 // *Send* the integer 1 to the channel ci.
74 | <-ci // *Receive* an integer from the channel ci.
75 | i := <-ci // *Receive* from the channel ci and store it in i.
76 | ~~~
77 |
78 | Let's put this to use.
79 |
80 | ~~~go
81 | var c chan int //<<1>>
82 |
83 | func ready(w string, sec int) {
84 | time.Sleep(time.Duration(sec) * time.Second)
85 | fmt.Println(w, "is ready!")
86 | c <- 1 //<<2>>
87 | }
88 |
89 | func main() {
90 | c = make(chan int) //<<3>>
91 | go ready("Tea", 2) //<<4>>
92 | go ready("Coffee", 1) //<<4>>
93 | fmt.Println("I'm waiting, but not too long")
94 | <-c //<<5>>
95 | <-c //<<5>>
96 | }
97 | ~~~
98 |
99 | At <<1>> we declare `c` to be a variable that is a channel of ints. That is: this
100 | channel can move integers. Note that this variable is global so that the
101 | goroutines have access to it. At <<2>> in the `ready` function we send the integer
102 | 1 on the channel. In our `main` function we initialize `c` at <<3>> and start our
103 | goroutines <<4>>. At <<5>> we Wait until we receive a value from the channel, the
104 | value we receive is discarded. We have started two goroutines, so we expect two
105 | values to receive.
106 |
107 | There is still some remaining ugliness; we have to read twice from the channel
108 | <<5>>). This is OK in this case, but what if we don't know how many goroutines we
109 | started? This is where another Go built-in comes in: `select` (((keywords,
110 | select))). With `select` you can (among other things) listen for incoming data
111 | on a channel.
112 |
113 | Using `select` in our program does not really make it shorter, because we run
114 | too few go-routines. We remove last lines and replace them with the following:
115 |
116 | ~~~go
117 | L: for {
118 | select {
119 | case <-c:
120 | i++
121 | if i > 1 {
122 | break L
123 | }
124 | }
125 | }
126 | ~~~
127 |
128 | We will now wait as long as it takes. Only when we have received more than one
129 | reply on the channel `c` will we exit the loop `L`.
130 |
131 |
132 | ## Make it run in parallel
133 |
134 | While our goroutines were running concurrently, they were not running in
135 | parallel. When you do not tell Go anything there can only be one goroutine
136 | running at a time. With `runtime.GOMAXPROCS(n)` you can set the number of
137 | goroutines that can run in parallel. From the documentation:
138 |
139 | > GOMAXPROCS sets the maximum number of CPUs that can be executing
140 | > simultaneously and returns the previous setting. If n < 1, it does not
141 | > change the current setting. *This call will go away when the scheduler
142 | > improves.*
143 |
144 | If you do not want to change any source code you can also set an environment
145 | variable `GOMAXPROCS` to the desired value.
146 |
147 | Note that the above discussion relates to older versions of Go. From
148 | version 1.5 and above, `GOMAXPROCS` defaults to the number of CPU
149 | cores[@go_1_5_release_notes].
150 |
151 | ## More on channels
152 |
153 | When you create a channel in Go with `ch := make(chan bool)`, an unbuffered
154 | channel (!channel, unbuffered) for bools is created. What does this mean for
155 | your program? For one, if you read (`value := <-ch`) it will block until there
156 | is data to receive. Secondly anything sending (`ch <- true`) will block until there
157 | is somebody to read it. Unbuffered channels make a perfect tool for
158 | synchronizing multiple goroutines. (!channel, blocking read) (!channel, blocking write)
159 |
160 | But Go allows you to specify the buffer size of a channel, which is quite simply
161 | how many elements a channel can hold. `ch := make(chan bool, 4)`, creates
162 | a buffered channel of bools that can hold 4 elements. The first 4 elements in
163 | this channel are written without any blocking. When you write the 5^th^ element,
164 | your code *will* block, until another goroutine reads some elements from the
165 | channel to make room. (!channel, non-blocking read) (!channel, non-blocking write)
166 |
167 | In conclusion, the following is true in Go:
168 |
169 | $$
170 | \textsf{ch := make(chan type, value)}
171 | \left\{
172 | \begin{array}{ll}
173 | value == 0 & \rightarrow \textsf{unbuffered} \\
174 | value > 0 & \rightarrow \textsf{buffer }{} value{} \textsf{ elements}
175 | \end{array}
176 | \right.
177 | $$
178 |
179 | When a channel is closed the reading side needs to know this. The following code
180 | will check if a channel is closed.
181 |
182 | ~~~go
183 | x, ok = <-ch
184 | ~~~
185 |
186 | Where `ok` is set to `true` the channel is not closed
187 | *and* we've read something. Otherwise `ok` is set to `false`. In that case the
188 | channel was closed and the value received is a zero value of the
189 | channel's type.
190 |
191 |
192 | ## Exercises
193 |
194 | {{ex/channels/ex.md}}
195 |
--------------------------------------------------------------------------------
/communication.md:
--------------------------------------------------------------------------------
1 | {.epigraph}
2 | > Good communication is as stimulating as black coffee, and just as hard
3 | > to sleep after.
4 | ****
5 |
6 | Quote: -- Anne Morrow Lindbergh
7 |
8 | In this chapter we are going to look at the building blocks in Go for
9 | communicating with the outside world. We will look at files, directories,
10 | networking and executing other programs. Central to Go's I/O are the interfaces
11 | `io.Reader` and `io.Writer`. The `io.Reader` interface specifies one method
12 | `Read(p []byte) (n int, err err)`.
13 |
14 | Reading from (and writing to) files is easy in Go. This program
15 | only uses the `os` package to read data from the file `/etc/passwd`.
16 |
17 | <{{src/communication/file.go}}
18 |
19 | We open the file at <<1>> with `os.Open` that returns a `*os.File`
20 | `*os.File` implements `io.Reader` and `io.Writer` interface.
21 | After the `Open` we directly put the `f.Close()` which we defer until the function
22 | return. At <<3>> we call `Read` on `f` and read up to 1024 bytes at the time. If anything
23 | fails we bail out at <<4>>. If the number of bytes read is 0 we've read the end of the
24 | file <<5>>. And at <<6>> we output the buffer to standard output.
25 |
26 | If you want to use buffered (!io, buffered) I/O there is the
27 | `bufio`(!package, bufio) package:
28 |
29 | <{{src/communication/buffile.go}}
30 |
31 | Again, we open <<1>> the file. Then at <<2>> we
32 | Turn `f` into a buffered `Reader`. `NewReader` expects an `io.Reader`, so you this will work.
33 | Then at <<4>> we read and at <<5>> we write. We also call `Flush()` at <<3>> to flush all output.
34 | This entire program could be optimized further by using `io.Copy`.
35 |
36 |
37 | ## io.Reader
38 |
39 | As mentioned above the `io.Reader` (!io.Reader) is an important interface in the language Go. A lot
40 | (if not all) functions that need to read from something take an `io.Reader`(!package, io)
41 | as input. To fulfill the interface a type needs to implement that one method.
42 | The writing side `io.Writer`, has the `Write` method.
43 |
44 | If you think of a new type in your program or package and you make it fulfill the `io.Reader`
45 | or `io.Writer` interface, *the whole standard Go library can be used* on that type!
46 |
47 |
48 | ## Some examples
49 |
50 | The previous program reads a file in its entirety, but a more common scenario is that
51 | you want to read a file on a line-by-line basis. The following snippet shows a way
52 | to do just that (we're discarding the error returned from `os.Open` here to keep
53 | the examples smaller -- don't ever do this in real life code).
54 |
55 | ~~~go
56 | f, _ := os.Open("/etc/passwd"); defer f.Close()
57 | r := bufio.NewReader(f) //<<1>>
58 | s, ok := r.ReadString('\n') //<<2>>
59 | ~~~
60 |
61 | At <<1>> make `f` a `bufio` to have access to the `ReadString` method. Then at <<2>> we read
62 | a line from the input, `s` now holds a string which we can manipulate with, for instance,
63 | the `strings` package.
64 |
65 | A more robust method (but slightly more complicated) is `ReadLine`, see the documentation
66 | of the `bufio` package.
67 |
68 | A common scenario in shell scripting is that you want to check if a directory
69 | exists and if not, create one.
70 |
71 | ~~~go
72 | if [ ! -e name ]; then if f, e := os.Stat("name"); e != nil {
73 | mkdir name os.Mkdir("name", 0755)
74 | else } else {
75 | # error // error
76 | fi }
77 | ~~~
78 |
79 | The similarity between these two examples (and with other scripting languages)
80 | have prompted comments that Go has a "script"-like feel to it, i.e. programming
81 | in Go can be compared to programming in an interpreted language (Python, Ruby,
82 | Perl or PHP).
83 |
84 |
85 | ## Command line arguments
86 |
87 | Arguments from the command line are available inside your program via the string
88 | slice `os.Args`, provided you have imported the package `os`. The `flag` package
89 | (!package, flag)
90 | has a more sophisticated interface, and also provides a way to parse flags. Take
91 | this example from a DNS query tool:
92 |
93 | ~~~go
94 | dnssec := flag.Bool("dnssec", false, "Request DNSSEC records") //<<1>>
95 | port := flag.String("port", "53", "Set the query port") //<<2>>
96 | flag.Usage = func() { //<<3>>
97 | fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] [name ...]\n", os.Args[0])
98 | flag.PrintDefaults() //<<4>>
99 | }
100 | flag.Parse() //<<4>>
101 | ~~~
102 |
103 | At <<1>> we define a `bool` flag `-dnssec`. Note that this function returns
104 | a *pointer* to the value, the `dnssec` is now a pointer to a `bool`. At <<2>> we
105 | define an `strings` flag. Then at <<3>> we *redefine* the `Usage` variable of the
106 | flag package so we can add some extra text. The `PrintDefaults` at <<4>> will
107 | output the default help for the flags that are defined. Note even without
108 | redefining a `flag.Usage` the flag `-h` is supported and will just output the help text
109 | for each of the flags. Finally at <<4>> we call `Parse` that parses the command
110 | line and fills the variables.
111 |
112 | After the flags have been parsed you can used them: `if *dnssec { ... }`
113 |
114 |
115 | ## Executing commands
116 |
117 | The `os/exec`(!package,os/exec) package has functions to run external
118 | commands, and is the premier way to execute commands from within a Go program.
119 | It works by defining a `*exec.Cmd` structure for which it defines a number of
120 | methods. Let's execute `ls -l`:
121 |
122 | ~~~go
123 | import "os/exec"
124 |
125 | cmd := exec.Command("/bin/ls", "-l")
126 | err := cmd.Run()
127 | ~~~
128 |
129 | The above example just runs "ls -l" without doing anything with the returned
130 | data, capturing the standard output from a command is done as follows:
131 |
132 | ~~~go
133 | cmd := exec.Command("/bin/ls", "-l")
134 | buf, err := cmd.Output()
135 | ~~~
136 |
137 | And `buf` is byte slice, that you can further use in your program.
138 |
139 |
140 | ## Networking
141 |
142 | All network related types and functions can be found in the package `net`. One
143 | of the most important functions in there is `Dial`(!networking, Dial). When
144 | you `Dial` into a remote system the function returns a `Conn` interface type,
145 | which can be used to send and receive information. The function `Dial` neatly
146 | abstracts away the network family and transport. So IPv4 or IPv6, TCP or UDP can
147 | all share a common interface.
148 |
149 | Dialing a remote system (port 80) over TCP, then UDP and lastly TCP over IPv6
150 | looks like this^[In case you are wondering, 192.0.32.10 and 2620:0:2d0:200::10
151 | are .]:
152 |
153 | ~~~go
154 | conn, e := Dial("tcp", "192.0.32.10:80")
155 | conn, e := Dial("udp", "192.0.32.10:80")
156 | conn, e := Dial("tcp", "[2620:0:2d0:200::10]:80")
157 | ~~~
158 |
159 | If there were no errors (returned in `e`), you can use `conn` to read and write.
160 | And `conn` implements the `io.Reader` and `io.Writer` interface. ^[The variable
161 | `conn` also implements a `close` method, this really makes it an
162 | `io.ReadWriteCloser`.]
163 |
164 | But these are the low level nooks and crannies, you will almost always use
165 | higher level packages, such as the `http` package. For instance a simple Get for
166 | http:
167 |
168 | ~~~go
169 | package main
170 |
171 | import (
172 | "fmt"
173 | "http"
174 | "io/ioutil"
175 | )
176 |
177 | func main() {
178 | r, err := http.Get("http://www.google.com/robots.txt")
179 | if err != nil {
180 | fmt.Printf("%s\n", err.String())
181 | return
182 | }
183 | b, err := ioutil.ReadAll(r.Body)
184 | r.Body.Close()
185 | if err == nil {
186 | fmt.Printf("%s", string(b))
187 | }
188 | }
189 | ~~~
190 |
191 |
192 | ## Exercises
193 |
194 | {{ex/communication/ex.md}}
195 |
--------------------------------------------------------------------------------
/contributors.md:
--------------------------------------------------------------------------------
1 | Adam J. Gray,
2 | Alexander Katasonov,
3 | Alexey Chernenkov,
4 | Alex Sychev,
5 | Andrea Spadaccini,
6 | Andrey Mirtchovski,
7 | Anthony Magro,
8 | Babu Sreekanth,
9 | Ben Bullock,
10 | Bob Cunningham,
11 | Brian Fallik,
12 | Cecil New,
13 | Cobold,
14 | Damian Gryski,
15 | Daniele Pala,
16 | Dan Kortschak,
17 | David Otton,
18 | Fabian Becker,
19 | Filip Zaludek,
20 | Hadi Amiri,
21 | Haiping Fan,
22 | Iaroslav Tymchenko,
23 | Jaap Akkerhuis,
24 | JC van Winkel,
25 | Jeroen Bulten,
26 | Jinpu Hu,
27 | John Shahid,
28 | Jonathan Kans,
29 | Joshua Stein,
30 | Makoto Inoue,
31 | Marco Ynema,
32 | Mayuresh Kathe,
33 | Mem,
34 | Michael Stapelberg,
35 | Nicolas Kaiser,
36 | Olexandr Shalakhin,
37 | Paulo Pinto,
38 | Peter Kleiweg,
39 | Philipp Schmidt,
40 | Robert Johnson,
41 | Russel Winder,
42 | Simoc,
43 | Sonia Keys,
44 | Stefan Schroeder,
45 | Thomas Kapplet,
46 | T.J. Yang,
47 | Uriel$\dagger$,
48 | Vrai Stacey,
49 | Xing Xing.
50 |
--------------------------------------------------------------------------------
/ex/basics/average-no-func.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Average
3 |
4 | 1. Write code to calculate the average of a `float64` slice. In
5 | a later exercise you will make it into a function.
6 |
7 |
8 | {.answer}
9 | ### Answer
10 |
11 | 1. The following code calculates the average.
12 |
13 | ~~~go
14 | sum := 0.0
15 | switch len(xs) {
16 | case 0: //<<1>>
17 | avg = 0
18 | default: //<<2>>
19 | for _, v := range xs {
20 | sum += v
21 | }
22 | avg = sum / float64(len(xs)) //<<3>>
23 | }
24 | ~~~
25 |
26 | Here at <<1>> we check if the length is zero and if so, we return 0.
27 | Otherwise we calculate the average at <<2>>.
28 | We have to convert the value return from `len` to a `float64`
29 | to make the division work at <<3>>.
30 |
--------------------------------------------------------------------------------
/ex/basics/ex.md:
--------------------------------------------------------------------------------
1 | {{for.md}}
2 | {{average-no-func.md}}
3 | {{fizzbuzz.md}}
4 |
--------------------------------------------------------------------------------
/ex/basics/fizzbuzz.md:
--------------------------------------------------------------------------------
1 | {#ex-fizzbuzz .exercise data-difficulty="0"}
2 | ### FizzBuzz
3 |
4 | 1. Solve this problem, called the Fizz-Buzz [@fizzbuzz] problem:
5 |
6 | Write a program that prints the numbers from 1 to 100. But for multiples
7 | of three print, "Fizz" instead of the number, and for multiples of
8 | five, print "Buzz". For numbers which are multiples of both three and
9 | five, print "FizzBuzz".
10 |
11 |
12 | {.answer}
13 | ### Answer
14 | 1. A possible solution to this problem is the following program.
15 |
16 | <{{src/fizzbuzz.go}}
17 |
18 | Here <<1>> we define two constants to make our code more readable, see (#constants).
19 | At <<2>> we define a boolean that keeps track if we already printed something.
20 | At <<3>> we start our for-loop, see (#for).
21 | If the value is divisible by FIZZ - that is, 3 - , we print "Fizz" <<4>>.
22 | And at <<5>> we check if the value is divisble by BUZZ -- that is, 5 -- if so print
23 | "Buzz". Note that we have also taken care of the FizzBuzz case.
24 | At <<6>>, if printed neither Fizz nor Buzz printed, we print the value.
25 |
--------------------------------------------------------------------------------
/ex/basics/for.md:
--------------------------------------------------------------------------------
1 | {.exersice data-difficulty="0"}
2 | ### For-loop
3 |
4 | 1. Create a loop with the `for` construct. Make it loop
5 | 10 times and print out the loop counter with the `fmt` package.
6 |
7 | 2. Rewrite the loop from 1 to use `goto`. The keyword `for` may not be used.
8 |
9 | 3. Rewrite the loop again so that it fills an array and then prints that array to the screen.
10 |
11 |
12 | {.answer}
13 | ### Answer
14 |
15 | 1. There are many possibilities. One solution could be:
16 |
17 | <{{src/for.go}}
18 |
19 | Let's compile this and look at the output.
20 |
21 | % go build for.go
22 | % ./for
23 | 0
24 | 1
25 | .
26 | .
27 | .
28 | 9
29 |
30 | 2. Rewriting the loop results in code that should look something
31 | like this (only showing the `main`-function):
32 |
33 | ~~~go
34 | func main() {
35 | i := 0 //<<1>>
36 | Loop: //<<2>>
37 | if i < 10 {
38 | fmt.Printf("%d\n", i)
39 | i++
40 | goto Loop //<<3>>
41 | }
42 | }
43 | ~~~
44 |
45 | At <<1>> we define our loop variable. And at <<2>> we define a label and at <<3>> we jump
46 | to this label.
47 |
48 | 3. The following is one possible solution:
49 |
50 | <{{src/for-arr.go}}
51 |
52 | Here <<1>> we create an array with 10 elements.
53 | Which we then fill <<2>> one by one. And finally we print it <<3>> with `%v` which lets
54 | Go to print the value for us. You could even do this in one fell swoop by using a composite literal:
55 |
56 | ~~~go
57 | fmt.Printf("%v\n", [...]int{0,1,2,3,4,5,6,7,8,9})
58 | ~~~
59 |
--------------------------------------------------------------------------------
/ex/basics/src/fizzbuzz.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | const (
7 | FIZZ = 3 //<<1>>
8 | BUZZ = 5
9 | )
10 | var p bool //<<2>>
11 | for i := 1; i < 100; i++ { //<<3>>
12 | p = false
13 | if i%FIZZ == 0 { //<<4>>
14 | fmt.Printf("Fizz")
15 | p = true
16 | }
17 | if i%BUZZ == 0 { //<<5>>
18 | fmt.Printf("Buzz")
19 | p = true
20 | }
21 | if !p { //<<6>>
22 | fmt.Printf("%v", i)
23 | }
24 | fmt.Println()
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/ex/basics/src/for-arr.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | var arr [10]int //<<1>>
7 | for i := 0; i < 10; i++ {
8 | arr[i] = i //<<2>>
9 | }
10 | fmt.Printf("%v", arr) //<<3>>
11 | }
12 |
--------------------------------------------------------------------------------
/ex/basics/src/for.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | for i := 0; i < 10; i++ {
7 | fmt.Println("%d", i)
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/ex/basics/src/string1.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | str := "A"
7 | for i := 0; i < 100; i++ {
8 | fmt.Printf("%s\n", str)
9 | str = str + "A"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/ex/basics/src/string2.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "unicode/utf8"
6 | )
7 |
8 | func main() {
9 | str := "I am a Gö programmer."
10 | fmt.Printf("String %s\nLength: %d, Runes: %d\n", str,
11 | len([]byte(str)), utf8.RuneCount([]byte(str)))
12 | }
13 |
--------------------------------------------------------------------------------
/ex/basics/src/string3.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | func main() {
8 | s := "ðåぽ ai no Æl"
9 | r := []rune(s)
10 | copy(r[4:4+3], []rune("abc"))
11 | fmt.Printf("Before: %s\n", s)
12 | fmt.Printf("After : %s\n", string(r))
13 | }
14 |
--------------------------------------------------------------------------------
/ex/basics/src/stringrev.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | s := "foobar"
7 | a := []rune(s) //<<1>>
8 | for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
9 | a[i], a[j] = a[j], a[i] //<<2>>
10 | }
11 | fmt.Printf("%s\n", string(a)) //<<3>>
12 | }
13 |
--------------------------------------------------------------------------------
/ex/basics/strings.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Strings
3 |
4 | 1. Create a Go program that prints the following (up to 100 characters):
5 |
6 | A
7 | AA
8 | AAA
9 | AAAA
10 | AAAAA
11 | AAAAAA
12 | AAAAAAA
13 | ...
14 |
15 | 2. Create a program that counts the number of characters in this string:
16 |
17 | I am a Gő programmer.
18 |
19 | In addition, make it output the number of bytes in that string.
20 | *Hint*: Check out the `utf8` package.
21 |
22 | 3. Extend/change the program from the previous question to replace the three runes at
23 | position 4 with 'abc'.
24 |
25 | 4. Write a Go program that reverses a string, so "foobar" is printed as "raboof".
26 | *Hint*: You will need to know about conversion; skip ahead to (#conversions).
27 |
28 |
29 | {.answer}
30 | ### Answer
31 |
32 | 1. This program is a solution:
33 |
34 | <{{src/string1.go}}
35 |
36 | 2. To answer this question we need some help from
37 | the `unicode/utf8` package. First we check the documentation
38 | with `godoc unicode/utf8 | less`, with has the
39 | `func RuneCount(p []byte) int` function. Secondly
40 | we can convert *string* to a `byte` slice with:
41 |
42 | str := "hello"
43 | b := []byte(str)
44 |
45 | On line 2, we use a conversion. Here we convert a `string`
46 | to a slice of `byte`s. Putting this together leads to the following program.
47 |
48 | <{{src/string2.go}}
49 |
50 | 3. Something along the lines of:
51 |
52 | <{{src/string3.go}}
53 |
54 | 4. Reversing a string can be done as follows. We start from the left (`i`) and
55 | the right (`j`) and swap the characters as we see them:
56 |
57 | <{{stringrev.go}}
58 |
59 | At <<1>> we have a conversion.
60 | At <<2>> we use parallel assignment.
61 | And at <<3>> we convert it back.
62 |
--------------------------------------------------------------------------------
/ex/beyond/cat.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Cat
3 |
4 | 1. Write a program which mimics the Unix program `cat`.
5 |
6 | 2. Make it support the `-n` flag, where each line is numbered.
7 |
8 | 3. The solution to the above question given in contains a bug. Can you spot and fix it?
9 |
10 |
11 | {.answer}
12 | ### Answer
13 | 1. The following is implemention of `cat` which also supports a \-n flag to number each line.
14 |
15 | <{{src/cat.go}}
16 |
17 | At <<1>> we include all the packages we need.
18 | Here <<2>> we define a new flag "n", which defaults to off. Note that we get the help (-h) for free.
19 | Start the function <<3>> that actually reads the file's contents and displays it;
20 | Read one line at the time at <<4>>. And stop <<5>> if we hit the end.
21 | If we should number each line, print the line number and then the line itself <<6>>.
22 | Otherwise <<7>> we could just print the line.
23 |
24 | 2. The bug show itself when the last line of the input does not
25 | contain a newline. Or worse, when the input contains one line without a
26 | closing newline nothing is shown at all. A better solution is the following
27 | program.
28 |
29 | <{{src/cat2.go}}
30 |
--------------------------------------------------------------------------------
/ex/beyond/doubly-linked-list.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Linked List
3 |
4 | 1. Make use of the package `container/list` to create
5 | a (doubly) linked list. Push the values 1, 2 and 4 to the list and then
6 | print it.
7 |
8 | 2. Create your own linked list implementation. And perform the same actions
9 | as above.
10 |
11 | {.answer}
12 | ### Answer
13 | 1. The following is the implementation of a program using doubly
14 | linked lists from `container/list`.
15 |
16 | <{{src/doubly-linked-list-container.go}}
17 |
18 | 2. The following is a program implementing a simple doubly
19 | linked list supporting `int` values.
20 |
21 | <{{src/doubly-linked-list.go}}
22 |
23 | Import <<<1>>> the packages we will need. At <<<2>>> we declare a type for the value our list will contain,
24 | this is not strictly neccesary. And at <<<3>>> we declare a type for the each node in our list.
25 | At <<<4>>> we define the `Front` method for our list.
26 | When pushing, create a new Node <<<5>>> with the provided value. If the list is empty <<<6>>>,
27 | put the new node at the head. Otherwise <<<7>>> put it at the tail and make sure <<<8>>>
28 | the new node points back to the previously existing one. At <<<9>>> we re-adjust tail
29 | to the newly inserted node.
30 |
31 | In the Pop <<10>> method, we return an error if the list is empty. If it is not empty <<11>>
32 | we save the last value. And then <<12>> discard the last node from the list. Finally at <<13>>
33 | we make sure the list is consistent if it becomes empty.
34 |
--------------------------------------------------------------------------------
/ex/beyond/ex.md:
--------------------------------------------------------------------------------
1 | {{map.md}}
2 | {{pointers.md}}
3 | {{doubly-linked-list.md}}
4 | {{cat.md}}
5 | {{pointers-method.md}}
6 |
--------------------------------------------------------------------------------
/ex/beyond/map.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="2"}
2 | ### Map function with interfaces
3 | 1. Use the answer from the earlier map exercise but now
4 | make it generic using interfaces. Make it at least work for
5 | ints and strings.
6 |
7 | {.answer}
8 | ### Answer
9 | 1.
10 |
11 | <{{src/map.go}}
12 |
--------------------------------------------------------------------------------
/ex/beyond/pointers-method.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="2"}
2 | ### Method calls
3 | 1. Suppose we have the following
4 | program. Note the package `container/vector` was once part
5 | of Go, but was removed when the `append` built-in was introduced.
6 | However, for this question this isn't important. The package implemented
7 | a stack-like structure, with push and pop methods.
8 |
9 | ~~~go
10 | package main
11 |
12 | import "container/vector"
13 |
14 | func main() {
15 | k1 := vector.IntVector{}
16 | k2 := &vector.IntVector{}
17 | k3 := new(vector.IntVector)
18 | k1.Push(2)
19 | k2.Push(3)
20 | k3.Push(4)
21 | }
22 | ~~~
23 |
24 | What are the types of `k1`, `k2` and `k3`?
25 |
26 | 2. Now, this program compiles and runs OK. All the `Push`
27 | operations work even though the variables are of a different type. The
28 | documentation for `Push` says:
29 |
30 | > `func (p *IntVector) Push(x int)`
31 | > Push appends x to the end of the vector.
32 |
33 | So the receiver has to be of type `*IntVector`, why does the code
34 | above (the Push statements) work correctly then?
35 |
36 |
37 | {.answer}
38 | ### Answer
39 | 1. The type of `k1` is `vector.IntVector`. Why? We use
40 | a composite literal (the `{}`), so we get a value of that type
41 | back. The variable `k2` is of `*vector.IntVector`, because we
42 | take the address (`&`) of the composite literal. And finally
43 | `k3` has also the type `*vector.IntVector`, because `new`
44 | returns a pointer to the type.
45 |
46 | 2. The answer is given in [@go_spec] in the section "Calls",
47 | where among other things it says:
48 |
49 | > A method call `x.m()` is valid if the method set of (the type of)
50 | > `x`
51 | > contains `m` and the argument list can be assigned to the parameter list
52 | > of `m`. If `x` is addressable and `&x`'s method set
53 | > contains `m`, `x.m()` is shorthand for `(&x).m()`.
54 |
55 | In other words because `k1` is addressable and
56 | `*vector.IntVector` *does* have the `Push` method, the
57 | call `k1.Push(2)` is translated by Go into
58 | `(&k1).Push(2)` which makes the type system happy again (and
59 | you too -- now you know this).^[Also see (#methods) in this chapter.]
60 |
--------------------------------------------------------------------------------
/ex/beyond/pointers.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Pointers
3 |
4 | 1. Suppose we have defined the following structure:
5 |
6 | ~~~go
7 | type Person struct {
8 | name string
9 | age int
10 | }
11 | ~~~
12 |
13 | What is the difference between the following two lines?
14 |
15 | ~~~go
16 | var p1 Person
17 | p2 := new(Person)
18 | ~~~
19 |
20 | 2. What is the difference between the following two allocations?
21 |
22 | ~~~go
23 | func Set(t *T) {
24 | x = t
25 | }
26 | ~~~
27 |
28 | and
29 |
30 | ~~~go
31 | func Set(t T) {
32 | x= &t
33 | }
34 | ~~~
35 |
36 |
37 | {.answer}
38 | ### Answer
39 | 1. The expression, `var p1 Person` allocates a `Person`-*value* to `p1`. The type of `p1` is `Person`.
40 | The second line: `p2 := new(Person)` allocates memory and assigns a *pointer* to `p2`. The type of `p2` is
41 | `*Person`.
42 |
43 | 2. In the first function, `x` points to the same thing that `t` does, which is the same thing that the
44 | actual argument points to. So in the second function, we have an "extra" variable containing a copy of the
45 | interesting value. In the second function, `x` points to a new (heap-allocated) variable `t` which contains
46 | a copy of whatever the actual argument value is.
47 |
--------------------------------------------------------------------------------
/ex/beyond/src/cat.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "flag"
6 | "fmt"
7 | "io" //<<1>>
8 | "os"
9 | )
10 |
11 | var numberFlag = flag.Bool("n", false, "number each line") // <<2>>
12 |
13 | func cat(r *bufio.Reader) { //<<3>>
14 | i := 1
15 | for {
16 | buf, e := r.ReadBytes('\n') //<<4>>
17 | if e == io.EOF { //<<5>>
18 | break
19 | }
20 | if *numberFlag { //<<6>>
21 | fmt.Fprintf(os.Stdout, "%5d %s", i, buf)
22 | i++
23 | } else { //<<7>>
24 | fmt.Fprintf(os.Stdout, "%s", buf)
25 | }
26 | }
27 | return
28 | }
29 |
30 | func main() {
31 | flag.Parse()
32 | if flag.NArg() == 0 {
33 | cat(bufio.NewReader(os.Stdin))
34 | }
35 | for i := 0; i < flag.NArg(); i++ {
36 | f, e := os.Open(flag.Arg(i))
37 | if e != nil {
38 | fmt.Fprintf(os.Stderr, "%s: error reading from %s: %s\n",
39 | os.Args[0], flag.Arg(i), e.Error())
40 | continue
41 | }
42 | cat(bufio.NewReader(f))
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ex/beyond/src/cat2.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "flag"
6 | "fmt"
7 | "io"
8 | "os"
9 | )
10 |
11 | var numberFlag = flag.Bool("n", false, "number each line")
12 |
13 | func cat(r *bufio.Reader) {
14 | i := 1
15 | for {
16 | buf, e := r.ReadBytes('\n')
17 | if e == io.EOF && string(buf) == "" {
18 | break
19 | }
20 | if *numberFlag {
21 | fmt.Fprintf(os.Stdout, "%5d %s", i, buf)
22 | i++
23 | } else {
24 | fmt.Fprintf(os.Stdout, "%s", buf)
25 | }
26 | }
27 | return
28 | }
29 |
30 | func main() {
31 | flag.Parse()
32 | if flag.NArg() == 0 {
33 | cat(bufio.NewReader(os.Stdin))
34 | }
35 | for i := 0; i < flag.NArg(); i++ {
36 | f, e := os.Open(flag.Arg(i))
37 | if e != nil {
38 | fmt.Fprintf(os.Stderr, "%s: error reading from %s: %s\n",
39 | os.Args[0], flag.Arg(i), e.Error())
40 | continue
41 | }
42 | cat(bufio.NewReader(f))
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/ex/beyond/src/doubly-linked-list-container.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "container/list"
5 | "fmt"
6 | )
7 |
8 | func main() {
9 | l := list.New()
10 | l.PushBack(1)
11 | l.PushBack(2)
12 | l.PushBack(4)
13 |
14 | for e := l.Front(); e != nil; e = e.Next() {
15 | fmt.Printf("%v\n", e.Value)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/ex/beyond/src/doubly-linked-list.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "errors" //<<1>>
5 | "fmt"
6 | )
7 |
8 | type Value int //<<2>>
9 |
10 | type Node struct { //<<3>>
11 | Value
12 | prev, next *Node
13 | }
14 |
15 | type List struct {
16 | head, tail *Node
17 | }
18 |
19 | func (l *List) Front() *Node { //<<4>>
20 | return l.head
21 | }
22 |
23 | func (n *Node) Next() *Node {
24 | return n.next
25 | }
26 |
27 | func (l *List) Push(v Value) *List {
28 | n := &Node{Value: v} //<<5>>
29 |
30 | if l.head == nil { //<<6>>
31 | l.head = n
32 | } else {
33 | l.tail.next = n //<<7>>
34 | n.prev = l.tail //<<8>>
35 | }
36 | l.tail = n //<<9>>
37 |
38 | return l
39 | }
40 |
41 | var errEmpty = errors.New("List is empty")
42 |
43 | func (l *List) Pop() (v Value, err error) {
44 | if l.tail == nil { //<<10>>
45 | err = errEmpty
46 | } else {
47 | v = l.tail.Value //<<11>>
48 | l.tail = l.tail.prev //<<12>>
49 | if l.tail == nil {
50 | l.head = nil //<<13>>
51 | }
52 | }
53 |
54 | return v, err
55 | }
56 |
57 | func main() {
58 | l := new(List)
59 |
60 | l.Push(1)
61 | l.Push(2)
62 | l.Push(4)
63 |
64 | for n := l.Front(); n != nil; n = n.Next() {
65 | fmt.Printf("%v\n", n.Value)
66 | }
67 |
68 | fmt.Println()
69 |
70 | for v, err := l.Pop(); err == nil; v, err = l.Pop() {
71 | fmt.Printf("%v\n", v)
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/ex/beyond/src/map.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | // Define the empty interface as a type.
6 | type e interface{}
7 |
8 | func mult2(f e) e {
9 | switch f.(type) {
10 | case int:
11 | return f.(int) * 2
12 | case string:
13 | return f.(string) + f.(string) + f.(string) + f.(string)
14 | }
15 | return f
16 | }
17 |
18 | func Map(n []e, f func(e) e) []e {
19 | m := make([]e, len(n))
20 | for k, v := range n {
21 | m[k] = f(v)
22 | }
23 | return m
24 | }
25 |
26 | func main() {
27 | m := []e{1, 2, 3, 4}
28 | s := []e{"a", "b", "c", "d"}
29 | mf := Map(m, mult2)
30 | sf := Map(s, mult2)
31 | fmt.Printf("%v\n", mf)
32 | fmt.Printf("%v\n", sf)
33 | }
34 |
--------------------------------------------------------------------------------
/ex/channels/ex.md:
--------------------------------------------------------------------------------
1 | {{for-channels.md}}
2 | {{fib.md}}
3 |
--------------------------------------------------------------------------------
/ex/channels/fib.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="2"}
2 | ### Fibonacci II
3 |
4 | This is the same exercise as an earlier one (#fibonacci) in
5 | exercise. For completeness the complete question:
6 |
7 | > The Fibonacci sequence starts as follows: $1, 1, 2, 3, 5, 8, 13, \ldots$
8 | > Or in mathematical terms:
9 | > $x_1 = 1; x_2 = 1; x_n = x_{n-1} + > x_{n-2}\quad\forall n > 2$.
10 | >
11 | > Write a function that takes an `int` value and gives
12 | > that many terms of the Fibonacci sequence.
13 |
14 | *But* now the twist: You must use channels.
15 |
16 | ### Answer
17 |
18 | The following program calculates the Fibonacci numbers using channels.
19 |
20 | <{{src/fib.go}}
21 |
--------------------------------------------------------------------------------
/ex/channels/for-channels.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Channels
3 |
4 | 1. Modify the program you created in exercise (#for-loop) to use
5 | channels, in other words, the function called in the body should now be
6 | a goroutine and communication should happen via channels. You should not
7 | worry yourself on how the goroutine terminates.
8 |
9 | 2. There are a few annoying issues left if you resolve question 1 above. One of
10 | the problems is that the goroutine isn't neatly cleaned up when `main.main()`
11 | exits. And worse, due to a race condition between the exit of `main.main()`
12 | and `main.shower()` not all numbers are printed. It should print up until 9,
13 | but sometimes it prints only to 8. Adding a second quit-channel you can
14 | remedy both issues. Do this.
15 |
16 | ### Answer
17 | 1. A possible program is:
18 |
19 | <{{src/for-chan.go}}
20 |
21 | We start in the usual way, then at line 6 we create a new channel of
22 | ints. In the next line we fire off the function `shower` with
23 | the `ch` variable as it argument, so that we may communicate with
24 | it. Next we start our for-loop (lines 8-10) and in the loop
25 | we send (with `<-`) our number to the function (now a goroutine) `shower`.
26 |
27 | In the function `shower` we wait (as this blocks) until we receive a number
28 | (line 15). Any received number is printed (line 16) and then continue the
29 | endless loop started on line 14.
30 |
31 | 2. An answer is
32 |
33 | <{{src/for-quit-chan.go}}
34 |
35 | On line 20 we read from the quit channel and we discard the value we read. We
36 | could have used `q := <-quit`, but then we would have used the variable only
37 | once --- which is illegal in Go. Another trick you might have pulled out of
38 | your hat may be: `_ = <-quit`. This is valid in Go, but idomatic Go is the
39 | one given on line 20.
40 |
--------------------------------------------------------------------------------
/ex/channels/src/fib.go:
--------------------------------------------------------------------------------
1 | package main
2 | import "fmt"
3 |
4 | func dup3(in <-chan int) (<-chan int, <-chan int, <-chan int) {
5 | a, b, c := make(chan int, 2), make(chan int, 2), make(chan int, 2)
6 | go func() {
7 | for {
8 | x := <-in
9 | a <- x
10 | b <- x
11 | c <- x
12 | }
13 | }()
14 | return a, b, c
15 | }
16 |
17 | func fib() <-chan int {
18 | x := make(chan int, 2)
19 | a, b, out := dup3(x)
20 | go func() {
21 | x <- 0
22 | x <- 1
23 | <-a
24 | for {
25 | x <- <-a+<-b
26 | }
27 | }()
28 | return out
29 | }
30 |
31 | func main() {
32 | x := fib()
33 | for i := 0; i < 10; i++ {
34 | fmt.Println(<-x)
35 | }
36 | }
37 |
38 | // See sdh33b.blogspot.com/2009/12/fibonacci-in-go.html
39 |
--------------------------------------------------------------------------------
/ex/channels/src/for-chan.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | ch := make(chan int)
7 | go shower(ch)
8 | for i := 0; i < 10; i++ {
9 | ch <- i
10 | }
11 | }
12 |
13 | func shower(c chan int) {
14 | for {
15 | j := <-c
16 | fmt.Printf("%d\n", j)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ex/channels/src/for-quit-chan.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | ch := make(chan int)
7 | quit := make(chan bool)
8 | go shower(ch, quit)
9 | for i := 0; i < 10; i++ {
10 | ch <- i
11 | }
12 | quit <- false // or true, does not matter
13 | }
14 |
15 | func shower(c chan int, quit chan bool) {
16 | for {
17 | select {
18 | case j := <-c:
19 | fmt.Printf("%d\n", j)
20 | case <-quit:
21 | break
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ex/communication/copy.md:
--------------------------------------------------------------------------------
1 | # TODO
2 | Use `io.Copy` to optimize the program we started this Chapter with.
3 |
--------------------------------------------------------------------------------
/ex/communication/echo.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Echo server
3 |
4 | Write a simple echo server. Make it listen to TCP port number 8053 on localhost.
5 | It should be able to read a line (up to the newline), echo back that line and
6 | then close the connection.
7 |
8 | Make the server concurrent so that every request is taken care of in a separate
9 | goroutine.
10 |
11 | ### Answer
12 |
13 | A simple echo server might be:
14 |
15 | <{{src/echo.go}}
16 |
17 | When started you should see the following:
18 |
19 | % nc 127.0.0.1 8053
20 | Go is *awesome*
21 | Go is *awesome*
22 |
23 |
24 | To make the connection handling concurrent we *only need to change one line* in our
25 | echo server, the line:
26 |
27 | ~~~go
28 | if c, err := l.Accept(); err == nil { Echo(c) }
29 | ~~~
30 |
31 | becomes:
32 |
33 | ~~~go
34 | if c, err := l.Accept(); err == nil { go Echo(c) }
35 | ~~~
36 |
--------------------------------------------------------------------------------
/ex/communication/ex.md:
--------------------------------------------------------------------------------
1 | {{finger.md}}
2 | {{echo.md}}
3 | {{wordcount.md}}
4 | {{uniq.md}}
5 | {{quine.md}}
6 | {{processes.md}}
7 | {{numbercruncher.md}}
8 |
--------------------------------------------------------------------------------
/ex/communication/finger.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Finger daemon
3 |
4 | Write a finger daemon that works with the finger(1) command.
5 |
6 | From the [Debian](https://www.debian.org) package description:
7 |
8 | > Fingerd is a simple daemon based on RFC 1196 [@RFC1196] that provides an interface to the
9 | > "finger" program at most network sites. The program is supposed to return a
10 | > friendly, human-oriented status report on either the system at the moment or a
11 | > particular person in depth.
12 |
13 |
14 | Stick to the basics and only support a username argument. If the user has a `.plan` file
15 | show the contents of that file. So your program needs to be able to figure out:
16 |
17 | * Does the user exist?
18 | * If the user exists, show the contents of the `.plan` file.
19 |
20 | ### Answer
21 | A> This solution is from Fabian Becker.
22 |
23 | <{{src/finger.go}}
24 |
--------------------------------------------------------------------------------
/ex/communication/numbercruncher.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="2"}
2 | ### Number cruncher
3 |
4 |
5 | * Pick six (6) random numbers from this list: $1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
6 | 25, 50, 75, 100$ Numbers may be picked multiple times.
7 | * Pick one (1) random number ($i$) in the range: $1 \ldots 1000$.
8 | * Tell how, by combining the first 6 numbers (or a subset thereof)
9 | with the operators `+,-,*` and `/`, you can make $i$.
10 |
11 | An example. We have picked the numbers: 1, 6, 7, 8, 8 and 75. And $i$ is
12 | 977. This can be done in many different ways, one way is:
13 | $ ((((1 * 6) * 8) + 75) * 8) - 7 = 977$
14 | or
15 | $ (8*(75+(8*6)))-(7/1) = 977$
16 |
17 | Implement a number cruncher that works like that. Make it print the solution in
18 | a similar format (i.e. output should be infix with parenthesis) as used above.
19 |
20 | Calculate *all* possible solutions and show them (or only show how many there
21 | are). In the example above there are 544 ways to do it.
22 |
23 |
24 | ### Answer
25 |
26 | The following is one possibility. It uses recursion and backtracking to get
27 | an answer. When starting `permrec` we give 977 as the first argument:
28 |
29 |
30 | % ./permrec 977
31 | 1+(((6+7)*75)+(8/8)) = 977 #1
32 | ... ...
33 | ((75+(8*6))*8)-7 = 977 #542
34 | (((75+(8*6))*8)-7)*1 = 977 #543
35 | (((75+(8*6))*8)-7)/1 = 977 #544
36 |
37 |
38 | <{{src/permrec.go}}
39 |
--------------------------------------------------------------------------------
/ex/communication/processes.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="2"}
2 | ### Processes
3 |
4 | Write a program that takes a list of all running processes and prints how many
5 | child processes each parent has spawned. The output should look like:
6 |
7 | Pid 0 has 2 children: [1 2]
8 | Pid 490 has 2 children: [1199 26524]
9 | Pid 1824 has 1 child: [7293]
10 |
11 | * For acquiring the process list, you'll need to capture the output of `ps -e
12 | -opid,ppid,comm`. This output looks like:
13 |
14 | PID PPID COMMAND
15 | 9024 9023 zsh
16 | 19560 9024 ps
17 |
18 | * If a parent has one child you must print `child`, if there is more than one
19 | print `children`.
20 |
21 | * The process list must be numerically sorted, so you start with pid 0 and work
22 | your way up.
23 |
24 | Here is a Perl version to help you on your way (or to create complete and utter confusion).
25 |
26 | <{{src/proc.pl}}
27 |
28 | ### Answer
29 |
30 | There is lots of stuff to do here. We can divide our program
31 | up in the following sections:
32 |
33 | * Starting `ps` and capturing the output.
34 | * Parsing the output and saving the child PIDs for each PPID.
35 | * Sorting the PPID list.
36 | * Printing the sorted list to the screen.
37 |
38 | In the solution presented below, we've used a `map[int][]int`, i.e. a map
39 | indexed with integers, pointing to a slice of ints -- which holds the PIDs. The
40 | builtin `append` is used to grow the integer slice.
41 |
42 | A possible program is:
43 |
44 | <{{src/proc.go}}
45 |
--------------------------------------------------------------------------------
/ex/communication/quine.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="2"}
2 | ### Quine
3 | A *Quine* is a program that prints itself. Write a Quine in Go.
4 |
5 | ### Answer
6 | A> This solution is from Russ Cox. It was posted to the Go Nuts mailing list.
7 |
8 | ~~~go
9 | /* Go quine */
10 | package main
11 | import "fmt"
12 | func main() {
13 | fmt.Printf("%s%c%s%c\n", q, 0x60, q, 0x60)
14 | }
15 | var q = `/* Go quine */
16 | package main
17 | import "fmt"
18 | func main() {
19 | fmt.Printf("%s%c%s%c\n", q, 0x60, q, 0x60)
20 | }
21 | var q = `
22 | ~~~
23 |
--------------------------------------------------------------------------------
/ex/communication/src/echo.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "fmt"
6 | "net"
7 | )
8 |
9 | func main() {
10 | l, err := net.Listen("tcp", "127.0.0.1:8053")
11 | if err != nil {
12 | fmt.Printf("Failure to listen: %s\n", err.Error())
13 | }
14 | for {
15 | if c, err := l.Accept(); err == nil {
16 | Echo(c)
17 | }
18 | }
19 | }
20 |
21 | func Echo(c net.Conn) {
22 | defer c.Close()
23 | line, err := bufio.NewReader(c).ReadString('\n')
24 | if err != nil {
25 | fmt.Printf("Failure to read: %s\n", err.Error())
26 | return
27 | }
28 | _, err = c.Write([]byte(line))
29 | if err != nil {
30 | fmt.Printf("Failure to write: %s\n", err.Error())
31 | return
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/ex/communication/src/finger.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "errors"
6 | "flag"
7 | "io/ioutil"
8 | "net"
9 | "os/user"
10 | )
11 |
12 | func main() {
13 | flag.Parse()
14 | ln, err := net.Listen("tcp", ":79")
15 | if err != nil {
16 | panic(err)
17 | }
18 | for {
19 | conn, err := ln.Accept()
20 | if err != nil {
21 | continue
22 | }
23 | go handleConnection(conn)
24 | }
25 | }
26 |
27 | func handleConnection(conn net.Conn) {
28 | defer conn.Close()
29 | reader := bufio.NewReader(conn)
30 | usr, _, _ := reader.ReadLine()
31 |
32 | if info, err := getUserInfo(string(usr)); err != nil {
33 | conn.Write([]byte(err.Error()))
34 | } else {
35 | conn.Write(info)
36 | }
37 | }
38 |
39 | func getUserInfo(usr string) ([]byte, error) {
40 | u, e := user.Lookup(usr)
41 | if e != nil {
42 | return nil, e
43 | }
44 | data, err := ioutil.ReadFile(u.HomeDir + ".plan")
45 | if err != nil {
46 | return data, errors.New("User doesn't have a .plan file!\n")
47 | }
48 | return data, nil
49 | }
50 |
--------------------------------------------------------------------------------
/ex/communication/src/permrec.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 | "fmt"
6 | "strconv"
7 | )
8 |
9 | const (
10 | _ = 1000 * iota
11 | ADD
12 | SUB
13 | MUL
14 | DIV
15 | MAXPOS = 11
16 | )
17 |
18 | var mop = map[int]string{ADD: "+", SUB: "-", MUL: "*", DIV: "/"}
19 | var (
20 | ok bool
21 | value int
22 | )
23 |
24 | type Stack struct {
25 | i int
26 | data [MAXPOS]int
27 | }
28 |
29 | func (s *Stack) Reset() { s.i = 0 }
30 | func (s *Stack) Len() int { return s.i }
31 | func (s *Stack) Push(k int) { s.data[s.i] = k; s.i++ }
32 | func (s *Stack) Pop() int { s.i--; return s.data[s.i] }
33 |
34 | var found int
35 | var stack = new(Stack)
36 |
37 | func main() {
38 | flag.Parse()
39 | list := []int{1, 6, 7, 8, 8, 75, ADD, SUB, MUL, DIV}
40 | magic, ok := strconv.Atoi(flag.Arg(0)) // Arg0 is i
41 | if ok != nil {
42 | return
43 | }
44 | f := make([]int, MAXPOS)
45 | solve(f, list, 0, magic)
46 | }
47 |
48 | func solve(form, numberop []int, index, magic int) {
49 | var tmp int
50 | for i, v := range numberop {
51 | if v == 0 {
52 | goto NEXT
53 | }
54 | if v < ADD { // it's a number, save it
55 | tmp = numberop[i]
56 | numberop[i] = 0
57 | }
58 | form[index] = v
59 | value, ok = rpncalc(form[0 : index+1])
60 |
61 | if ok && value == magic {
62 | if v < ADD {
63 | numberop[i] = tmp // reset and go on
64 | }
65 | found++
66 | fmt.Printf("%s = %d #%d\n", rpnstr(form[0:index+1]), value, found)
67 | }
68 |
69 | if index == MAXPOS-1 {
70 | if v < ADD {
71 | numberop[i] = tmp // reset and go on
72 | }
73 | goto NEXT
74 | }
75 | solve(form, numberop, index+1, magic)
76 | if v < ADD {
77 | numberop[i] = tmp // reset and go on
78 | }
79 | NEXT:
80 | }
81 | }
82 |
83 | func rpnstr(r []int) (ret string) { // Convert rpn to infix notation
84 | s := make([]string, 0) // Still memory intensive
85 | for k, t := range r {
86 | switch t {
87 | case ADD, SUB, MUL, DIV:
88 | var a, b string
89 | a, s = s[len(s)-1], s[:len(s)-1]
90 | b, s = s[len(s)-1], s[:len(s)-1]
91 | if k == len(r)-1 {
92 | s = append(s, b+mop[t]+a)
93 | } else {
94 | s = append(s, "("+b+mop[t]+a+")")
95 | }
96 | default:
97 | s = append(s, strconv.Itoa(t))
98 | }
99 | }
100 | for _, v := range s {
101 | ret += v
102 | }
103 | return
104 | }
105 |
106 | func rpncalc(r []int) (int, bool) {
107 | stack.Reset()
108 | for _, t := range r {
109 | switch t {
110 | case ADD, SUB, MUL, DIV:
111 | if stack.Len() < 2 {
112 | return 0, false
113 | }
114 | a := stack.Pop()
115 | b := stack.Pop()
116 | if t == ADD {
117 | stack.Push(b + a)
118 | }
119 | if t == SUB {
120 | // disallow negative subresults
121 | if b-a < 0 {
122 | return 0, false
123 | }
124 | stack.Push(b - a)
125 | }
126 | if t == MUL {
127 | stack.Push(b * a)
128 | }
129 | if t == DIV {
130 | if a == 0 {
131 | return 0, false
132 | }
133 | // disallow fractions
134 | if b%a != 0 {
135 | return 0, false
136 | }
137 | stack.Push(b / a)
138 | }
139 | default:
140 | stack.Push(t)
141 | }
142 | }
143 | if stack.Len() == 1 { // there is only one!
144 | return stack.Pop(), true
145 | }
146 | return 0, false
147 | }
148 |
--------------------------------------------------------------------------------
/ex/communication/src/proc.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os/exec"
6 | "sort"
7 | "strconv"
8 | "strings"
9 | )
10 |
11 | func main() {
12 | ps := exec.Command("ps", "-e", "-opid,ppid,comm")
13 | output, _ := ps.Output()
14 | child := make(map[int][]int)
15 | for i, s := range strings.Split(string(output), "\n") {
16 | if i == 0 { // kill first line
17 | continue
18 | }
19 | if len(s) == 0 { // kill last line
20 | continue
21 | }
22 | f := strings.Fields(s)
23 | fpp, _ := strconv.Atoi(f[1]) // parent's pid
24 | fp, _ := strconv.Atoi(f[0]) // child's pid
25 | child[fpp] = append(child[fpp], fp)
26 | }
27 | schild := make([]int, len(child))
28 | i := 0
29 | for k, _ := range child {
30 | schild[i] = k
31 | i++
32 | }
33 | sort.Ints(schild)
34 | for _, ppid := range schild {
35 | fmt.Printf("Pid %d has %d child", ppid, len(child[ppid]))
36 | if len(child[ppid]) == 1 {
37 | fmt.Printf(": %v\n", child[ppid])
38 | continue
39 | }
40 | fmt.Printf("ren: %v\n", child[ppid])
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ex/communication/src/proc.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl -l
2 | my (%child, $pid, $parent);
3 | my @ps=`ps -e -opid,ppid,comm`; # capture the output from `ps`
4 | foreach (@ps[1..$#ps]) { # discard the header line
5 | ($pid, $parent, undef) = split; # split the line, discard 'comm'
6 | push @{$child{$parent}}, $pid; # save the child PIDs on a list
7 | }
8 | # Walk through the sorted PPIDs
9 | foreach (sort { $a <=> $b } keys %child) {
10 | print "Pid ", $_, " has ", @{$child{$_}}+0, " child",
11 | @{$child{$_}} == 1 ? ": " : "ren: ", "[@{$child{$_}}]";
12 | }
13 |
--------------------------------------------------------------------------------
/ex/communication/src/uniq.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | list := []string{"a", "b", "a", "a", "c", "d", "e", "f"}
7 | first := list[0]
8 |
9 | fmt.Printf("%s ", first)
10 | for _, v := range list[1:] {
11 | if first != v {
12 | fmt.Printf("%s ", v)
13 | first = v
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ex/communication/src/uniq.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | my @a = qw/a b a a a c d e f g/;
3 | print my $first = shift @a;
4 | foreach (@a) {
5 | if ($first ne $_) { print; $first = $_; }
6 | }
7 |
--------------------------------------------------------------------------------
/ex/communication/src/wc.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "fmt"
6 | "os"
7 | "strings"
8 | )
9 |
10 | func main() {
11 | var chars, words, lines int
12 | r := bufio.NewReader(os.Stdin) //<<1>>
13 | for {
14 | switch s, ok := r.ReadString('\n'); true { //<<2>>
15 | case ok != nil: //<<3>>
16 | fmt.Printf("%d %d %d\n", chars, words, lines)
17 | return
18 | default: //<<4>>
19 | chars += len(s)
20 | words += len(strings.Fields(s))
21 | lines++
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/ex/communication/uniq.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="0"}
2 | ### Uniq
3 |
4 | Write a Go program that mimics the function of the Unix `uniq` command. This
5 | program should work as follows, given a list with the following items:
6 |
7 | 'a' 'b' 'a' 'a' 'a' 'c' 'd' 'e' 'f' 'g'
8 |
9 | it should print only those items which don't have the same successor:
10 |
11 | 'a' 'b' 'a' 'c' 'd' 'e' 'f' 'g'
12 |
13 | The next listing is a Perl implementation of the algorithm.
14 |
15 | <{{src/uniq.pl}}
16 |
17 | ### Answer
18 |
19 | The following is a `uniq` implementation in Go.
20 |
21 | <{{src/uniq.go}}
22 |
--------------------------------------------------------------------------------
/ex/communication/wordcount.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="0"}
2 | ### Word and Letter Count
3 |
4 | Write a small program that reads text from standard input and performs the
5 | following actions:
6 |
7 | * Count the number of characters (including spaces).
8 | * Count the number of words.
9 | * Count the numbers of lines
10 |
11 | In other words implement wc(1) (check you local manual page), however you only
12 | have to read from standard input.
13 |
14 |
15 | ### Answer
16 |
17 | The following program is an implementation of wc(1).
18 |
19 | <{{src/wc.go}}
20 |
21 | At <<1>> we create a new reader that reads from standard input, we then read from
22 | the input at <<2>>. And at <<3>> we check the value of `ok` and if we received an
23 | error, we assume it was because of a EOF, So we print the current values;.
24 | Otherwise <<4>> we count the charaters, words and increment the number lines.
25 |
--------------------------------------------------------------------------------
/ex/functions/average.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="0"}
2 | ### Average
3 | 1. Write a function that calculates the average of a `float64` slice.
4 |
5 |
6 | {.answer}
7 | ### Answer
8 | 1. The following function calculates the average:
9 |
10 | <{{src/ave.go}}
11 |
12 | At <<1>> we use a named return parameter. If the length of `xs` is zero <<2>>, we
13 | return 0. Otherwise <<3>>, we calculate the average. At <<4>> we convert the
14 | value to a `float64` to make the division work as `len` returns an `int`.
15 | Finally, at <<5>> we reutrn our avarage.
16 |
--------------------------------------------------------------------------------
/ex/functions/bubblesort.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Bubble sort
3 | 1. Write a function that performs a bubble sort on a slice of ints. From [@bubblesort]:
4 |
5 | > It works by repeatedly stepping through the list to be sorted, comparing each
6 | > pair of adjacent items and swapping them if they are in the wrong order. The
7 | > pass through the list is repeated until no swaps are needed, which indicates
8 | > that the list is sorted. The algorithm gets its name from the way smaller
9 | > elements "bubble" to the top of the list.
10 |
11 | It also gives an example in pseudo code:
12 |
13 | procedure bubbleSort( A : list of sortable items )
14 | do
15 | swapped = false
16 | for each i in 1 to length(A) - 1 inclusive do:
17 | if A[i-1] > A[i] then
18 | swap( A[i-1], A[i] )
19 | swapped = true
20 | end if
21 | end for
22 | while swapped
23 | end procedure
24 |
25 | ### Answer
26 |
27 | 1. Bubble sort isn't terribly efficient. For $n$ elements it scales $O(n^2)$.
28 | But bubble sort is easy to implement:
29 |
30 | <{{src/bubblesort.go}}[4,18]
31 |
32 | Because a slice is a reference type, the `bubblesort` function works and
33 | does not need to return a sorted slice.
34 |
--------------------------------------------------------------------------------
/ex/functions/ex.md:
--------------------------------------------------------------------------------
1 | {{average.md}}
2 | {{bubblesort.md}}
3 | {{for.md}}
4 | {{fib.md}}
5 | {{vararg.md}}
6 | {{funcfunc.md}}
7 | {{min.md}}
8 | {{map.md}}
9 | {{stack.md}}
10 |
--------------------------------------------------------------------------------
/ex/functions/fib.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Fibonacci
3 |
4 | 1. The Fibonacci sequence starts as follows: $1, 1, 2, 3, 5, 8, 13, \ldots$
5 | Or in mathematical terms: $x_1 = 1; x_2 = 1; x_n = x_{n-1} + x_{n-2}\quad\forall n > 2$.
6 |
7 | Write a function that takes an `int` value and gives
8 | that many terms of the Fibonacci sequence.
9 |
10 |
11 | {.answer}
12 | ### Answer
13 | 1. The following program calculates Fibonacci numbers:
14 |
15 | <{{src/fib.go}}
16 |
17 | At <<1>> we create an array to hold the integers up to the value given in
18 | the function call. At <<2>> we start the Fibonacci calculation. Then <<3>>:
19 | $x_n = x_{n-1} + x_{n-2}$. At <<4>> we return the *entire* array.
20 | And at <<5>> we use the `range` keyword to "walk" the numbers returned by the
21 | Fibonacci function. Here up to 10. Finally, we print the numbers.
22 |
--------------------------------------------------------------------------------
/ex/functions/for.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="0"}
2 | ### For-loop II
3 | 1. Take what you did in exercise to write the for loop and extend it a bit.
4 | Put the body of the for loop - the `fmt.Printf` - in a separate function.
5 |
6 |
7 | {.answer}
8 | ### Answer
9 |
10 | 1.
11 |
12 | <{{src/for-func.go}}
13 |
--------------------------------------------------------------------------------
/ex/functions/funcfunc.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Functions that return functions
3 |
4 | 1. Write a function that returns a function that performs a $+2$ on integers. Name the function `plusTwo`.
5 | You should then be able do the following:
6 |
7 | ~~~go
8 | p := plusTwo()
9 | fmt.Printf("%v\n", p(2))
10 | ~~~
11 |
12 | Which should print 4. See (#callbacks).
13 |
14 | 2. Generalize the function from above and create a `plusX(x)` which returns functions that add `x` to an integer.
15 |
16 |
17 | {.answer}
18 | ### Answer
19 | 1. Define a new function that returns a function: `return func(x int) int { return x + 2 }`
20 | Function literals at work, we define the +2--function right there in the return statement.
21 |
22 | ~~~go
23 | func main() {
24 | p2 := plusTwo()
25 | fmt.Printf("%v\n",p2(2))
26 | }
27 |
28 | func plusTwo() func(int) int { //<<1>>
29 | return func(x int) int { return x + 2 } //<<2>>
30 | }
31 | ~~~
32 |
33 | 2. Here we use a closure:
34 |
35 | ~~~go
36 | func plusX(x int) func(int) int { //<<1>>
37 | return func(y int) int { return x + y } //<<2>>
38 | }
39 | ~~~
40 |
41 | Here <<1>>, we again define a function that returns a function.
42 | We use the *local* variable `x` in the function literal at <<2>>.
43 |
--------------------------------------------------------------------------------
/ex/functions/map.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Map function
3 |
4 | A `map()`-function is a function that takes
5 | a function and a list. The function is applied to
6 | each member in the list and a new list containing
7 | these calculated values is returned.
8 | Thus:
9 |
10 | $ \mathrm{map}(f(), (a_1,a_2,\ldots,a_{n-1},a_n)) = (f(a_1), f(a_2),\ldots,f(a_{n-1}), f(a_n)) $
11 |
12 | 1. Write a simple
13 | `map()`-function in Go. It is sufficient for this function only to work for ints.
14 |
15 |
16 | {.answer}
17 | ### Answer
18 |
19 | 1. A possible answer:
20 |
21 | ~~~go
22 | func Map(f func(int) int, l []int) []int {
23 | j := make([]int, len(l))
24 | for k, v := range l {
25 | j[k] = f(v)
26 | }
27 | return j
28 | }
29 |
30 | func main() {
31 | m := []int{1, 3, 4}
32 | f := func(i int) int {
33 | return i * i
34 | }
35 | fmt.Printf("%v", (Map(f, m)))
36 | }
37 | ~~~
38 |
--------------------------------------------------------------------------------
/ex/functions/min.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="0"}
2 | ### Maximum
3 | 1. Write a function that finds the
4 | maximum value in an `int` slice (`[]int`).
5 |
6 |
7 | {.answer}
8 | ### Answer
9 | 1. This function returns the largest int in the slice \var{l}:
10 |
11 | ~~~go
12 | func max(l []int) (max int) { //<<1>>
13 | max = l[0]
14 | for _, v := range l { //<<2>>
15 | if v > max { //<<3>>
16 | max = v
17 | }
18 | }
19 | return //<<4>>
20 | }
21 | ~~~
22 |
23 | At <<1>> we use a named return parameter.
24 | At <<2>> we loop over `l`. The index of the element is not important.
25 | At <<3>>, if we find a new maximum, we remember it.
26 | And at <<4>> we have a "lone" return; the current value of `max` is now returned.
27 |
--------------------------------------------------------------------------------
/ex/functions/src/ave.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func average(xs []float64) (avg float64) { //<1>
4 | sum := 0.0
5 | switch len(xs) {
6 | case 0: //<2>
7 | avg = 0
8 | default: //<3>
9 | for _, v := range xs {
10 | sum += v
11 | }
12 | avg = sum / float64(len(xs)) //<4>
13 | }
14 | return //<5>
15 | }
16 |
--------------------------------------------------------------------------------
/ex/functions/src/bubblesort.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | n := []int{5, -1, 0, 12, 3, 5}
7 | fmt.Printf("unsorted %v\n", n)
8 | bubblesort(n)
9 | fmt.Printf("sorted %v\n", n)
10 | }
11 |
12 | func bubblesort(n []int) {
13 | for i := 0; i < len(n)-1; i++ {
14 | for j := i + 1; j < len(n); j++ {
15 | if n[j] < n[i] {
16 | n[i], n[j] = n[j], n[i]
17 | }
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/ex/functions/src/fib.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func fibonacci(value int) []int {
6 | x := make([]int, value) //<<1>>
7 | x[0], x[1] = 1, 1 //<<2>>
8 | for n := 2; n < value; n++ {
9 | x[n] = x[n-1] + x[n-2] //<<3>>
10 | }
11 | return x //<<4>>
12 | }
13 |
14 | func main() {
15 | for _, term := range fibonacci(10) { //<<5>>
16 | fmt.Printf("%v ", term)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/ex/functions/src/for-func.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | for i := 0; i < 10; i++ {
7 | show(i)
8 | }
9 | }
10 |
11 | func show(j int) {
12 | fmt.Printf("%d\n", j)
13 | }
14 |
--------------------------------------------------------------------------------
/ex/functions/src/queen8.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | )
6 |
7 | const (
8 | size = 8
9 | norm = size - 1
10 | )
11 |
12 | var B = [size][size]string{
13 | {".", ".", ".", ".", ".", ".", ".", "."},
14 | {".", ".", ".", ".", ".", ".", ".", "."},
15 | {".", ".", ".", ".", ".", ".", ".", "."},
16 | {".", ".", ".", ".", ".", ".", ".", "."},
17 | {".", ".", ".", ".", ".", ".", ".", "."},
18 | {".", ".", ".", ".", ".", ".", ".", "."},
19 | {".", ".", ".", ".", ".", ".", ".", "."},
20 | {".", ".", ".", ".", ".", ".", ".", "."}}
21 |
22 | var leftdiag [size*2 - 1]bool
23 | var rightdiag [size*2 - 1]bool
24 | var col [size]bool
25 |
26 | func main() {
27 | tryQueen(0)
28 | }
29 |
30 | func tryQueen(x int) {
31 | for y := 0; y < size; y++ {
32 | if col[y] == false && leftdiag[x-y+norm] == false && rightdiag[x+y] == false {
33 | B[y][x] = "Q" // reverse coordinates so it prints correctly
34 | col[y] = true
35 | leftdiag[x-y+norm] = true
36 | rightdiag[x+y] = true
37 | if x < size-1 {
38 | tryQueen(x + 1)
39 | } else {
40 | fmt.Printf("Solution found\n%s", func() string {
41 | s := ""
42 | for i := 0; i < 8; i++ {
43 | for j := 0; j < 8; j++ {
44 | s += B[i][j]
45 | }
46 | s += "\n"
47 | }
48 | return s
49 | }())
50 | return
51 | }
52 | B[y][x] = "."
53 | col[y] = false
54 | leftdiag[x-y+norm] = false
55 | rightdiag[x+y] = false
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/ex/functions/src/stack-by-value.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "strconv"
6 | )
7 |
8 | type stack struct {
9 | i int
10 | data [10]int
11 | }
12 |
13 | func (s stack) push(k int) {
14 | s.data[s.i] = k
15 | s.i++
16 | }
17 |
18 | func (s stack) pop() int {
19 | s.i--
20 | return s.data[s.i]
21 | }
22 |
23 | func (s stack) String() string {
24 | var str string
25 | for i := 0; i <= s.i; i++ {
26 | str = str + "[" +
27 | strconv.Itoa(i) + ":" + strconv.Itoa(s.data[i]) + "]"
28 | }
29 | return str
30 | }
31 |
32 | func main() {
33 | var s stack
34 | s.push(25)
35 | s.push(14)
36 | fmt.Printf("stack %v\n", s)
37 | }
38 |
--------------------------------------------------------------------------------
/ex/functions/src/stack.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "strconv"
6 | )
7 |
8 | type stack struct {
9 | i int
10 | data [10]int
11 | }
12 |
13 | func (s *stack) push(k int) {
14 | s.data[s.i] = k
15 | s.i++
16 | }
17 |
18 | func (s *stack) pop() int {
19 | s.i--
20 | return s.data[s.i]
21 | }
22 |
23 | func (s *stack) String() string {
24 | var str string
25 | for i := 0; i < s.i; i++ {
26 | str = str + "[" +
27 | strconv.Itoa(i) + ":" + strconv.Itoa(s.data[i]) + "]"
28 | }
29 | return str
30 | }
31 |
32 | func main() {
33 | s := new(stack) // returns pointer!
34 | s.push(25)
35 | s.push(14)
36 | fmt.Printf("stack %v\n", s)
37 | }
38 |
--------------------------------------------------------------------------------
/ex/functions/src/var-arg.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | printthem(1, 4, 5, 7, 4)
7 | printthem(1, 2, 4)
8 | }
9 |
10 | func printthem(numbers ...int) {
11 | for _, d := range numbers {
12 | fmt.Printf("%d\n", d)
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/ex/functions/stack.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Stack
3 | 1. Create a simple stack which can hold a
4 | fixed number of ints. It does not have to grow beyond this limit.
5 | Define `push` -- put something on the stack -- and `pop`
6 | -- retrieve something from the stack -- functions. The stack should be
7 | a LIFO (last in, first out) stack.
8 |
9 | !---
10 | 
11 | !---
12 | Figure: A stack.
13 |
14 | 2. Write a `String` method which
15 | converts the stack to a string representation.
16 | The stack in the figure could be represented as: `[0:m] [1:l] [2:k]` .
17 |
18 |
19 | {.answer}
20 | ### Answer
21 |
22 | 1. First we define a new type that represents a stack; we need an
23 | array (to hold the keys) and an index, which points to the last element.
24 | Our small stack can only hold 10 elements.
25 |
26 | ~~~go
27 | type stack struct {
28 | i int
29 | data [10]int
30 | }
31 | ~~~
32 |
33 | Next we need the `push` and `pop` functions to actually
34 | use the thing. First we show the *wrong* solution!
35 |
36 | In Go, data passed to functions is *passed-by-value* meaning a copy
37 | is created and given to the function. The first stab for the function
38 | `push` could be:
39 |
40 | ~~~go
41 | func (s stack) push(k int) {
42 | if s.i+1 > 9 {
43 | return
44 | }
45 | s.data[s.i] = k
46 | s.i++
47 | }
48 | ~~~
49 |
50 | The function works on the `s` which is of the type `stack`. To
51 | use this we just call `s.push(50)`, to push the integer 50 on
52 | the stack. But the push function gets a copy of `s`, so it is
53 | *not* working on the *real* thing. Nothing gets pushed to our
54 | stack. For example the following code:
55 |
56 | ~~~go
57 | var s stack
58 | s.push(25)
59 | fmt.Printf("stack %v\n", s);
60 | s.push(14)
61 | fmt.Printf("stack %v\n", s);
62 | ~~~
63 |
64 | prints:
65 |
66 | stack [0:0]
67 | stack [0:0]
68 |
69 | To solve this we need to give the function `push` a pointer
70 | to the stack. This means we need to change `push` from
71 |
72 | ~~~go
73 | func (s stack) push(k int)
74 | ~~~
75 |
76 | to
77 |
78 | ~~~go
79 | func (s *stack) push(k int).
80 | ~~~
81 |
82 | We should now use `new()` (see (#allocation-with-new)).
83 | in (#beyond-the-basics) to create a *pointer* to a newly
84 | allocated `stack`, so line 1 from the example above needs to be
85 | `s := new(stack)` .
86 |
87 | And our two functions become:
88 |
89 | ~~~go
90 | func (s *stack) push(k int) {
91 | s.data[s.i] = k
92 | s.i++
93 | }
94 |
95 | func (s *stack) pop() int {
96 | s.i--
97 | ret := s.data[s.i]
98 | s.data[s.i] = 0
99 | return ret
100 | }
101 | ~~~
102 |
103 | Which we then use as follows:
104 |
105 | ~~~go
106 | func main() {
107 | var s stack
108 | s.push(25)
109 | s.push(14)
110 | fmt.Printf("stack %v\n", s)
111 | }
112 | ~~~
113 |
114 | 2. `fmt.Printf("%v")` can
115 | print any value (`%v`) that satisfies the `Stringer` interface
116 | (see (#interfaces)).
117 | For this to work we only need to define a `String()` function for
118 | our type:
119 |
120 | ~~~go
121 | func (s stack) String() string {
122 | var str string
123 | for i := 0; i <= s.i; i++ {
124 | str = str + "[" +
125 | strconv.Itoa(i) + ":" + strconv.Itoa(s.data[i]) + "]"
126 | }
127 | return str
128 | }
129 | ~~~
130 |
--------------------------------------------------------------------------------
/ex/functions/vararg.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Var args
3 |
4 | 1. Write a function that takes a variable number of ints and print each integer on a separate line.
5 |
6 |
7 | ### Answer
8 | 1. For this we need the `{...}`-syntax to signal we define a
9 | function that takes an arbitrary number of arguments.
10 |
11 | <{{src/var-arg.go}}
12 |
--------------------------------------------------------------------------------
/ex/interfaces/ex.md:
--------------------------------------------------------------------------------
1 | {{minmax.md}}
2 | {{pointers-and-reflect.md}}
3 |
--------------------------------------------------------------------------------
/ex/interfaces/minmax.md:
--------------------------------------------------------------------------------
1 | {.exercise data-dificulty="2"}
2 | ### Interfaces and max()
3 |
4 | In the maximum exercise we created a max function that works on a slice of
5 | integers. The question now is to create a program that shows the maximum number
6 | and that works for both integers and floats. Try to make your program as
7 | generic as possible, although that is quite difficult in this case.
8 |
9 | ### Answer
10 |
11 | The following program calculates a maximum. It is as generic as you can get with
12 | Go.
13 |
14 | ~~~go
15 | package main
16 |
17 | import "fmt"
18 |
19 | func Less(l, r interface{}) bool { //<<1>>
20 | switch l.(type) {
21 | case int:
22 | if _, ok := r.(int); ok {
23 | return l.(int) < r.(int) //<<2>>
24 | }
25 | case float32:
26 | if _, ok := r.(float32); ok {
27 | return l.(float32) < r.(float32) //<<3>>
28 | }
29 | }
30 | return false
31 | }
32 |
33 | func main() {
34 | var a, b, c int = 5, 15, 0
35 | var x, y, z float32 = 5.4, 29.3, 0.0
36 |
37 | if c = a; Less(a, b) { //<<4>>
38 | c = b
39 | }
40 | if z = x; Less(x, y) { //<<4>>
41 | z = y
42 | }
43 | fmt.Println(c, z)
44 | }
45 | ~~~
46 |
47 | We could have chosen to make the return type of this <<1>> function an
48 | `interface{}`, but that would mean that a caller would always have to do a type
49 | assertion to extract the actual type from the interface. At <<2>> we compare the
50 | parameters. All parameters are confirmed to be integers, so this is legit. And
51 | at <<3>> we do the some for floats. At <<4>> we get the maximum value for `a`, `b`
52 | and `x` and `y`.
53 |
--------------------------------------------------------------------------------
/ex/interfaces/pointers-and-reflect.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="1"}
2 | ### Pointers and reflection
3 |
4 | One of the last paragraphs in section (#introspection-and-reflection)
5 | has the following words:
6 |
7 | > The code on the right works OK and sets the member `Name`
8 | > to "Albert Einstein". Of course this only works when you call `Set()`
9 | > with a pointer argument.
10 |
11 | Why is this the case?
12 |
13 | ### Answer
14 |
15 | When called with a non-pointer argument the variable is a copy (call-by-value).
16 | So you are doing the reflection voodoo on a copy. And thus you are *not*
17 | changing the original value, but only this copy.
18 |
--------------------------------------------------------------------------------
/ex/packages/calc.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="2"}
2 | ### Calculator
3 | 1. Create a reverse polish calculator. Use your stack package.
4 |
5 |
6 | {.answer}
7 | ### Answer
8 | 1. This is one answer:
9 |
10 | <{{src/calc.go}}
11 |
--------------------------------------------------------------------------------
/ex/packages/ex.md:
--------------------------------------------------------------------------------
1 | {{stack-package.md}}
2 | {{calc.md}}
3 |
--------------------------------------------------------------------------------
/ex/packages/src/calc.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "fmt"
6 | "os"
7 | "strconv"
8 | )
9 |
10 | var reader *bufio.Reader = bufio.NewReader(os.Stdin)
11 | var st = new(Stack)
12 |
13 | type Stack struct {
14 | i int
15 | data [10]int
16 | }
17 |
18 | func (s *Stack) push(k int) {
19 | if s.i+1 > 9 {
20 | return
21 | }
22 | s.data[s.i] = k
23 | s.i++
24 | }
25 |
26 | func (s *Stack) pop() (ret int) {
27 | s.i--
28 | if s.i < 0 {
29 | s.i = 0
30 | return
31 | }
32 | ret = s.data[s.i]
33 | return
34 | }
35 |
36 | func main() {
37 | for {
38 | s, err := reader.ReadString('\n')
39 | var token string
40 | if err != nil {
41 | return
42 | }
43 | for _, c := range s {
44 | switch {
45 | case c >= '0' && c <= '9':
46 | token = token + string(c)
47 | case c == ' ':
48 | r, _ := strconv.Atoi(token)
49 | st.push(r)
50 | token = ""
51 | case c == '+':
52 | fmt.Printf("%d\n", st.pop()+st.pop())
53 | case c == '*':
54 | fmt.Printf("%d\n", st.pop()*st.pop())
55 | case c == '-':
56 | p := st.pop()
57 | q := st.pop()
58 | fmt.Printf("%d\n", q-p)
59 | case c == 'q':
60 | return
61 | default:
62 | //error
63 | }
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/ex/packages/src/pushpop_test.go:
--------------------------------------------------------------------------------
1 | package stack
2 |
3 | import "testing"
4 |
5 | func TestPushPop(t *testing.T) {
6 | c := new(Stack)
7 | c.Push(5)
8 | if c.Pop() != 5 {
9 | t.Log("Pop doesn't give 5")
10 | t.Fail()
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ex/packages/src/stack-as-package.go:
--------------------------------------------------------------------------------
1 | package stack
2 |
3 | // Stack holds the items.
4 | type Stack struct {
5 | i int
6 | data [10]int
7 | }
8 |
9 | // Push pushes an item on the stack.
10 | func (s *Stack) Push(k int) {
11 | s.data[s.i] = k
12 | s.i++
13 | }
14 |
15 | // Pop pops an item from the stack.
16 | func (s *Stack) Pop() (ret int) {
17 | s.i--
18 | ret = s.data[s.i]
19 | return
20 | }
21 |
--------------------------------------------------------------------------------
/ex/packages/stack-package.md:
--------------------------------------------------------------------------------
1 | {.exercise data-difficulty="0"}
2 | ### Stack as package
3 |
4 | 1. See the Stack exercise. In this exercise we want to create a separate package
5 | for that code. Create a proper package for your stack implementation, `Push`,
6 | `Pop` and the `Stack` type need to be exported.
7 |
8 | 2. Write a simple unit test for this package.
9 | You should at least test that a `Pop` works after a `Push`.
10 |
11 |
12 | {.answer}
13 | ### Answer
14 | 1. There are a few details that should be changed to make a proper package
15 | for our stack. First, the exported functions should begin with a capital
16 | letter and so should `Stack`. The package file is named `stack-as-package.go`
17 | and contains:
18 |
19 | <{{src/stack-as-package.go}}
20 |
21 | 2. To make the unit testing work properly you need to do some
22 | preparations. We'll come to those in a minute. First the actual unit test.
23 | Create a file with the name `pushpop_test.go`, with the following contents:
24 |
25 | <{{src/pushpop_test.go}}
26 |
27 | For `go test` to work we need to put our package files in a directory
28 | under `$GOPATH/src`:
29 |
30 | % mkdir $GOPATH/src/stack
31 | % cp pushpop_test.go $GOPATH/src/stack
32 | % cp stack-as-package.go $GOPATH/src/stack
33 |
34 | Yields:
35 |
36 | % go test stack
37 | ok stack 0.001s
38 |
--------------------------------------------------------------------------------
/fig/array-vs-slice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miekg/learninggo/d93385b5b66b020c4ddfe37a54802c3c5d171929/fig/array-vs-slice.png
--------------------------------------------------------------------------------
/fig/bumper-inverse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miekg/learninggo/d93385b5b66b020c4ddfe37a54802c3c5d171929/fig/bumper-inverse.png
--------------------------------------------------------------------------------
/fig/reflection.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miekg/learninggo/d93385b5b66b020c4ddfe37a54802c3c5d171929/fig/reflection.png
--------------------------------------------------------------------------------
/fig/stack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/miekg/learninggo/d93385b5b66b020c4ddfe37a54802c3c5d171929/fig/stack.png
--------------------------------------------------------------------------------
/fig/stack.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
553 |
--------------------------------------------------------------------------------
/functions.md:
--------------------------------------------------------------------------------
1 | {.epigraph}
2 | > I'm always delighted by the light touch and stillness of
3 | > early programming languages. Not much text; a lot gets
4 | > done. Old programs read like quiet conversations
5 | > between a well-spoken research worker and a well-
6 | > studied mechanical colleague, not as a debate with a
7 | > compiler. Who'd have guessed sophistication bought
8 | > such noise?
9 | ****
10 |
11 | Quote: Richard P. Gabriel
12 |
13 | Functions are the basic building blocks of Go programs; all interesting stuff
14 | happens in them.
15 |
16 | Here is an example of how you can declare a function:
17 |
18 | ~~~go
19 | type mytype int
20 | func (p mytype) funcname(q int) (r,s int) { return 0,0 }
21 | //<<1>> //<<2>> //<<3>> //<<4>> //<<5>> //<<6>>
22 | ~~~
23 |
24 | To declare a function, you use the `func` keyword <<1>>. You can optionally bind
25 | <<2>> to a specific type called receiver (!functions, receiver) (a function
26 | with a receiver is usually called a method(!functions, method)). This will
27 | be explored in (#interfaces). Next <<3>> you write the name of your
28 | function. Here <<4>> we define that the variable `q` of type `int` is the input
29 | parameter. Parameters are passed *pass-by-value*.(!functions, pass-by-value)
30 | The variables `r` and `s` <<5>> are the *named return parameters* (((functions,
31 | named return parameters))) for this function. Functions in Go can have multiple
32 | return values. This is very useful to return a value *and* error. This
33 | removes the need for in-band error returns (such as -1 for `EOF`) and modifying
34 | an argument. If you want the return parameters not to be named you only give the
35 | types: `(int, int)`. If you have only one value to return you may omit the
36 | parentheses. If your function is a subroutine and does not have anything to
37 | return you may omit this entirely. Finally, we have the body <<6>> of the
38 | function. Note that `return` is a statement so the braces around the
39 | parameter(s) are optional.
40 |
41 | As said the return or result parameters of a Go function can be given names and
42 | used as regular variables, just like the incoming parameters. When named, they
43 | are initialized to the zero values for their types when the function begins. If
44 | the function executes a `return` statement with no arguments, the current values
45 | of the result parameters are returned. Using these features enables you (again)
46 | to do more with less code.^[This is a motto of Go; "Do *more* with *less*
47 | code".]
48 |
49 | The names are not mandatory but they can make code shorter and clearer:
50 | *they are documentation*. However don't overuse this feature, especially in
51 | longer functions where it might not be immediately apparent what is returned.
52 |
53 | Functions can be declared in any order you wish. The compiler scans the entire
54 | file before execution, so function prototyping is a thing of the past in Go. Go
55 | does not allow nested functions, but you can work around this with anonymous
56 | functions. See the Section (#functions-as-values) in this chapter. Recursive
57 | functions work just as in other languages:
58 |
59 | ~~~go
60 | func rec(i int) {
61 | if i == 10 { //<<1>>
62 | return
63 | }
64 | rec(i+1) //<<2>>
65 | fmt.Printf("%d ", i)
66 | }
67 | ~~~
68 |
69 | Here <<2>> we call the same function again, `rec` returns when `i` has the value
70 | 10, this is checked on the second line <<1>>. This function prints: `9
71 | 8 7 6 5 4 3 2 1 0`, when called as `rec(0)`.
72 |
73 |
74 | ## Scope
75 |
76 | Variables declared outside any functions are *global* (!scope, local) in Go,
77 | those defined in functions are *local* (!scope, local) to those functions. If
78 | names overlap - a local variable is declared with the same name as a global one
79 | - the local variable hides the global one when the current function is executed.
80 |
81 | In the following example we call `g()` from `f()`:
82 |
83 | ~~~go
84 | package main
85 |
86 | var a int //<<1>>
87 |
88 | func main() {
89 | a = 5
90 | print(a)
91 | f()
92 | }
93 |
94 | func f() {
95 | a := 6 //<<2>>
96 | print(a)
97 | g()
98 | }
99 |
100 | func g() {
101 | print(a)
102 | }
103 | ~~~
104 |
105 | Here <<1>>, we declare `a` to be a global variable of type `int`. Then in the
106 | `main` function we give the *global* `a` the value of 5, after printing it we
107 | call the function `f`. Then here <<2>>, `a := 6`, we create a *new, local*
108 | variable also called `a`. This new `a` gets the value of 6, which we then print.
109 | Then we call `g`, which uses the *global* `a` again and prints `a`'s value set
110 | in `main`. Thus the output will be: `565`. A *local* variable is *only* valid
111 | when we are executing the function in which it is defined. Note that the `:=`
112 | used in line 12 is sometimes hard to spot so it is generally advised *not* to
113 | use the same name for global and local variables.
114 |
115 |
116 | ## Functions as values
117 | (!functions, as values) (!functions, literals) As with almost everything in
118 | Go, functions are also *just* values. They can be assigned to variables as
119 | follows:
120 |
121 | <{{src/functions/anon-func.go}}[3,]
122 |
123 | `a` is defined as an anonymous (nameless) function <<1>>.
124 | Note the lack of parentheses `()` after `a`. If there were, that would be to *call*
125 | some function with the name `a` before we have defined what `a` is. Once `a` is
126 | defined, then we can *call* it, <<3>>.
127 |
128 | Functions--as--values may be used in other places, for example maps. Here we
129 | convert from integers to functions:
130 |
131 | ~~~go
132 | var xs = map[int]func() int{
133 | 1: func() int { return 10 },
134 | 2: func() int { return 20 },
135 | 3: func() int { return 30 },
136 | }
137 | ~~~
138 |
139 | Note that the final comma on second to last line is *mandatory*.
140 |
141 | Or you can write a function that takes a function as its parameter, for example
142 | a `Map` function that works on `int` slices. This is left as an exercise for the
143 | reader; see the exercise (#map-function).
144 |
145 |
146 | ## Callbacks
147 |
148 | Because functions are values they are easy to pass to functions, from where they
149 | can be used as callbacks. First define a function that does "something" with an
150 | integer value:
151 |
152 | ~~~go
153 | func printit(x int) {
154 | fmt.Printf("%v\n", x)
155 | }
156 | ~~~
157 |
158 | This function does not return a value and just prints its argument. The
159 | *signature* (!functions, signature) of this function is: `func printit(int)`,
160 | or without the function name: `func(int)`. To create a new function that uses
161 | this one as a callback we need to use this signature:
162 |
163 | ~~~go
164 | func callback(y int, f func(int)) {
165 | f(y)
166 | }
167 | ~~~
168 |
169 | Here we create a new function that takes two parameters: `y int`, i.e. just an
170 | `int` and `f func(int)`, i.e. a function that takes an int and returns nothing.
171 | The parameter `f` is the variable holding that function. It can be used as any
172 | other function, and we execute the function on line 2 with the parameter `y`:
173 | `f(y)`
174 |
175 |
176 | ## Deferred Code
177 |
178 | Suppose you have a function in which you open a file and perform various writes
179 | and reads on it. In such a function there are often spots where you want to
180 | return early. If you do that, you will need to close the file descriptor you are
181 | working on. This often leads to the following code:
182 |
183 | ~~~go
184 | func ReadWrite() bool {
185 | file.Open("file")
186 | // Do your thing
187 | if failureX {
188 | file.Close() //<<1>>
189 | return false
190 | }
191 |
192 | if failureY {
193 | file.Close() //<<1>>
194 | return false
195 | }
196 | file.Close() //<<1>>
197 | return true //<<2>>
198 | }
199 | ~~~
200 |
201 | Note that we repeat a lot of code here; you can see the that `file.Close()` is
202 | called at <<1>>. To overcome this, Go has the `defer` (!keywords, defer)
203 | keyword. After `defer` you specify a function which is called just *before* <<2>>
204 | the current function exits.
205 |
206 | With `defer` we can rewrite the above code as follows. It makes the function
207 | more readable and it puts the `Close` *right next* to the `Open`.
208 |
209 | ~~~go
210 | func ReadWrite() bool {
211 | file.Open("filename")
212 | defer file.Close() //<<1>>
213 | // Do your thing
214 | if failureX {
215 | return false //<<2>>
216 | }
217 | if failureY {
218 | return false //<<2>>
219 | }
220 | return true //<<2>>
221 | }
222 | ~~~
223 |
224 | At <<1>> `file.Close()` is added to the defer list. (!keywords, defer list)
225 | `Close` is now done automatically at <<2>>. This makes the function shorter and
226 | more readable. It puts the `Close` right next to the `Open`.
227 |
228 | You can put multiple functions on the "defer list", like this example from
229 | [@effective_go]:
230 |
231 | ~~~go
232 | for i := 0; i < 5; i++ {
233 | defer fmt.Printf("%d ", i)
234 | }
235 | ~~~
236 |
237 | Deferred functions are executed in LIFO order, so the above code prints: `4
238 | 3 2 1 0`.
239 |
240 | With `defer` you can even change return values, provided that you are using
241 | named result parameters and a function literal (!functions, literal)^[A
242 | function literal is sometimes called a closure (!closure).], i.e:
243 |
244 | ~~~go
245 | defer func() {/* ... */}()
246 | ~~~
247 |
248 | Here we use a function without a name and specify the body of the function
249 | inline, basically we're creating a nameless function on the spot. The final
250 | parentheses are needed because `defer` needs a function call, not a function value.
251 | If our anonymous function would take an parameter it would be easier to see why
252 | we need the parentheses:
253 |
254 | ~~~go
255 | defer func(x int) {/* ... */}(5)
256 | ~~~
257 |
258 | In this (unnamed) function you can access any named return parameter:
259 |
260 | ~~~go
261 | func f() (ret int)
262 | defer func() { //<<1>>
263 | ret++
264 | }()
265 | return 0
266 | }
267 | ~~~
268 |
269 | Here <<1>> we specify our function, the named return value `ret` is initialized
270 | with zero. The nameless function in the defer increments the value of `ret`
271 | with 1. The `return 0` on line
272 | 5 *will not be the returned value*, because of `defer`. The function `f` will
273 | return 1!
274 |
275 |
276 | ## Variadic Parameter
277 | Functions that take a variable number of parameters are known as variadic
278 | functions. (!functions, variadic) To declare a function as variadic, do
279 | something like this:
280 |
281 | ~~~go
282 | func myfunc(arg ...int) {}
283 | ~~~
284 |
285 | The `arg ...int` instructs Go to see this as a function that takes a variable
286 | number of arguments. Note that these arguments all have to have the type `int`.
287 | In the body of your function the variable `arg` is a slice of ints:
288 |
289 | ~~~go
290 | for _, n := range arg {
291 | fmt.Printf("And the number is: %d\n", n)
292 | }
293 | ~~~
294 |
295 | We range over the arguments on the first line. We are not interested in the
296 | index as returned by `range`, hence the use of the underscore there. In the body
297 | of the `range` we just print the parameters we were given.
298 |
299 | If you don't specify the type of the variadic argument it defaults to the empty
300 | interface `interface{}` (see Chapter (#interfaces)).
301 |
302 | Suppose we have another variadic function called `myfunc2`, the following
303 | example shows how to pass variadic arguments to it:
304 |
305 | ~~~go
306 | func myfunc(arg ...int) {
307 | myfunc2(arg...)
308 | myfunc2(arg[:2]...)
309 | }
310 | ~~~
311 |
312 | With `myfunc2(arg...)` we pass all the parameters to `myfunc2`, but because the
313 | variadic parameters is just a slice, we can use some slice tricks as well.
314 |
315 |
316 | ## Panic and recovering
317 |
318 | Go does not have an exception mechanism: you cannot throw exceptions. Instead it
319 | uses a panic-and-recover mechanism. It is worth remembering that you should use
320 | this as a last resort, your code will not look, or be, better if it is littered
321 | with panics. It's a powerful tool: use it wisely. So, how do you use it? In the
322 | words of the Go Authors [@go_blog_panic]:
323 |
324 | Panic
325 | : is a built-in function that stops the ordinary flow of control and begins
326 | panicking. When the function `F` calls `panic`, execution of `F` stops, any
327 | deferred functions in `F` are executed normally, and then `F` returns to its
328 | caller. To the caller, `F` then behaves like a call to `panic`. The process
329 | continues up the stack until all functions in the current goroutine have
330 | returned, at which point the program crashes. Panics can be initiated by
331 | invoking `panic` directly. They can also be caused by *runtime errors*, such as
332 | out-of-bounds array accesses.
333 |
334 | Recover
335 | : is a built-in function that regains control of a panicking goroutine.
336 | Recover is *only* useful inside *deferred* functions. During normal execution,
337 | a call to `recover` will return `nil` and have no other effect. If the current
338 | goroutine is panicking, a call to `recover` will capture the value given to
339 | `panic` and resume normal execution.
340 |
341 | This function checks if the function it gets as argument will panic when it is
342 | executed^[Modified from a presentation of Eleanor McHugh.]:
343 |
344 | ~~~go
345 | func Panic(f func()) (b bool) { //<<1>>
346 | defer func() { //<<2>>
347 | if x := recover(); x != nil {
348 | b = true
349 | }
350 | }()
351 | f() //<<3>>
352 | return //<<4>>
353 | }
354 | ~~~
355 |
356 | We define a new function `Panic` <<1>> that takes a function as an argument (see
357 | (#functions-as-values)). It returns true if `f` panics when run, else false. We
358 | then <<2>> define a `defer` function that utilizes `recover`. If the current
359 | goroutine panics, this defer function will notice that. If `recover()` returns
360 | non-`nil` we set `b` to true. At <<3>> Execute the function we received as the
361 | argument. And finally <<4>> we return the value of `b`. Because `b` is a named
362 | return parameter.
363 |
364 | The following code fragment, shows how we can use this function:
365 |
366 | ~~~go
367 | func panicy() {
368 | var a []int
369 | a[3] = 5
370 | }
371 |
372 | func main() {
373 | fmt.Println(Panic(panicy))
374 | }
375 | ~~~
376 |
377 | On line 3 the `a[3] = 5` triggers a *runtime* out of bounds error which results
378 | in a panic. Thus this program will print `true`. If we change line 2: `var
379 | a []int` to `var a [4]int` the function `panicy` does not panic anymore. Why?
380 |
381 | ## Exercises
382 |
383 | {{ex/functions/ex.md}}
384 |
--------------------------------------------------------------------------------
/inc/bib.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Go website
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | Go tutorial
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Effective Go
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | Communicating sequential processes
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | Duck typing
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | Bubble sort
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | Go Nuts mailing list
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | Go language specification
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | Go interfaces
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | Getting Started
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | Google's new language: Go
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 | Go package documentation
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 | Go for C++ programmers
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | The Go programming language blog
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 | Erlang
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 | Scala
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | The C programming language
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 | The C++ programming language
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 | Java
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 | Perl
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 | Haskell
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 | Go youtube channel
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 | Comprehensive perl archive network
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 | Plan 9
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 | Inferno
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 | Limbo
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 | Communicating sequential processes (csp)
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 | Newsqueak: a language for communicating with mice
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 | Quicksort
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 | Iota
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 | Using fizzbuzz to find developers...
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 | The Go programming language, day 2
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 | The Go programming language, day 3
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 | Function accepting a slice of interface types
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 | Go issue 65: compiler can't spot guaranteed return in if statement
305 |
306 |
307 |
308 |
309 |
310 |
311 |
312 | Defer, panic, and recover
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
321 | Go faq
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 | Go release history
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 | Profiling Go programs
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 | Go 1.5 Release Notes
349 |
350 |
351 |
352 |
353 |
354 |
--------------------------------------------------------------------------------
/inc/head.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
83 |
--------------------------------------------------------------------------------
/inc/jquery.waypoints.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | Waypoints - 3.1.1
3 | Copyright © 2011-2015 Caleb Troughton
4 | Licensed under the MIT license.
5 | https://github.com/imakewebthings/waypoints/blog/master/licenses.txt
6 | */
7 | !function(){"use strict";function t(o){if(!o)throw new Error("No options passed to Waypoint constructor");if(!o.element)throw new Error("No element option passed to Waypoint constructor");if(!o.handler)throw new Error("No handler option passed to Waypoint constructor");this.key="waypoint-"+e,this.options=t.Adapter.extend({},t.defaults,o),this.element=this.options.element,this.adapter=new t.Adapter(this.element),this.callback=o.handler,this.axis=this.options.horizontal?"horizontal":"vertical",this.enabled=this.options.enabled,this.triggerPoint=null,this.group=t.Group.findOrCreate({name:this.options.group,axis:this.axis}),this.context=t.Context.findOrCreateByElement(this.options.context),t.offsetAliases[this.options.offset]&&(this.options.offset=t.offsetAliases[this.options.offset]),this.group.add(this),this.context.add(this),i[this.key]=this,e+=1}var e=0,i={};t.prototype.queueTrigger=function(t){this.group.queueTrigger(this,t)},t.prototype.trigger=function(t){this.enabled&&this.callback&&this.callback.apply(this,t)},t.prototype.destroy=function(){this.context.remove(this),this.group.remove(this),delete i[this.key]},t.prototype.disable=function(){return this.enabled=!1,this},t.prototype.enable=function(){return this.context.refresh(),this.enabled=!0,this},t.prototype.next=function(){return this.group.next(this)},t.prototype.previous=function(){return this.group.previous(this)},t.invokeAll=function(t){var e=[];for(var o in i)e.push(i[o]);for(var n=0,r=e.length;r>n;n++)e[n][t]()},t.destroyAll=function(){t.invokeAll("destroy")},t.disableAll=function(){t.invokeAll("disable")},t.enableAll=function(){t.invokeAll("enable")},t.refreshAll=function(){t.Context.refreshAll()},t.viewportHeight=function(){return window.innerHeight||document.documentElement.clientHeight},t.viewportWidth=function(){return document.documentElement.clientWidth},t.adapters=[],t.defaults={context:window,continuous:!0,enabled:!0,group:"default",horizontal:!1,offset:0},t.offsetAliases={"bottom-in-view":function(){return this.context.innerHeight()-this.adapter.outerHeight()},"right-in-view":function(){return this.context.innerWidth()-this.adapter.outerWidth()}},window.Waypoint=t}(),function(){"use strict";function t(t){window.setTimeout(t,1e3/60)}function e(t){this.element=t,this.Adapter=n.Adapter,this.adapter=new this.Adapter(t),this.key="waypoint-context-"+i,this.didScroll=!1,this.didResize=!1,this.oldScroll={x:this.adapter.scrollLeft(),y:this.adapter.scrollTop()},this.waypoints={vertical:{},horizontal:{}},t.waypointContextKey=this.key,o[t.waypointContextKey]=this,i+=1,this.createThrottledScrollHandler(),this.createThrottledResizeHandler()}var i=0,o={},n=window.Waypoint,r=window.onload;e.prototype.add=function(t){var e=t.options.horizontal?"horizontal":"vertical";this.waypoints[e][t.key]=t,this.refresh()},e.prototype.checkEmpty=function(){var t=this.Adapter.isEmptyObject(this.waypoints.horizontal),e=this.Adapter.isEmptyObject(this.waypoints.vertical);t&&e&&(this.adapter.off(".waypoints"),delete o[this.key])},e.prototype.createThrottledResizeHandler=function(){function t(){e.handleResize(),e.didResize=!1}var e=this;this.adapter.on("resize.waypoints",function(){e.didResize||(e.didResize=!0,n.requestAnimationFrame(t))})},e.prototype.createThrottledScrollHandler=function(){function t(){e.handleScroll(),e.didScroll=!1}var e=this;this.adapter.on("scroll.waypoints",function(){(!e.didScroll||n.isTouch)&&(e.didScroll=!0,n.requestAnimationFrame(t))})},e.prototype.handleResize=function(){n.Context.refreshAll()},e.prototype.handleScroll=function(){var t={},e={horizontal:{newScroll:this.adapter.scrollLeft(),oldScroll:this.oldScroll.x,forward:"right",backward:"left"},vertical:{newScroll:this.adapter.scrollTop(),oldScroll:this.oldScroll.y,forward:"down",backward:"up"}};for(var i in e){var o=e[i],n=o.newScroll>o.oldScroll,r=n?o.forward:o.backward;for(var s in this.waypoints[i]){var a=this.waypoints[i][s],l=o.oldScroll=a.triggerPoint,p=l&&h,u=!l&&!h;(p||u)&&(a.queueTrigger(r),t[a.group.id]=a.group)}}for(var c in t)t[c].flushTriggers();this.oldScroll={x:e.horizontal.newScroll,y:e.vertical.newScroll}},e.prototype.innerHeight=function(){return this.element==this.element.window?n.viewportHeight():this.adapter.innerHeight()},e.prototype.remove=function(t){delete this.waypoints[t.axis][t.key],this.checkEmpty()},e.prototype.innerWidth=function(){return this.element==this.element.window?n.viewportWidth():this.adapter.innerWidth()},e.prototype.destroy=function(){var t=[];for(var e in this.waypoints)for(var i in this.waypoints[e])t.push(this.waypoints[e][i]);for(var o=0,n=t.length;n>o;o++)t[o].destroy()},e.prototype.refresh=function(){var t,e=this.element==this.element.window,i=this.adapter.offset(),o={};this.handleScroll(),t={horizontal:{contextOffset:e?0:i.left,contextScroll:e?0:this.oldScroll.x,contextDimension:this.innerWidth(),oldScroll:this.oldScroll.x,forward:"right",backward:"left",offsetProp:"left"},vertical:{contextOffset:e?0:i.top,contextScroll:e?0:this.oldScroll.y,contextDimension:this.innerHeight(),oldScroll:this.oldScroll.y,forward:"down",backward:"up",offsetProp:"top"}};for(var n in t){var r=t[n];for(var s in this.waypoints[n]){var a,l,h,p,u,c=this.waypoints[n][s],d=c.options.offset,f=c.triggerPoint,w=0,y=null==f;c.element!==c.element.window&&(w=c.adapter.offset()[r.offsetProp]),"function"==typeof d?d=d.apply(c):"string"==typeof d&&(d=parseFloat(d),c.options.offset.indexOf("%")>-1&&(d=Math.ceil(r.contextDimension*d/100))),a=r.contextScroll-r.contextOffset,c.triggerPoint=w+a-d,l=f=r.oldScroll,p=l&&h,u=!l&&!h,!y&&p?(c.queueTrigger(r.backward),o[c.group.id]=c.group):!y&&u?(c.queueTrigger(r.forward),o[c.group.id]=c.group):y&&r.oldScroll>=c.triggerPoint&&(c.queueTrigger(r.forward),o[c.group.id]=c.group)}}for(var g in o)o[g].flushTriggers();return this},e.findOrCreateByElement=function(t){return e.findByElement(t)||new e(t)},e.refreshAll=function(){for(var t in o)o[t].refresh()},e.findByElement=function(t){return o[t.waypointContextKey]},window.onload=function(){r&&r(),e.refreshAll()},n.requestAnimationFrame=function(e){var i=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||t;i.call(window,e)},n.Context=e}(),function(){"use strict";function t(t,e){return t.triggerPoint-e.triggerPoint}function e(t,e){return e.triggerPoint-t.triggerPoint}function i(t){this.name=t.name,this.axis=t.axis,this.id=this.name+"-"+this.axis,this.waypoints=[],this.clearTriggerQueues(),o[this.axis][this.name]=this}var o={vertical:{},horizontal:{}},n=window.Waypoint;i.prototype.add=function(t){this.waypoints.push(t)},i.prototype.clearTriggerQueues=function(){this.triggerQueues={up:[],down:[],left:[],right:[]}},i.prototype.flushTriggers=function(){for(var i in this.triggerQueues){var o=this.triggerQueues[i],n="up"===i||"left"===i;o.sort(n?e:t);for(var r=0,s=o.length;s>r;r+=1){var a=o[r];(a.options.continuous||r===o.length-1)&&a.trigger([i])}}this.clearTriggerQueues()},i.prototype.next=function(e){this.waypoints.sort(t);var i=n.Adapter.inArray(e,this.waypoints),o=i===this.waypoints.length-1;return o?null:this.waypoints[i+1]},i.prototype.previous=function(e){this.waypoints.sort(t);var i=n.Adapter.inArray(e,this.waypoints);return i?this.waypoints[i-1]:null},i.prototype.queueTrigger=function(t,e){this.triggerQueues[e].push(t)},i.prototype.remove=function(t){var e=n.Adapter.inArray(t,this.waypoints);e>-1&&this.waypoints.splice(e,1)},i.prototype.first=function(){return this.waypoints[0]},i.prototype.last=function(){return this.waypoints[this.waypoints.length-1]},i.findOrCreate=function(t){return o[t.axis][t.name]||new i(t)},n.Group=i}(),function(){"use strict";function t(t){this.$element=e(t)}var e=window.jQuery,i=window.Waypoint;e.each(["innerHeight","innerWidth","off","offset","on","outerHeight","outerWidth","scrollLeft","scrollTop"],function(e,i){t.prototype[i]=function(){var t=Array.prototype.slice.call(arguments);return this.$element[i].apply(this.$element,t)}}),e.each(["extend","inArray","isEmptyObject"],function(i,o){t[o]=e[o]}),i.adapters.push({name:"jquery",Adapter:t}),i.Adapter=t}(),function(){"use strict";function t(t){return function(){var i=[],o=arguments[0];return t.isFunction(arguments[0])&&(o=t.extend({},arguments[1]),o.handler=arguments[0]),this.each(function(){var n=t.extend({},o,{element:this});"string"==typeof n.context&&(n.context=t(this).closest(n.context)[0]),i.push(new e(n))}),i}}var e=window.Waypoint;window.jQuery&&(window.jQuery.fn.waypoint=t(window.jQuery)),window.Zepto&&(window.Zepto.fn.waypoint=t(window.Zepto))}();
--------------------------------------------------------------------------------
/inc/learninggo.css:
--------------------------------------------------------------------------------
1 | @import url("orderedlist-minimal.css");
2 | @import url("prism-bold.css");
3 |
4 | nav {
5 | background-color: #f8f8f8;
6 | border: 1px solid #e5e5e5;
7 | box-shadow: 0 3px 3px -1px rgba(0, 0, 0, 0.055);
8 | color: black;
9 | position:fixed;
10 | top:0;
11 | left:0;
12 | right:0;
13 | display: block;
14 | text-align: center;
15 | z-index: 5;
16 | }
17 |
18 | nav ul {
19 | margin: 0;
20 | padding: 0;
21 | }
22 |
23 | nav ul li {
24 | display: inline-block;
25 | list-style-type: none;
26 | }
27 |
28 | nav > ul > li > a {
29 | display: block;
30 | line-height: 4em;
31 | padding: 0 24px;
32 | text-decoration: none;
33 | }
34 |
35 | nav > ul > li:hover {}
36 |
37 | nav > ul > li:hover > a {
38 | text-decoration: underline;
39 | }
40 |
41 | h1.title {
42 | text-align: center;
43 | font-size: 42pt;
44 | letter-spacing: 0.4em;
45 | text-transform: uppercase;
46 | }
47 |
48 | .header-link {
49 | position: absolute;
50 | font-size: 14pt;
51 | left: 30px;
52 | opacity: 0;
53 | transition: opacity 0.2s ease-in-out 0.1s;
54 | color: black;
55 | }
56 |
57 | /* http://ben.balter.com/2014/03/13/pages-anchor-links/ */
58 | h1:hover .header-link,
59 | h2:hover .header-link,
60 | h3:hover .header-link,
61 | h4:hover .header-link,
62 | h5:hover .header-link,
63 | h6:hover .header-link {
64 | opacity: 1;
65 | }
66 |
67 | .book {
68 | width: 90%;
69 | }
70 |
71 | h1 {
72 | padding-bottom: 2em;
73 | font-size: 3em;
74 | border-top: 1px solid #e5e5e5;
75 | padding-top: 1em;
76 | }
77 |
78 | figure > blockquote.epigraph {
79 | text-align: right;
80 | border-left: none;
81 | padding-bottom: 1ex;
82 | }
83 |
84 | blockquote.epigraph {
85 | border-left: none;
86 | }
87 |
88 | .epigraph p {
89 | padding-left: 40%;
90 | text-align: right;
91 | }
92 |
93 | .epigraph hr {
94 | margin-left: 50%;
95 | width: 50%;
96 | }
97 |
98 | figure > blockquote.epigraph + figcaption {
99 | font-variant: small-caps;
100 | text-align: right;
101 | }
102 |
103 | .epigraph > ul {
104 | /* bullets are misplaced, remove them all together, looks nicer too */
105 | list-style-type: none;
106 | text-align: right;
107 | }
108 |
109 | .epigraph > ul > li {
110 | text-align: right;
111 | }
112 |
113 | span.callout {
114 | font-size: x-small;
115 | font-family:Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal, monospace;
116 | height: 1.3em;
117 | width: 1.2em;
118 | display: inline-block;
119 | text-align: center;
120 | vertical-align: middle;
121 | border-radius: 50%;
122 | background: black;
123 | color: white;
124 | }
125 |
126 | cite {
127 | font-size: 75%;
128 | line-height: 0;
129 | position: relative;
130 | vertical-align: baseline;
131 | top: -0.5em;
132 | }
133 |
134 | .closed:before {
135 | content: "▷ ";
136 | color: #000000;
137 | margin-right: 6px;
138 | }
139 |
140 | .open:before {
141 | content: "▽ ";
142 | color: #000000;
143 | margin-right: 6px;
144 | }
145 |
--------------------------------------------------------------------------------
/inc/orderedlist-minimal.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding:50px;
3 | font:14px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
4 | color:black;
5 | font-weight:300;
6 | }
7 |
8 | h1, h2, h3, h4, h5, h6 {
9 | color:#222;
10 | margin:0 0 20px;
11 | }
12 |
13 | p, ul, ol, table, pre, dl {
14 | margin:0 0 20px;
15 | }
16 |
17 | h1, h2, h3 {
18 | line-height:1.1;
19 | }
20 |
21 | h1 {
22 | font-size:28px;
23 | }
24 |
25 | h2 {
26 | color:#393939;
27 | }
28 |
29 | h3, h4, h5, h6 {
30 | color:#494949;
31 | }
32 |
33 | a {
34 | /* color:#39c; */
35 | font-weight:400;
36 | text-decoration:none;
37 | }
38 |
39 | a:hover {
40 | /* color:#069; */
41 | text-decoration:underline;
42 | }
43 |
44 | a small {
45 | font-size:11px;
46 | margin-top:-0.6em;
47 | display:block;
48 | }
49 |
50 | a:hover small {
51 | }
52 |
53 | .wrapper {
54 | width:860px;
55 | margin:0 auto;
56 | }
57 |
58 | blockquote {
59 | border-left:1px solid #e5e5e5;
60 | margin:0;
61 | padding:0 0 0 20px;
62 | font-style:italic;
63 | }
64 |
65 | aside {
66 | border-top:1px solid #e5e5e5;
67 | border-bottom:1px solid #e5e5e5;
68 | margin:20px 0 20px 0px;
69 | padding:20px 0 0 20px;
70 | font-style:italic;
71 | }
72 |
73 | code, pre {
74 | font-family:Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal, monospace;
75 | color:#333;
76 | font-size:14px;
77 | -moz-tab-size: 4;
78 | -o-tab-size: 4;
79 | tab-size: 4;
80 | }
81 |
82 | pre {
83 | padding:8px 15px;
84 | background: #f8f8f8;
85 | border-radius:5px;
86 | border:1px solid #e5e5e5;
87 | overflow-x: auto;
88 | }
89 |
90 | table {
91 | display: block;
92 | overflow-x: auto;
93 | width:100%;
94 | border-collapse:collapse;
95 | }
96 |
97 | th, td {
98 | text-align:left;
99 | padding:5px 10px;
100 | border-bottom:1px solid #e5e5e5;
101 | }
102 |
103 | dt {
104 | color:#444;
105 | font-weight:700;
106 | }
107 |
108 | th {
109 | color:#444;
110 | }
111 |
112 | img {
113 | max-width:100%;
114 | }
115 |
116 | header {
117 | width:270px;
118 | float:left;
119 | position:fixed;
120 | }
121 |
122 | header ul {
123 | list-style:none;
124 | height:40px;
125 |
126 | padding:0;
127 |
128 | background: #eee;
129 | background: -moz-linear-gradient(top, #f8f8f8 0%, #dddddd 100%);
130 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd));
131 | background: -webkit-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
132 | background: -o-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
133 | background: -ms-linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
134 | background: linear-gradient(top, #f8f8f8 0%,#dddddd 100%);
135 |
136 | border-radius:5px;
137 | border:1px solid #d2d2d2;
138 | box-shadow:inset #fff 0 1px 0, inset rgba(0,0,0,0.03) 0 -1px 0;
139 | width:270px;
140 | }
141 |
142 | header li {
143 | width:89px;
144 | float:left;
145 | border-right:1px solid #d2d2d2;
146 | height:40px;
147 | }
148 |
149 | header li:first-child a {
150 | border-radius:5px 0 0 5px;
151 | }
152 |
153 | header li:last-child a {
154 | border-radius:0 5px 5px 0;
155 | }
156 |
157 | header ul a {
158 | line-height:1;
159 | font-size:11px;
160 | color:#999;
161 | display:block;
162 | text-align:center;
163 | padding-top:6px;
164 | height:34px;
165 | }
166 |
167 | header ul a:hover {
168 | color:#999;
169 | background: -moz-linear-gradient(top, #fff 0%, #ddd 100%);
170 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fff), color-stop(100%,#ddd));
171 | background: -webkit-linear-gradient(top, #fff 0%,#ddd 100%);
172 | background: -o-linear-gradient(top, #fff 0%,#ddd 100%);
173 | background: -ms-linear-gradient(top, #fff 0%,#ddd 100%);
174 | background: linear-gradient(top, #fff 0%,#ddd 100%);
175 | }
176 |
177 | header ul a:active {
178 | -webkit-box-shadow: inset 0px 2px 2px 0px #ddd;
179 | -moz-box-shadow: inset 0px 2px 2px 0px #ddd;
180 | box-shadow: inset 0px 2px 2px 0px #ddd;
181 | }
182 |
183 | strong {
184 | color:#222;
185 | font-weight:700;
186 | }
187 |
188 | header ul li + li {
189 | width:88px;
190 | border-left:1px solid #fff;
191 | }
192 |
193 | header ul li + li + li {
194 | border-right:none;
195 | width:89px;
196 | }
197 |
198 | header ul a strong {
199 | font-size:14px;
200 | display:block;
201 | color:#222;
202 | }
203 |
204 | /* Removed to keep some sanity; mmark2 outputs sectionsin the HTML5 output.
205 | section {
206 | width:500px;
207 | float:right;
208 | padding-bottom:50px;
209 | }
210 | */
211 |
212 | small {
213 | font-size:11px;
214 | }
215 |
216 | hr {
217 | border:0;
218 | background:#e5e5e5;
219 | height:1px;
220 | margin:0 0 20px;
221 | }
222 |
223 | footer {
224 | /* width:270px;
225 | float:left;
226 | position:fixed;
227 | bottom:50px;
228 | */
229 | }
230 |
231 | @media print, screen and (max-width: 960px) {
232 |
233 | div.wrapper {
234 | width:auto;
235 | margin:0;
236 | }
237 |
238 | header, section, footer {
239 | float:none;
240 | position:static;
241 | width:auto;
242 | }
243 |
244 | header {
245 | padding-right:320px;
246 | }
247 |
248 | section {
249 | border:1px solid #e5e5e5;
250 | border-width:1px 0;
251 | padding:20px 0;
252 | margin:0 0 20px;
253 | }
254 |
255 | header a small {
256 | display:inline;
257 | }
258 |
259 | header ul {
260 | position:absolute;
261 | right:50px;
262 | top:52px;
263 | }
264 | }
265 |
266 | @media print, screen {
267 | body {
268 | font-size: 16px;
269 | }
270 | }
271 |
272 | @media print, screen and (max-width: 720px) {
273 | body {
274 | word-wrap:break-word;
275 | font-size: 15px;
276 | }
277 |
278 | header {
279 | padding:0;
280 | }
281 |
282 | header ul, header p.view {
283 | position:static;
284 | }
285 |
286 | pre, code {
287 | word-wrap:normal;
288 | }
289 | }
290 |
291 | @media print, screen and (max-width: 480px) {
292 | body {
293 | font-size: 14px;
294 | padding:15px;
295 | }
296 |
297 | header ul {
298 | display:none;
299 | }
300 | }
301 |
302 | @media print {
303 | body {
304 | padding:0.4in;
305 | font-size:12pt;
306 | color:#444;
307 | }
308 | }
309 |
--------------------------------------------------------------------------------
/inc/orderedlist-minimal.scale.fix.js:
--------------------------------------------------------------------------------
1 | var metas = document.getElementsByTagName('meta');
2 | var i;
3 | if (navigator.userAgent.match(/iPhone/i)) {
4 | for (i=0; i code {
65 | position: relative;
66 | }
67 |
68 | .line-numbers .line-numbers-rows {
69 | position: absolute;
70 | pointer-events: none;
71 | top: 0;
72 | font-size: 100%;
73 | left: -3.8em;
74 | width: 3em; /* works for line-numbers below 1000 lines */
75 | letter-spacing: -1px;
76 | border-right: 1px solid #999;
77 |
78 | -webkit-user-select: none;
79 | -moz-user-select: none;
80 | -ms-user-select: none;
81 | user-select: none;
82 |
83 | }
84 |
85 | .line-numbers-rows > span {
86 | pointer-events: none;
87 | display: block;
88 | counter-increment: linenumber;
89 | }
90 |
91 | .line-numbers-rows > span:before {
92 | content: counter(linenumber);
93 | color: #999;
94 | display: block;
95 | padding-right: 0.8em;
96 | text-align: right;
97 | }
98 |
--------------------------------------------------------------------------------
/inc/prism.js:
--------------------------------------------------------------------------------
1 | /* http://prismjs.com/download.html?themes=prism&languages=clike+go&plugins=line-numbers+keep-markup */
2 | var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(\w+)\b/i,t=0,n=_self.Prism={util:{encode:function(e){return e instanceof a?new a(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/e.length)break e;if(!(v instanceof a)){u.lastIndex=0;var b=u.exec(v),k=1;if(!b&&h&&m!=r.length-1){if(u.lastIndex=y,b=u.exec(e),!b)break;for(var w=b.index+(c?b[1].length:0),_=b.index+b[0].length,A=m,P=y,j=r.length;j>A&&_>P;++A)P+=r[A].length,w>=P&&(++m,y=P);if(r[m]instanceof a||r[A-1].greedy)continue;k=A-m,v=e.slice(y,P),b.index-=y}if(b){c&&(f=b[1].length);var w=b.index+f,b=b[0].slice(f),_=w+b.length,x=v.slice(0,w),O=v.slice(_),S=[m,k];x&&S.push(x);var N=new a(l,g?n.tokenize(b,g):b,d,b,h);S.push(N),O&&S.push(O),Array.prototype.splice.apply(r,S)}}}}}return r},hooks:{all:{},add:function(e,t){var a=n.hooks.all;a[e]=a[e]||[],a[e].push(t)},run:function(e,t){var a=n.hooks.all[e];if(a&&a.length)for(var r,i=0;r=a[i++];)r(t)}}},a=n.Token=function(e,t,n,a,r){this.type=e,this.content=t,this.alias=n,this.length=0|(a||"").length,this.greedy=!!r};if(a.stringify=function(e,t,r){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return a.stringify(n,t,e)}).join("");var i={type:e.type,content:a.stringify(e.content,t,r),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:r};if("comment"==i.type&&(i.attributes.spellcheck="true"),e.alias){var l="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(i.classes,l)}n.hooks.run("wrap",i);var o=Object.keys(i.attributes).map(function(e){return e+'="'+(i.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+i.tag+' class="'+i.classes.join(" ")+'"'+(o?" "+o:"")+">"+i.content+""+i.tag+">"},!_self.document)return _self.addEventListener?(_self.addEventListener("message",function(e){var t=JSON.parse(e.data),a=t.language,r=t.code,i=t.immediateClose;_self.postMessage(n.highlight(r,n.languages[a],a)),i&&_self.close()},!1),_self.Prism):_self.Prism;var r=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return r&&(n.filename=r.src,document.addEventListener&&!r.hasAttribute("data-manual")&&("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
3 | Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/};
4 | Prism.languages.go=Prism.languages.extend("clike",{keyword:/\b(break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,builtin:/\b(bool|byte|complex(64|128)|error|float(32|64)|rune|string|u?int(8|16|32|64|)|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(ln)?|real|recover)\b/,"boolean":/\b(_|iota|nil|true|false)\b/,operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,number:/\b(-?(0x[a-f\d]+|(\d+\.?\d*|\.\d+)(e[-+]?\d+)?)i?)\b/i,string:/("|'|`)(\\?.|\r|\n)*?\1/}),delete Prism.languages.go["class-name"];
5 | !function(){"undefined"!=typeof self&&self.Prism&&self.document&&Prism.hooks.add("complete",function(e){if(e.code){var t=e.element.parentNode,s=/\s*\bline-numbers\b\s*/;if(t&&/pre/i.test(t.nodeName)&&(s.test(t.className)||s.test(e.element.className))&&!e.element.querySelector(".line-numbers-rows")){s.test(e.element.className)&&(e.element.className=e.element.className.replace(s,"")),s.test(t.className)||(t.className+=" line-numbers");var n,a=e.code.match(/\n(?!$)/g),l=a?a.length+1:1,r=new Array(l+1);r=r.join(""),n=document.createElement("span"),n.setAttribute("aria-hidden","true"),n.className="line-numbers-rows",n.innerHTML=r,t.hasAttribute("data-start")&&(t.style.counterReset="linenumber "+(parseInt(t.getAttribute("data-start"),10)-1)),e.element.appendChild(n)}}})}();
6 | !function(){"undefined"!=typeof self&&self.Prism&&self.document&&document.createRange&&(Prism.plugins.KeepMarkup=!0,Prism.hooks.add("before-highlight",function(e){if(e.element.children.length){var n=0,o=[],t=function(e,d){var r={};d||(r.clone=e.cloneNode(!1),r.posOpen=n,o.push(r));for(var a=0,s=e.childNodes.length;s>a;a++){var p=e.childNodes[a];1===p.nodeType?t(p):3===p.nodeType&&(n+=p.data.length)}d||(r.posClose=n)};t(e.element,!0),o&&o.length&&(e.keepMarkup=o)}}),Prism.hooks.add("after-highlight",function(e){if(e.keepMarkup&&e.keepMarkup.length){var n=function(e,o){for(var t=0,d=e.childNodes.length;d>t;t++){var r=e.childNodes[t];if(1===r.nodeType){if(!n(r,o))return!1}else 3===r.nodeType&&(!o.nodeStart&&o.pos+r.data.length>o.node.posOpen&&(o.nodeStart=r,o.nodeStartPos=o.node.posOpen-o.pos),o.nodeStart&&o.pos+r.data.length>=o.node.posClose&&(o.nodeEnd=r,o.nodeEndPos=o.node.posClose-o.pos),o.pos+=r.data.length);if(o.nodeStart&&o.nodeEnd){var a=document.createRange();return a.setStart(o.nodeStart,o.nodeStartPos),a.setEnd(o.nodeEnd,o.nodeEndPos),o.node.clone.appendChild(a.extractContents()),a.insertNode(o.node.clone),a.detach(),!1}}return!0};e.keepMarkup.forEach(function(o){n(e.element,{node:o,pos:0})})}}))}();
7 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 | learninggo.html
--------------------------------------------------------------------------------
/interfaces.md:
--------------------------------------------------------------------------------
1 | {.epigraph}
2 | > I have this phobia about having my body penetrated surgically. You know what
3 | > I mean?
4 | ****
5 |
6 | Quote: eXistenZ -- Ted Pikul
7 |
8 | In Go, the word *interface*(!interface) is overloaded to mean several
9 | different things. Every type has an interface, which is the *set of methods
10 | defined* for (!interface, set of methods) that type. This bit of code defines
11 | a struct type `S` with one field, and defines two methods for `S`. ^[The following text is partly from [@go_interfaces].]
12 |
13 | ~~~go
14 | type S struct { i int }
15 | func (p *S) Get() int { return p.i }
16 | func (p *S) Put(v int) { p.i = v }
17 | ~~~
18 | Figure: Defining a struct and methods on it.
19 |
20 | You can also define an (!interface, type)interface type, which is simply
21 | a set of methods. This defines an interface `I` with two methods:
22 |
23 | ~~~go
24 | type I interface {
25 | Get() int
26 | Put(int)
27 | }
28 | ~~~
29 |
30 | `S` is a valid *implementation* for interface `I`, because it defines the two
31 | methods which `I` requires. Note that this is true even though there is no
32 | explicit declaration that `S` implements `I`.
33 |
34 | A Go program can use this fact via yet another meaning of interface, which is an
35 | interface value: (!interface, value)
36 |
37 | ~~~go
38 | func f(p I) { //<<1>>
39 | fmt.Println(p.Get()) //<<2>>
40 | p.Put(1) //<<3>>
41 | }
42 | ~~~
43 |
44 | At <<1>> we declare a function that takes an interface type as the argument.
45 | Because `p` implements `I`, it *must* have the `Get()` method, which we call at
46 | <<2>>. And the same holds true for the `Put()` method at <<3>>. Because `S`
47 | implements `I`, we can call the function `f` passing in a pointer to a value of
48 | type `S`: `var s S; f(&s)`
49 |
50 | The reason we need to take the address of `s`, rather than a value of type `S`,
51 | is because we defined the methods on `s` to operate on pointers, see the
52 | definition in the code above. This is not a requirement -- we could have defined
53 | the methods to take values -- but then the `Put` method would not work as
54 | expected.
55 |
56 | The fact that you do not need to declare whether or not a type implements an
57 | interface means that Go implements a form of duck typing (!duck, typing)
58 | [@duck_typing]. This is not pure duck typing, because when possible the
59 | Go compiler will statically check whether the type implements the interface.
60 | However, Go does have a purely dynamic aspect, in that you can convert from one
61 | interface type to another. In the general case, that conversion is checked at
62 | run time. If the conversion is invalid -- if the type of the value stored in
63 | the existing interface value does not satisfy the interface to which it is being
64 | converted -- the program will fail with a run time error.
65 |
66 | Interfaces in Go are similar to ideas in several other programming languages:
67 | pure abstract virtual base classes in C++, typeclasses in Haskell or duck typing
68 | in Python. However there is no other language which combines interface values,
69 | static type checking, dynamic run time conversion, and no requirement for
70 | explicitly declaring that a type satisfies an interface. The result in Go is
71 | powerful, flexible, efficient, and easy to write.
72 |
73 |
74 | ## Which is what?
75 |
76 | Let's define another type `R` that also implements the interface `I`:
77 |
78 | ~~~go
79 | type R struct { i int }
80 | func (p *R) Get() int { return p.i }
81 | func (p *R) Put(v int) { p.i = v }
82 | ~~~
83 |
84 | The function `f` can now accept variables of type `R` and `S`.
85 |
86 | Suppose you need to know the actual type in the function `f`. In Go you can
87 | figure that out by using a type switch(!type switch).
88 |
89 | ~~~go
90 | func f(p I) {
91 | switch t := p.(type) { //<<1>>
92 | case *S: //<<2>>
93 | case *R: //<<2>>
94 | default: //<<3>>
95 | }
96 | }
97 | ~~~
98 |
99 | At <<1>> we use the type switch, note that the `.(type)` syntax is *only* valid
100 | within a `switch` statement. We store the value in the variable `t`. The
101 | subsequent cases <<2>> each check for a different *actual* type. And we can even
102 | have a `default` <<3>> clause. It is worth pointing out that both `case R` and
103 | `case s` aren't possible, because `p` needs to be a pointer in order to satisfy
104 | `i`.
105 |
106 | A type switch isn't the only way to discover the type at *run-time*.
107 |
108 | ~~~go
109 | if t, ok := something.(I); ok { //<<1>>
110 | // ...
111 | }
112 | ~~~
113 |
114 | You can also use a "comma, ok" form <<1>> to see if an interface type implements
115 | a specific interface. If `ok` is true, `t` will hold the type of `something`.
116 | When you are sure a variable implements an interface you can use: `t := something.(I)` .
117 |
118 |
119 | ## Empty interface
120 |
121 | Since every type satisfies the empty interface: `interface{}` we can create
122 | a generic function which has an empty interface as its argument:
123 |
124 | ~~~go
125 | func g(something interface{}) int {
126 | return something.(I).Get()
127 | }
128 | ~~~
129 |
130 | The `return something.(I).Get()` is the tricky bit in this function. The value
131 | `something` has type `interface{}`, meaning no guarantee of any methods at all:
132 | it could contain any type. The `.(I)` is a type assertion (!type assertion)
133 | which converts `something` to an interface of type `I`. If we have that type we
134 | can invoke the `Get()` function. So if we create a new variable of the type
135 | `*S`, we can just call `g()`, because `*S` also implements the empty interface.
136 |
137 | ~~~go
138 | s = new(S)
139 | fmt.Println(g(s));
140 | ~~~
141 |
142 | The call to `g` will work fine and will print 0. If we however invoke `g()` with
143 | a value that does not implement `I` we have a problem:
144 |
145 | ~~~go
146 | var i int
147 | fmt.Println(g(i))
148 | ~~~
149 |
150 | This compiles, but when we run this we get slammed with: "panic: interface
151 | conversion: int is not main.I: missing method Get".
152 |
153 | Which is completely true, the built-in type `int` does not have a `Get()`
154 | method.
155 |
156 |
157 | ## Methods
158 |
159 | Methods are functions that have a receiver (see (#functions)).
160 | You can define methods on any type (except on non-local types, this includes
161 | built-in types: the type `int` can not have methods).
162 | You can however make a new integer type with its own methods. For example:
163 |
164 | ~~~go
165 | type Foo int
166 |
167 | func (self Foo) Emit() {
168 | fmt.Printf("%v", self)
169 | }
170 |
171 | type Emitter interface {
172 | Emit()
173 | }
174 | ~~~
175 |
176 | Doing this on non-local (types defined in other packages) types yields an error
177 | "cannot define new methods on non-local type int".
178 |
179 |
180 | ## Methods on interface types
181 |
182 | An interface defines a set of methods. A method contains the actual code. In
183 | other words, an interface is the definition and the methods are the
184 | implementation. So a receiver can not be an interface type, doing so results in
185 | a "invalid receiver type ..." compiler error. The authoritative word from the
186 | language spec [@go_spec]:
187 |
188 | > The receiver type must be of the form `T` or `*T` where `T` is a type name. `T`
189 | > is called the receiver base type or just base type. The base type must not be
190 | > a pointer or interface type and must be declared in the same package as the
191 | > method.
192 |
193 |
194 | A> Creating a pointer to an interface value is a useless action in Go. It is in
195 | A> fact illegal to create a pointer to an interface value. The release notes for an
196 | A> earlier Go release that made them illegal leave no room for doubt:
197 | A>
198 | A> > The language change is that uses of pointers to interface values no longer
199 | A> > automatically de-reference the pointer. A pointer to an interface value is
200 | A> > more often a beginner's bug than correct code.
201 |
202 |
203 | ## Interface names
204 |
205 | By convention, one-method interfaces are named by the method name plus the *-er*
206 | suffix: Read*er*, Writ*er*, Formatt*er* etc.
207 |
208 | There are a number of such names and it's productive to honor them and the
209 | function names they capture. `Read`, `Write`, `Close`, `Flush`, `String` and so
210 | on have canonical signatures and meanings. To avoid confusion, don't give your
211 | method one of those names unless it has the same signature and meaning.
212 | Conversely, if your type implements a method with the same meaning as a method
213 | on a well-known type, give it the same name and signature; call your
214 | string-converter method `String` not `ToString`. ^[Text copied from
215 | [@effective_go].]
216 |
217 |
218 | ## A sorting example
219 |
220 | Recall the Bubblesort exercise, where we sorted an array of integers:
221 |
222 | ~~~go
223 | func bubblesort(n []int) {
224 | for i := 0; i < len(n)-1; i++ {
225 | for j := i + 1; j < len(n); j++ {
226 | if n[j] < n[i] {
227 | n[i], n[j] = n[j], n[i]
228 | }
229 | }
230 | }
231 | }
232 | ~~~
233 |
234 | A version that sorts strings is identical except for the signature of the
235 | function: `func bubblesortString(n []string) { /* ... */ }` . Using this
236 | approach would lead to two functions, one for each type. By using interfaces we
237 | can make this more (!generic) generic. Let's create a new function that will
238 | sort both strings and integers, something along the lines of this non-working
239 | example:
240 |
241 | ~~~go
242 | func sort(i []interface{}) { //<<1>>
243 | switch i.(type) { //<<2>>
244 | case string: //<<3>>
245 | // ...
246 | case int:
247 | // ...
248 | }
249 | return /* ... */ //<<4>>
250 | }
251 | ~~~
252 |
253 | Our function will receive a slice of empty interfaces at <<1>>. We then <<2>> use a
254 | type switch to find out what the actual type of the input is. And then <<3>>
255 | then sort accordingly. And, when done, return <<4>> the sorted slice.
256 |
257 | But when we call this function with `sort([]int{1, 4, 5})`, it fails with:
258 | "cannot use i (type []int) as type []interface { } in function argument"
259 |
260 | This is because Go can not easily convert to a *slice* of interfaces.
261 | Just converting to an interface is easy, but to a slice is much more costly.
262 | The full mailing list discussion on this subject can be found at
263 | [@go_nuts_interfaces]. To keep a long story short: Go does not (implicitly) convert slices for you.
264 |
265 | So what is the Go way of creating such a "generic" function?
266 | Instead of doing the type inference ourselves with a type switch, we let
267 | Go do it implicitly:
268 | The following steps are required:
269 |
270 | * Define an interface type (called `Sorter` here) with a number of methods
271 | needed for sorting. We will at least need a function to get the length of the
272 | slice, a function to compare two values and a swap function.
273 |
274 | ~~~go
275 | type Sorter interface {
276 | Len() int // len() as a method.
277 | Less(i, j int) bool // p[j] < p[i] as a method.
278 | Swap(i, j int) // p[i], p[j] = p[j], p[i] as a method.
279 | }
280 | ~~~
281 |
282 | * Define new types for the slices we want to sort. Note that we declare slice types:
283 |
284 | ~~~go
285 | type Xi []int
286 | type Xs []string
287 | ~~~
288 |
289 | * Implementation of the methods of the `Sorter` interface.
290 | For integers:
291 |
292 | ~~~go
293 | func (p Xi) Len() int {return len(p)}
294 | func (p Xi) Less(i int, j int) bool {return p[j] < p[i]}
295 | func (p Xi) Swap(i int, j int) {p[i], p[j] = p[j], p[i]}
296 | ~~~
297 |
298 | And for strings:
299 |
300 | ~~~go
301 | func (p Xs) Len() int {return len(p)}
302 | func (p Xs) Less(i int, j int) bool {return p[j] < p[i]}
303 | func (p Xs) Swap(i int, j int) {p[i], p[j] = p[j], p[i]}
304 | ~~~
305 |
306 | * Write a *generic* Sort function that works on the `Sorter` interface.
307 |
308 | ~~~go
309 | func Sort(x Sorter) { //<<1>>
310 | for i := 0; i < x.Len() - 1; i++ { //<<2>>
311 | for j := i + 1; j < x.Len(); j++ {
312 | if x.Less(i, j) {
313 | x.Swap(i, j)
314 | }
315 | }
316 | }
317 | }
318 | ~~~
319 |
320 | At <<1>> `x` is now of the `Sorter` type and using the defined methods for this interface we implement
321 | Bubblesort at <<2>>.
322 |
323 | Now we can use our *generic* `Sort` function as follows:
324 |
325 | ~~~go
326 | ints := Xi{44, 67, 3, 17, 89, 10, 73, 9, 14, 8}
327 | strings := Xs{"nut", "ape", "elephant", "zoo", "go"}
328 |
329 | Sort(ints)
330 | fmt.Printf("%v\n", ints)
331 | Sort(strings)
332 | fmt.Printf("%v\n", strings)
333 | ~~~
334 |
335 |
336 | ## Listing interfaces in interfaces
337 |
338 | Take a look at the following example of an interface definition, this one is
339 | from the package `container/heap`:
340 |
341 | ~~~go
342 | type Interface interface {
343 | sort.Interface
344 | Push(x interface{})
345 | Pop() interface{}
346 | }
347 | ~~~
348 |
349 | Here another interface is listed inside the definition of `heap.Interface`, this
350 | may look odd, but is perfectly valid, remember that on the surface an interface is nothing
351 | more than a listing of methods. `sort.Interface` is also such a listing, so it is
352 | perfectly legal to include it in the interface.
353 |
354 |
355 | ## Introspection and reflection
356 |
357 | In the following example we want to look at the "tag" (here named "namestr")
358 | defined in the type definition of `Person`. To do this we need the
359 | `reflect`(!package,reflect) package (there is no other way in Go). Keep in
360 | mind that looking at a tag means going back to the *type* definition. So we use
361 | the `reflect` package to figure out the type of the variable and *then* access
362 | the tag.
363 |
364 | ~~~go
365 | type Person struct {
366 | name string "namestr"
367 | age int
368 | }
369 |
370 | func ShowTag(i interface{}) { //<<1>>
371 | switch t := reflect.TypeOf(i); t.Kind() {
372 | case reflect.Ptr: //<<2>>
373 | tag := t.Elem().Field(0).Tag
374 | // <<3>> <<4>> <<5>>
375 | ~~~
376 | Figure: Introspection using reflection.
377 |
378 | We are calling `ShowTag` at <<1>> with a `*Person`, so at <<2>> we're expecting
379 | a `reflect.Ptr`. We are dealing with a `Type` <<3>> and according to the
380 | documentation ^[`go doc reflect`]:
381 |
382 | > Elem returns a type's element type.
383 | > It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
384 |
385 | So on `t` we use `Elem()` to get the value the pointer points to. We have now
386 | dereferenced the pointer and are "inside" our structure. We then <<4>> use
387 | `Field(0)` to access the zeroth field.
388 |
389 | The struct `StructField` has a `Tag` member which returns the tag-name as
390 | a string. So on the $0^{th}$ field we can unleash `.Tag` <<5>> to access this
391 | name: `Field(0).Tag`. This gives us `namestr`.
392 |
393 | To make the difference between types and values more clear, take a look at the
394 | following code:
395 |
396 | ~~~go
397 | func show(i interface{}) {
398 | switch t := i.(type) {
399 | case *Person:
400 | t := reflect.TypeOf(i) //<<1>>
401 | v := reflect.ValueOf(i) //<<2>>
402 | tag := t.Elem().Field(0).Tag //<<3>>
403 | name := v.Elem().Field(0).String() //<<4>>
404 | }
405 | }
406 | ~~~
407 | Figure: Reflection and the type and value.
408 |
409 | At <<1>> we create `t` the type data of `i`, and `v` gets the actual values at
410 | <<2>>. Here at <<3>> we want to get to the "tag". So we need `Elem()` to redirect
411 | the pointer, access the first field and get the tag. Note that we operate on `t`
412 | a `reflect.Type`. Now <<4>> we want to get access to the *value* of one of the
413 | members and we employ `Elem()` on `v` to do the redirection. we have "arrived"
414 | at the structure. Then we go to the first field `Field(0)` and invoke the
415 | `String()` method on it.
416 |
417 | !---
418 | 
419 | !---
420 | Figure: Peeling away the layers using reflection. Going from a `*Person` via `Elem` using the
421 | methods described in `go doc reflect` to get the actual `string` contained within.")
422 |
423 | Setting a value works similarly as getting a value, but only works on
424 | *exported* members. Again some code:
425 |
426 | ~~~go
427 | type Person struct {
428 | name string
429 | age int
430 | }
431 |
432 | func Set(i interface{}) {
433 | switch i.(type) {
434 | case *Person:
435 | r := reflect.ValueOf(i)
436 | r.Elem(0).Field(0).SetString("Albert Einstein")
437 | }
438 | }
439 | ~~~
440 | Figure: Reflect with *private* member.
441 |
442 | ~~~go
443 | type Person struct {
444 | Name string
445 | age int
446 | }
447 |
448 | func Set(i interface{}) {
449 | switch i.(type) {
450 | case *Person:
451 | r := reflect.ValueOf(i)
452 | r.Elem().Field(0).SetString("Albert Einstein")
453 | }
454 | }
455 | ~~~
456 | Figure: Reflect with *public* member.
457 |
458 | The first program compiles and runs, but when you run it, you are greeted with a
459 | stack trace and a *run time* error:
460 | "panic: reflect.Value.SetString using value obtained using unexported field".
461 |
462 | The second program works OK and sets the member `Name` to "Albert Einstein".
463 | Of course this only works when you call `Set()` with a pointer argument.
464 |
465 |
466 | ## Exercises
467 |
468 | {{ex/interfaces/ex.md}}
469 |
--------------------------------------------------------------------------------
/introduction.md:
--------------------------------------------------------------------------------
1 | {.epigraph}
2 | > Is Go an object-oriented language? Yes and no.
3 | ****
4 |
5 | Quote: Frequently asked questions, Go Authors
6 |
7 |
8 | The Go programming language is an open source project language to make programmers more productive.
9 |
10 | According to the website [@go_web] "Go is expressive, concise, clean, and efficient". And indeed it
11 | is. My initial interest was piqued when I read early announcements about this new language that had
12 | built-in concurreny and a C-like syntax (Erlang also has built-in concurrency, but I could never get
13 | used to its syntax). Go is a compiled statically typed language that feels like a dynamically typed,
14 | interpreted language. My go to (scripting!) language Perl has taken a back seat now that Go is
15 | around.
16 |
17 | The unique Go language is defined by these principles:
18 |
19 | Clean and Simple
20 | : Go strives to keep things small and beautiful. You should be able to do a lot in only a few
21 | lines of code.
22 |
23 | Concurrent
24 | : Go makes it easy to "fire off" functions to be run as *very* lightweight threads. These threads
25 | are called goroutines (!goroutine)^[Yes, that sounds a lot like *co*routines, but goroutines are
26 | slightly different as we will see in (#communication).] in Go.
27 |
28 | Channels
29 | : Communication with these goroutines is done, either via shared state or via (!channels)
30 | channels [@csp].
31 |
32 | Fast
33 | : Compilation is fast and execution is fast. The aim is to be as fast as C. Compilation time is
34 | measured in seconds.
35 |
36 | Safe
37 | : Explicit casting and strict rules when converting one type to another. Go has garbage
38 | collection. No more `free()` in Go: the language takes care of this.
39 |
40 | Standard format
41 | : A Go program can be formatted in (almost) any way the programmers want, but an official format
42 | exists. The rule is very simple: The output of the filter `gofmt` *is the officially endorsed
43 | format*.
44 |
45 | Postfix types
46 | : Types are given *after* the variable name, thus `var a int`, instead of `int a`.
47 |
48 | UTF-8
49 | : UTF-8 is everywhere, in strings *and* in the program code. Finally you can use $\Phi = \Phi + 1$
50 | in your source code.
51 |
52 | Open Source
53 | : The Go license is completely open source.
54 |
55 | Fun
56 | : Programming with Go should be fun!
57 |
58 | As I mentioned Erlang also shares some features of Go. A notable difference between Erlang and Go is
59 | that Erlang borders on being a functional language, while Go is imperative. And Erlang runs in
60 | a virtual machine, while Go is compiled.
61 |
62 |
63 | ## How to Read this Book
64 |
65 | I've written this book for people who already know some programming languages and how to program. In
66 | order to use this book, you (of course) need Go installed on your system, but you can easily try
67 | examples online in the Go playground^[.]. All exercises in this book work
68 | with Go 1, the first stable release of Go -- if not, it's a bug.
69 |
70 | The best way to learn Go is to create your own programs. Each chapter therefore includes exercises
71 | (and answers to exercises) to acquaint you with the language. Each exercise is either *easy*,
72 | *intermediate*, or *difficult*. The answers are included after the exercises on a new page. Some
73 | exercises don't have an answer; these are marked with an asterisk.
74 |
75 | Here's what you can expect from each chapter:
76 |
77 | (#basics)
78 | : We'll look at the basic types, variables, and control structures available in the language.
79 |
80 | (#functions)
81 | : Here we look at functions, the basic building blocks of Go programs.
82 |
83 | (#packages)
84 | : We'll see that functions and data can be grouped together in packages. We'll also see how to
85 | document and test our packages.
86 |
87 | (#beyond-the-basics)
88 | : We'll create our own types. We'll also look at memory allocations in Go.
89 |
90 | (#interfaces)
91 | : We'll learn how to use interfaces. Interfaces are the central concept in Go,
92 | as Go does not support object orientation in the traditional sense.
93 |
94 | (#concurrency)
95 | : We'll learn the `go` keyword, which can be used to start function in separate routines (called
96 | goroutines). Communication with those goroutines is done via channels.
97 |
98 | (#communication)
99 | : Finally we'll see how to interface with the rest of the world from within a Go program. We'll
100 | see how to create files and read and write to and from them. We'll also briefly look into
101 | networking.
102 |
103 |
104 | ## Official Documentation
105 |
106 | There is a substantial amount of documentation written about Go. The Go Tutorial [@go_tutorial], the
107 | Go Tour (with lots of exercises) and the Effective Go [@effective_go] are helpful resources. The
108 | website is a very good starting point for reading up on
109 | Go^[ itself is served by `godoc`.]. Reading these documents is certainly not
110 | required, but it is recommended.
111 |
112 | > When searching on the internet use the term "golang" instead of plain "go".
113 |
114 | Go comes with its own documentation in the form of a program called `godoc`^[When building from
115 | source it must be installed separately with `go get golang.org/x/tools/cmd/godoc`.]. If you are
116 | interested in the documentation for the built-ins, simply do this:
117 |
118 | % godoc builtin
119 |
120 | To get the documentation of the `hash` package, just:
121 |
122 | % godoc hash
123 |
124 | To read the documentation of `fnv` contained in `hash`, you'll need to issue `godoc hash/fnv` as
125 | `fnv` is a subdirectory of `hash`.
126 |
127 | ~~~go
128 | PACKAGE DOCUMENTATION
129 |
130 | package fnv
131 | import "hash/fnv"
132 |
133 | Package fnv implements FNV-1 and FNV-1a, non-cryptographic hash
134 | ...
135 | ~~~
136 |
--------------------------------------------------------------------------------
/learninggo.md:
--------------------------------------------------------------------------------
1 | %%%
2 | Title = "Learning Go"
3 | abbrev = "Learning Go"
4 | ipr= "trust200902"
5 | area = "Application"
6 | workgroup = "Go Working Group"
7 | keyword = ["Go", "Language", "Computer"]
8 |
9 | date = 2018-08-25T00:00:00Z
10 |
11 | [seriesInfo]
12 | name = "Internet-Draft"
13 | value = "draft-learning-go-00"
14 | stream = "IETF"
15 | status = "informational"
16 |
17 | [[author]]
18 | initials = "R."
19 | surname = "Gieben"
20 | fullname = "R. (Miek) Gieben"
21 | [author.address]
22 | email = "miek@miek.nl"
23 | %%%
24 |
25 | .# Preface
26 | {{preface.md}}
27 |
28 | {mainmatter}
29 |
30 | {.title}
31 | # Learning Go
32 | {.title}
33 | !---
34 | 
35 | !---
36 |
37 |
38 | # Introduction
39 | {{introduction.md}}
40 |
41 |
42 | # Basics
43 | {{basics.md}}
44 |
45 |
46 | # Functions
47 | {{functions.md}}
48 |
49 |
50 | # Packages
51 | {{packages.md}}
52 |
53 |
54 | # Beyond the basics
55 | {{beyond.md}}
56 |
57 |
58 | # Interfaces
59 | {{interfaces.md}}
60 |
61 |
62 | # Concurrency
63 | {{channels.md}}
64 |
65 |
66 | # Communication
67 | {{communication.md}}
68 |
69 |
70 | {{inc/bib.xml}}
71 | {backmatter}
72 |
--------------------------------------------------------------------------------
/packages.md:
--------------------------------------------------------------------------------
1 | {.epigraph}
2 | > "\^"
3 | ****
4 |
5 | Quote: Answer to whether there is a bit wise negation operator -- Ken Thompson
6 |
7 | A package (!package) is a collection of functions and data.
8 |
9 | You declare a package with the `package`(!keywords, package) keyword. The
10 | filename does not have to match the package name. The convention for package
11 | names is to use lowercase characters. Go packages may consist of multiple files,
12 | but they share the `package ` line. Let's define a package `even` in the
13 | file `even.go`.
14 |
15 | (!functions, exported)
16 | (!functions, private)
17 | (!functions, public)
18 |
19 | <{{src/packages/even.go}}
20 |
21 | Here <<1>> we start a new namespace: "even". The function `Even` <<2>> starts with
22 | a capital letter. This means the function is *exported*, and may be used outside
23 | our package (more on that later). The function `odd` <<3>> does not start with
24 | a capital letter, so it is a *private* function.
25 |
26 | Now we just need to build the package. We create a directory under `$GOPATH`,
27 | and copy `even.go` there (see (#compiling-and-running-code) in (#basics)).
28 |
29 | % mkdir $GOPATH/src/even
30 | % cp even.go $GOPATH/src/even
31 | % go build
32 | % go install
33 |
34 | Now we can use the package in our own program `myeven.go`:
35 |
36 | <{{src/packages/myeven.go}}
37 |
38 | Import <<1>> the following packages. The *local* package `even` is imported here
39 | <<2>>. This <<3>> imports the official `fmt` package. And now we use <<4>> the
40 | function from the `even` package. The syntax for accessing a function from
41 | a package is `.FunctionName()`. And finally we can build our program.
42 |
43 | % go build myeven.go
44 | % ./myeven
45 | Is 5 even? false
46 |
47 | If we change our `myeven.go` at <<4>> to use the unexported function `even.odd`:
48 | `fmt.Printf("Is %d even? %v\n", i, even.odd(i))` We get an error when compiling,
49 | because we are trying to use a
50 | *private* function:
51 |
52 | myeven.go: cannot refer to unexported name even.odd
53 |
54 | Note that the "starts with capital $\rightarrow$ exported", "starts with
55 | lower\-case $\rightarrow$ private" rule also extends to other names (new
56 | types, global variables) defined in the package. Note that the term "capital" is
57 | not limited to US-ASCII -- it extends to all bicameral alphabets (Latin, Greek,
58 | Cyrillic, Armenian and Coptic).
59 |
60 |
61 | ## Identifiers
62 | The Go standard library names some function with the old (Unix) names while
63 | others are in CamelCase. The convention is to leave well-known legacy
64 | not-quite-words alone rather than try to figure out where the capital letters
65 | go: `Atoi`, `Getwd`, `Chmod`. CamelCasing works best when you have whole words
66 | to work with: `ReadFile`, `NewWriter`, `MakeSlice`. The convention in Go is to
67 | use CamelCase rather than underscores to write multi-word names.
68 |
69 | As we did above in our `myeven` program, accessing content from an imported
70 | (with `import` (!keywords, import)) package is done with using the package's
71 | name and then a dot. After (!package, bytes) `import "bytes"` the importing
72 | program can talk about `bytes.Buffer`. A package name should be good, short,
73 | concise and evocative. The convention in Go is that package names are lowercase,
74 | single word names.
75 |
76 | The package name used in the `import` statement is the default name used. But if
77 | the need arises (two different packages with the same name for instance), you
78 | can override this default: `import bar "bytes"` The function `Buffer` is now
79 | accessed as `bar.Buffer`.
80 |
81 | Another convention is that the package name is the base name of its source
82 | directory; the package in `src/compress/gzip` is imported as `compress/gzip` but
83 | has name `gzip`, not `compress/gzip`.
84 |
85 | It is important to avoid stuttering when naming things. For instance, the
86 | buffered reader type in the `bufio` (!package, bufio) package is called
87 | `Reader`, not `BufReader`, because users see it as `bufio.Reader`, which is
88 | a clear, concise name.
89 |
90 | Similarly, the function to make new instances of `ring.Ring` (package
91 | `container/ring`), would normally be called `NewRing`, but since `Ring` is the
92 | only type exported by the package, and since the package is called
93 | `ring`(!package, ring), it's called just `New`. Clients of the package see
94 | that as `ring.New`. Use the package structure to help you choose good names.
95 |
96 | Another short example is `once.Do` (see package `sync`); `once.Do(setup)` reads
97 | well and would not be improved by writing `once.DoOrWaitUntilDone(setup)`. Long
98 | names don't automatically make things more readable.
99 |
100 |
101 | ## Documenting packages
102 | When we created our `even` package, we skipped over an important item:
103 | documentation. Each package should have a *package comment*, a block comment
104 | preceding the `package` clause. In our case we should extend the beginning of
105 | the package, with:
106 |
107 | ~~~go
108 | // The even package implements a fast function for detecting if an integer
109 | // is even or not.
110 | package even
111 | ~~~
112 |
113 | When running `go doc` this will show up at the top of the page. When a package
114 | consists of multiple files the package comment should only appear in one
115 | file. A common convention (in really big packages) is to have a separate
116 | `doc.go` that only holds the package comment. Here is a snippet from the
117 | official `regexp` package:
118 |
119 | ~~~go
120 | /*
121 | The regexp package implements a simple library for
122 | regular expressions.
123 |
124 | The syntax of the regular expressions accepted is:
125 |
126 | regexp:
127 | concatenation { '|' concatenation }
128 | */
129 | package regexp
130 | ~~~
131 |
132 |
133 | Each defined (and exported) function should have a small line of text
134 | documenting the behavior of the function. Again to extend our `even` package:
135 |
136 | ~~~go
137 | // Even returns true of i is even. Otherwise false is returned.
138 | func Even(i int) bool {
139 | ~~~
140 |
141 | And even though `odd` is not exported, it's good form to document it as well.
142 |
143 | ~~~go
144 | // odd is the opposite of Even.
145 | func odd(i int) bool {
146 | ~~~
147 |
148 |
149 | ## Testing packages
150 | In Go it is customary to write (unit) tests for your package. Writing tests
151 | involves the `testing` package and the program `go test`(!tooling, go test).
152 | Both have excellent documentation.
153 |
154 | The `go test` program runs all the test functions. Without any defined tests for
155 | our `even` package, `go test` yields:
156 |
157 | % go test
158 | ? even [no test files]
159 |
160 | Let us fix this by defining a test in a test file. Test files reside in the
161 | package directory and are named `*_test.go`. Those test files are just like
162 | other Go programs, but `go test` will only execute the test functions. Each test
163 | function has the same signature and its name should start with
164 | `Test`: `func TestXxx(t *testing.T)` .
165 |
166 | When writing test you will need to tell `go test` whether a test was
167 | successful or not. A successful test function just returns. When
168 | the test fails you can signal this with the following
169 | functions. These are the most important ones (see `go doc testing` or `go help testfunc` for more):
170 |
171 |
172 | * `func (t *T) Fail()`, `Fail` marks the test function as having failed but
173 | continues execution.
174 |
175 | * `func (t *T) FailNow()`, `FailNow` marks the test function as having failed
176 | and stops its execution. Any remaining tests in this file are skipped, and
177 | execution continues with the next test.
178 |
179 | * `func (t *T) Log(args ...interface{})`, `Log` formats its arguments using
180 | default formatting, analogous to `Print()`, and records the text in the error
181 | log.
182 |
183 | * `func (t *T) Fatal(args ...interface{})`, `Fatal` is equivalent to `Log()`
184 | followed by `FailNow()`.
185 |
186 | Putting all this together we can write our test. First we pick a name:
187 | `even_test.go`. Then we add the following contents:
188 |
189 | <{{src/packages/even_test.go}}
190 |
191 | A test file belongs to the current <<1>> package. This is not only convenient, but
192 | also allows tests of unexported functions and structures. We then <<2>> import the
193 | `testing` package. And finally the test we want to execute. The code here <<3>>
194 | should hold no surprises: we check if the `Even` function works OK. And now, the
195 | moment we have been waiting for executing the test.
196 |
197 | % go test
198 | ok even 0.001s
199 |
200 | Our test ran and reported `ok`. Success! If we redefine our test function, we
201 | can see the result of a failed test:
202 |
203 | ~~~go
204 | // Entering the twilight zone
205 | func TestEven(t *testing.T) {
206 | if Even(2) {
207 | t.Log("2 should be odd!")
208 | t.Fail()
209 | }
210 | }
211 | ~~~
212 |
213 | We now get:
214 |
215 | FAIL even 0.004s
216 | --- FAIL: TestEven (0.00 seconds)
217 | 2 should be odd!
218 | FAIL
219 |
220 | And you can act accordingly (by fixing the test for instance).
221 |
222 | Writing new packages should go hand in hand with writing (some)
223 | documentation and test functions. It will make your code better and it
224 | shows that you really put in the effort.
225 |
226 | The Go test suite also allows you to incorporate example functions which serve
227 | as documentation *and* as tests. These functions need to start with `Example`.
228 |
229 | ~~~go
230 | func ExampleEven() {
231 | if Even(2) {
232 | fmt.Printf("Is even\n")
233 | }
234 | // Output: //<<1>>
235 | // Is even
236 | }
237 | ~~~
238 |
239 | Those last two comments lines <<1>> are part of the example, `go test` uses those
240 | to check the *generated* output with the text in the comments. If there is
241 | a mismatch the test fails.
242 |
243 |
244 | ## Useful packages
245 | The standard libary of Go includes a huge number of packages. It is very
246 | enlightening to browse the `$GOROOT/src` directory and look at the
247 | packages. We cannot comment on each package, but the following are worth
248 | a mention: ^[The descriptions are copied from the packages' `go doc`.]
249 |
250 | `fmt`
251 | : (!package, fmt)
252 | Package `fmt` implements formatted I/O with functions analogous
253 | to C's `printf` and `scanf`. The format verbs are derived
254 | from C's but are simpler. Some verbs (%-sequences) that can be used:
255 |
256 | * *%v*, the value in a default format. when printing structs, the plus flag (%+v) adds field names.
257 | * *%#v*, a Go-syntax representation of the value.
258 | * *%T*, a Go-syntax representation of the type of the value.
259 |
260 | `io`
261 | : (!package, io)
262 | This package provides basic interfaces to I/O primitives.
263 | Its primary job is to wrap existing implementations of such primitives,
264 | such as those in package os, into shared public interfaces that
265 | abstract the functionality, plus some other related primitives.
266 |
267 | `bufio`
268 | : (!package, bufio)
269 | This package implements buffered I/O. It wraps an
270 | `io.Reader`
271 | or
272 | `io.Writer`
273 | object, creating another object (Reader or Writer) that also implements
274 | the interface but provides buffering and some help for textual I/O.
275 |
276 | `sort`
277 | : (!package, sort)
278 | The `sort` package provides primitives for sorting arrays
279 | and user-defined collections.
280 |
281 | `strconv`
282 | : (!package, strconv)
283 | The `strconv` package implements conversions to and from
284 | string representations of basic data types.
285 |
286 | `os`
287 | : (!package, os)
288 | The `os` package provides a platform-independent interface to operating
289 | system functionality. The design is Unix-like.
290 |
291 | `sync`
292 | : (!package, sync)
293 | The package `sync` provides basic synchronization primitives such as mutual
294 | exclusion locks.
295 |
296 | `flag`
297 | : (!package, flag)
298 | The `flag` package implements command-line flag parsing.
299 |
300 | `encoding/json`
301 | : (!package, encoding/json)
302 | The `encoding/json` package implements encoding and decoding of JSON objects as
303 | defined in RFC 4627 [@RFC4627].
304 |
305 | `html/template`
306 | : (!package, html/template)
307 | Data-driven templates for generating textual output such as HTML.
308 |
309 | Templates are executed by applying them to a data structure. Annotations in
310 | the template refer to elements of the data structure (typically a field of
311 | a struct or a key in a map) to control execution and derive values to be
312 | displayed. The template walks the structure as it executes and the "cursor"
313 | @ represents the value at the current location in the structure.
314 |
315 | `net/http`
316 | : (!package, net/http)
317 | The `net/http` package implements parsing of HTTP requests, replies,
318 | and URLs and provides an extensible HTTP server and a basic
319 | HTTP client.
320 |
321 | `unsafe`
322 | : (!package, unsafe)
323 | The `unsafe` package contains operations that step around the type safety of Go programs.
324 | Normally you don't need this package, but it is worth mentioning that *unsafe* Go programs
325 | are possible.
326 |
327 | `reflect`
328 | : (!package, reflect)
329 | The `reflect` package implements run-time reflection, allowing a program to
330 | manipulate objects with arbitrary types. The typical use is to take a
331 | value with static type `interface{}` and extract its dynamic type
332 | information by calling `TypeOf`, which returns an object with interface
333 | type `Type`. See (#interfaces), Section (#introspection-and-reflection).
334 |
335 | `os/exec`
336 | : (!package, os/exec) The `os/exec` package runs external commands.
337 |
338 |
339 | ## Exercises
340 | {{ex/packages/ex.md}}
341 |
--------------------------------------------------------------------------------
/preface.md:
--------------------------------------------------------------------------------
1 | The [source of this book](https://github.com/miekg/learninggo) is written in
2 | [mmark](https://mmark.nl) and is converted from the [original LaTeX source](https://github.com/miekg/gobook).
3 |
4 | *All example code used in this book is hereby licensed under the Apache License version 2.0.*
5 |
6 | > This work is licensed under the Attribution-NonCommercial-ShareAlike 3.0 Unported License. To
7 | > view a copy of this license, visit
8 | > or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
9 |
10 | The following people made large or small contributions to earlier versions of this book:
11 |
12 | {{contributors.md}}
13 |
14 | "Learning Go" has been translated into (note that this used the original LaTeX source).
15 |
16 | * Chinese, by Xing Xing, 这里是中文译本:
17 |
18 | I hope this book is useful.
19 |
20 | Miek Gieben, London, 2015.
21 |
22 | This book still sees development, small incremental improvements trickle in from Github.
23 |
24 | Miek Gieben, London, 2017.
25 |
26 | Learning Go's source has been rewritten in [mmark2](https://github.com/mmarkdown/mmark), but did not see any
27 | other changes. This books translates cleanly into an [RFC-like document](learninggo-2.txt).
28 |
29 | Miek Gieben, London, 2018.
30 |
--------------------------------------------------------------------------------
/src/basics/array-and-slices.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {
4 | var array [100]int //<<1>>
5 | slice := array[0:99] //<<2>>
6 |
7 | slice[98] = 1 //<<3>>
8 | slice[99] = 2 //<<4>>
9 | }
10 |
--------------------------------------------------------------------------------
/src/basics/helloworld.go:
--------------------------------------------------------------------------------
1 | package main //<<1>>
2 |
3 | import "fmt" //<<2>> // Implements formatted I/O.
4 |
5 | /* Print something */ //<<3>>
6 | func main() { //<<4>>
7 | fmt.Printf("Hello, world.") //<<5>>
8 | }
9 |
--------------------------------------------------------------------------------
/src/basics/types.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | func main() {
4 | var a int
5 | var b int32
6 | b = a + a
7 | b = b + 5
8 | }
9 |
--------------------------------------------------------------------------------
/src/beyond/struct.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | type NameAge struct {
6 | name string // Both non exported fields.
7 | age int
8 | }
9 |
10 | func main() {
11 | a := new(NameAge)
12 | a.name = "Pete"
13 | a.age = 42
14 | fmt.Printf("%v\n", a)
15 | }
16 |
--------------------------------------------------------------------------------
/src/channels/for-chan.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | ch := make(chan int)
7 | go shower(ch)
8 | for i := 0; i < 10; i++ {
9 | ch <- i
10 | }
11 | }
12 |
13 | func shower(c chan int) {
14 | for {
15 | j := <-c
16 | fmt.Printf("%d\n", j)
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/channels/for-quit-chan.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | ch := make(chan int)
7 | quit := make(chan bool)
8 | go shower(ch, quit)
9 | for i := 0; i < 10; i++ {
10 | ch <- i
11 | }
12 | quit <- false // or true, does not matter
13 | }
14 |
15 | func shower(c chan int, quit chan bool) {
16 | for {
17 | select {
18 | case j := <-c:
19 | fmt.Printf("%d\n", j)
20 | case <-quit:
21 | break
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/channels/sleep.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "time"
6 | )
7 |
8 | func ready(w string, sec int) {
9 | time.Sleep(time.Duration(sec) * time.Second)
10 | fmt.Println(w, "is ready!")
11 | }
12 |
13 | func main() {
14 | go ready("Tea", 2) //<1>
15 | go ready("Coffee", 1) //<1>
16 | fmt.Println("I'm waiting")
17 | time.Sleep(5 * time.Second) //<2>
18 | }
19 |
--------------------------------------------------------------------------------
/src/communication/buffile.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bufio"
5 | "log"
6 | "os"
7 | )
8 |
9 | func main() {
10 | buf := make([]byte, 1024)
11 | f, e := os.Open("/etc/passwd") //<<1>>
12 | if e != nil {
13 | log.Fatalf(e)
14 | }
15 | defer f.Close()
16 | r := bufio.NewReader(f) //<<2>>
17 | w := bufio.NewWriter(os.Stdout)
18 | defer w.Flush() //<<3>>
19 | for {
20 | n, e := r.Read(buf) //<<4>>
21 | if e != nil {
22 | log.Fatalf(e)
23 | }
24 | if n == 0 {
25 | break
26 | }
27 | w.Write(buf[0:n]) //<<5>>
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/communication/file.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "log"
5 | "os"
6 | )
7 |
8 | func main() {
9 | buf := make([]byte, 1024)
10 | f, e := os.Open("/etc/passwd") //<<1>>
11 | if e != nil {
12 | log.Fatalf(e)
13 | }
14 | defer f.Close() //<<2>>
15 | for {
16 | n, e := f.Read(buf) //<<3>>
17 | if e != nil {
18 | log.Fatalf(e) //<<4>>
19 | }
20 | if n == 0 { //<<5>>
21 | break
22 | }
23 | os.Stdout.Write(buf[:n]) //<<6>>
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/functions/anon-func.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import "fmt"
4 |
5 | func main() {
6 | a := func() { //<<1>>
7 | fmt.Println("Hello")
8 | } //<<2>>
9 | a() //<<3>>
10 | }
11 |
--------------------------------------------------------------------------------
/src/packages/even.go:
--------------------------------------------------------------------------------
1 | package even //<<1>>
2 |
3 | func Even(i int) bool { //<<2>>
4 | return i%2 == 0
5 | }
6 |
7 | func odd(i int) bool { //<<3>>
8 | return i%2 == 1
9 | }
10 |
--------------------------------------------------------------------------------
/src/packages/even_test.go:
--------------------------------------------------------------------------------
1 | package even //<<1>>
2 |
3 | import "testing" //<<2>>
4 |
5 | func TestEven(t *testing.T) { //<<3>>
6 | if !Even(2) {
7 | t.Log("2 should be even!")
8 | t.Fail()
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/packages/myeven.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import ( //<<1>>
4 | "even" //<<2>>
5 | "fmt" //<<3>>
6 | )
7 |
8 | func main() {
9 | i := 5
10 | fmt.Printf("Is %d even? %v\n", i, even.Even(i)) //<<4>>
11 | }
12 |
--------------------------------------------------------------------------------
/tab/conversion.md:
--------------------------------------------------------------------------------
1 | From | `b []byte` | `i []int` | `r []rune` | `s string` | `f float32` | `i int`
2 | -----------|----------------|----------------|----------------|----------------|----------------|-------------
3 | **To**| | | | | |
4 | `[]byte` | · | | | `[]byte(s)` | |
5 | `[]int` | | · | | `[]int(s)` | |
6 | `[]rune` | | | | `[]rune(s)` | |
7 | `string` | `string(b)` | `string(i)` | `string(r)` | · | |
8 | `float32` | | | | | · | `float32(i)`
9 | `int` | | | | | `int(f)` | ·
10 | Table: Valid conversions, `float64` works the same as `float32`.
11 |
--------------------------------------------------------------------------------
/tab/functions.md:
--------------------------------------------------------------------------------
1 | ---------|----------|-----------|---------
2 | `close` | `new` | `panic` | `complex`
3 | `delete` | `make` | `recover` | `real`
4 | `len` | `append` | `print` | `imag`
5 | `cap` | `copy` | `println` |
6 | Table: Pre-defined functions in Go.
7 |
--------------------------------------------------------------------------------
/tab/keywords.md:
--------------------------------------------------------------------------------
1 | ------------|---------------|-----------|------------|--------
2 | `break` |`default` |`func` |`interface` |`select`
3 | `case` |`defer` |`go` |`map` |`struct`
4 | `chan` |`else` |`goto` |`package` |`switch`
5 | `const` |`fallthrough` |`if` |`range` |`type`
6 | `continue` |`for` |`import` |`return` |`var`
7 | Table: Keywords in Go.
8 |
--------------------------------------------------------------------------------
/tab/precedence.md:
--------------------------------------------------------------------------------
1 | Precedence | Operator(s)
2 | -----------|------------------
3 | Highest | `* / % << >> & &^`
4 | | `+ - | ^`
5 | | `== != < <= > >=`
6 | | `<-`
7 | | `&&`
8 | Lowest | \|\|
9 | Table: Operator precedence.
10 |
--------------------------------------------------------------------------------