├── 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 | ![A stack](fig/stack.png) 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 | 20 | 22 | 29 | 34 | 35 | 42 | 47 | 48 | 55 | 60 | 61 | 68 | 73 | 74 | 81 | 86 | 87 | 94 | 101 | 108 | 115 | 122 | 129 | 136 | 143 | 150 | 155 | 156 | 163 | 170 | 175 | 176 | 183 | 190 | 195 | 196 | 203 | 210 | 215 | 216 | 223 | 230 | 237 | 244 | 251 | 258 | 263 | 264 | 271 | 278 | 285 | 292 | 299 | 306 | 307 | 326 | 329 | 330 | 332 | 333 | 335 | image/svg+xml 336 | 338 | 339 | 340 | 341 | 342 | 346 | 354 | 362 | 370 | 378 | 386 | 394 | 402 | 410 | 421 | 426 | 431 | push(k) 443 | pop() 455 | k 467 | k 479 | i 491 | l 503 | m 515 | i++ 527 | i-- 539 | 0 551 | 552 | 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+""},!_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 | ![Peeling away the layers using reflection.](fig/reflection.png) 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 | ![](fig/bumper-inverse.png) 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 | --------------------------------------------------------------------------------