├── ex-intro └── .gitempty ├── go.tex ├── src ├── short.go ├── even_test.go ├── scope.go ├── scope2.go ├── anon-func.go ├── even.go ├── scope3.go ├── struct.go ├── types.go ├── array-and-slices.go ├── sleep.go ├── sleep-chan.go ├── myeven.go ├── array-and-slices.2.go ├── file.go ├── buffile.go ├── stack.go ├── callback.go └── helloworld.go ├── fig ├── bumper.png ├── gopher.png ├── bumper-inverse.png ├── avatar-miekg-300x300.jpg ├── Makefile ├── scope2.tex ├── scope1.tex ├── scope3.tex ├── reflection.tex └── function.tex ├── fonts ├── PT-Sans.zip ├── PTC55F.ttf ├── PTC75F.ttf ├── PTN57F.ttf ├── PTN77F.ttf ├── PTS55F.ttf ├── PTS56F.ttf ├── PTS75F.ttf ├── PTS76F.ttf ├── SourceCodePro-Bold.ttf ├── SourceCodePro-Regular.ttf └── Paratype PT Sans Free Font License.txt ├── creative_commons ├── cc_by_30.pdf ├── cc_cc_30.pdf ├── cc_nc_30.pdf ├── cc_nd_30.pdf ├── cc_pd_30.pdf ├── cc_sa_30.pdf ├── cc_sampling_30.pdf ├── cc_dev_nations_30.pdf ├── cc_sampling_plus_30.pdf ├── cc_by_30.svg ├── cc_nd_30.svg ├── cc_sa_30.svg ├── cc_nc_30.svg ├── cc_dev_nations_30.svg ├── cc_pd_30.svg ├── cc_cc_30.svg ├── cc_sampling_30.svg └── cc_sampling_plus_30.svg ├── ex-unsorted ├── ex-reverse-slice.tex └── ideas ├── ex-communication ├── src │ ├── uniq.pl │ ├── uniq.go │ ├── proc.pl │ ├── echo.go │ ├── wc.go │ ├── proc.go │ ├── finger.go │ └── permrec.go ├── ex-quine.tex ├── ex-wordcount.tex ├── ex-uniq.tex ├── ex-finger.tex ├── ex-echo.tex ├── ex-numbercruncher.tex └── ex-processes.tex ├── tab ├── Makefile ├── functions.tex ├── precedence.tex ├── keywords.tex └── conversion.tex ├── draft.tex ├── go-nits-contributors.tex ├── ex-functions ├── src │ ├── for-func.go │ ├── var-arg.go │ ├── bubblesort.go │ ├── ave.go │ ├── stack-by-value.go │ ├── stack.go │ ├── fib.go │ └── queen8.go ├── ex-queen8.tex ├── ex-average.tex ├── ex-for.tex ├── ex-vararg.tex ├── ex-fib.tex ├── ex-order.tex ├── ex-scope.tex ├── ex-map.tex ├── ex-bubblesort.tex ├── ex-funcfunc.tex ├── ex-minmax.tex └── ex-stack.tex ├── .gitignore ├── ex-basics ├── src │ ├── for.go │ ├── string1.go │ ├── string3.go │ ├── string2.go │ ├── for-arr.go │ ├── stringrev.go │ └── fizzbuzz.go ├── ex-fizzbuzz.tex ├── ex-average-no-func.tex ├── ex-doc.tex ├── ex-for.tex └── ex-strings.tex ├── ex-packages ├── src │ ├── pushpop_test.go │ ├── stack-as-package.go │ └── calc.go ├── ex-calc.tex └── ex-stack-package.tex ├── ex-channels ├── src │ ├── for-chan.go │ ├── for-quit-chan.go │ └── fib.go ├── ex-fib.tex └── ex-for-channels.tex ├── ex-beyond ├── src │ ├── doubly-linked-list-container.go │ ├── map.go │ ├── cat2.go │ ├── cat.go │ └── doubly-linked-list.go ├── ex-map.tex ├── ex-copy-array.ex ├── ex-pointer-arith.tex ├── ex-doubly-linked-list.tex ├── ex-cat.tex ├── ex-pointers.tex └── ex-pointers-method.tex ├── todo.tex ├── ex-interfaces ├── ex-pointers-and-reflect.tex ├── ex-interfaces.tex └── ex-minmax.tex ├── about-miekg.tex ├── coderemarks.sty ├── go-contributors.tex ├── Makefile ├── go-colophon.tex ├── bin ├── go-lstinputlisting.pl └── go-lstlisting.pl ├── go-cc-license.tex ├── README.mkd ├── go-preface.tex ├── go_a4.tex ├── go-setup.tex ├── blocksbook.cls ├── go-communication.tex ├── go.bib └── go-channels.tex /ex-intro/.gitempty: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /go.tex: -------------------------------------------------------------------------------- 1 | go_a4.tex -------------------------------------------------------------------------------- /src/short.go: -------------------------------------------------------------------------------- 1 | package main 2 | func main() {} 3 | -------------------------------------------------------------------------------- /fig/bumper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fig/bumper.png -------------------------------------------------------------------------------- /fig/gopher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fig/gopher.png -------------------------------------------------------------------------------- /fonts/PT-Sans.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fonts/PT-Sans.zip -------------------------------------------------------------------------------- /fonts/PTC55F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fonts/PTC55F.ttf -------------------------------------------------------------------------------- /fonts/PTC75F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fonts/PTC75F.ttf -------------------------------------------------------------------------------- /fonts/PTN57F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fonts/PTN57F.ttf -------------------------------------------------------------------------------- /fonts/PTN77F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fonts/PTN77F.ttf -------------------------------------------------------------------------------- /fonts/PTS55F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fonts/PTS55F.ttf -------------------------------------------------------------------------------- /fonts/PTS56F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fonts/PTS56F.ttf -------------------------------------------------------------------------------- /fonts/PTS75F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fonts/PTS75F.ttf -------------------------------------------------------------------------------- /fonts/PTS76F.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fonts/PTS76F.ttf -------------------------------------------------------------------------------- /fig/bumper-inverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fig/bumper-inverse.png -------------------------------------------------------------------------------- /creative_commons/cc_by_30.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/creative_commons/cc_by_30.pdf -------------------------------------------------------------------------------- /creative_commons/cc_cc_30.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/creative_commons/cc_cc_30.pdf -------------------------------------------------------------------------------- /creative_commons/cc_nc_30.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/creative_commons/cc_nc_30.pdf -------------------------------------------------------------------------------- /creative_commons/cc_nd_30.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/creative_commons/cc_nd_30.pdf -------------------------------------------------------------------------------- /creative_commons/cc_pd_30.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/creative_commons/cc_pd_30.pdf -------------------------------------------------------------------------------- /creative_commons/cc_sa_30.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/creative_commons/cc_sa_30.pdf -------------------------------------------------------------------------------- /ex-unsorted/ex-reverse-slice.tex: -------------------------------------------------------------------------------- 1 | 1. reverse slice 2 | give back new one 3 | 4 | 2 reverse in place 5 | -------------------------------------------------------------------------------- /fig/avatar-miekg-300x300.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fig/avatar-miekg-300x300.jpg -------------------------------------------------------------------------------- /fonts/SourceCodePro-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fonts/SourceCodePro-Bold.ttf -------------------------------------------------------------------------------- /fonts/SourceCodePro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/fonts/SourceCodePro-Regular.ttf -------------------------------------------------------------------------------- /creative_commons/cc_sampling_30.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/creative_commons/cc_sampling_30.pdf -------------------------------------------------------------------------------- /creative_commons/cc_dev_nations_30.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/creative_commons/cc_dev_nations_30.pdf -------------------------------------------------------------------------------- /creative_commons/cc_sampling_plus_30.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/miekg/gobook/HEAD/creative_commons/cc_sampling_plus_30.pdf -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/even_test.go: -------------------------------------------------------------------------------- 1 | package even 2 | 3 | import "testing" 4 | 5 | func TestEven(t *testing.T) { 6 | if ! Even(2) { 7 | t.Log("2 should be even!") 8 | t.Fail() 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tab/Makefile: -------------------------------------------------------------------------------- 1 | tabs := $(patsubst %.gnumeric,%.tex,$(wildcard *.gnumeric)) 2 | 3 | %.tex: %.gnumeric 4 | ssconvert -T Gnumeric_html:latex $< $@ 2>/dev/null 5 | 6 | all: ${tabs} 7 | 8 | clean: 9 | -------------------------------------------------------------------------------- /draft.tex: -------------------------------------------------------------------------------- 1 | \newcommand{\pagedraft}{ 2 | \begin{tikzpicture}[remember picture,overlay] 3 | \node [rotate=60,scale=10,text opacity=0.1] 4 | at (current page.center) {Draft}; 5 | \end{tikzpicture} 6 | } 7 | -------------------------------------------------------------------------------- /go-nits-contributors.tex: -------------------------------------------------------------------------------- 1 | %% smaller stuff, like nits, typos and other stuff 2 | \emph{Alexander Katasonov}, 3 | \emph{Daniele Pala}, 4 | \emph{Iaroslav Tymchenko}, 5 | \emph{Nicolas Kaiser}, 6 | \emph{Marco Ynema}. 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/scope.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var a = 6 4 | 5 | func main() { 6 | p() 7 | q() 8 | p() 9 | } 10 | 11 | func p() { 12 | println(a) 13 | } 14 | 15 | func q() { 16 | a := 5 17 | println(a) 18 | } 19 | -------------------------------------------------------------------------------- /src/scope2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var a = 6 4 | 5 | func main() { 6 | p() 7 | q() 8 | p() 9 | } 10 | 11 | func p() { 12 | println(a) 13 | } 14 | 15 | func q() { 16 | a = 5 17 | println(a) 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.6 2 | *.8 3 | *.pdf 4 | 6.out 5 | *.bak 6 | .fig 7 | .tab 8 | go.aux 9 | go.bbl 10 | go.blg 11 | go.code 12 | go.ex 13 | go.idx 14 | go.ilg 15 | go.ind 16 | go.lof 17 | go.log 18 | go.out 19 | go.toc 20 | -------------------------------------------------------------------------------- /ex-basics/src/for.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | for i := 0; i < 10; i++ { |\coderemark{See page % 7 | \pageref{sec:for}}| 8 | fmt.Printf("%d\n", i) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /fig/Makefile: -------------------------------------------------------------------------------- 1 | pdfs := $(patsubst %.svg,%.pdf,$(wildcard *.svg)) 2 | 3 | %.pdf: %.svg 4 | inkscape --export-pdf=$@ $< 5 | pdfcrop $@ output.pdf && mv output.pdf $@ 6 | 7 | all: ${pdfs} 8 | 9 | clean: 10 | rm -f *.pdf 11 | -------------------------------------------------------------------------------- /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" |\coderemark{String concatenation}| 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/anon-func.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | a := func() { |\coderemark{Define a nameless function and assign to \var{a}}| 5 | println("Hello") 6 | } |\coderemark{No () here}| 7 | a() |\coderemark{Call the function}| 8 | } 9 | -------------------------------------------------------------------------------- /src/even.go: -------------------------------------------------------------------------------- 1 | package even |\coderemark{Start our own namespace}| 2 | 3 | func Even(i int) bool { |\coderemark{Exported function}| 4 | return i % 2 == 0 5 | } 6 | 7 | func odd(i int) bool { |\coderemark{Private function}| 8 | return i % 2 == 1 9 | } 10 | -------------------------------------------------------------------------------- /ex-unsorted/ideas: -------------------------------------------------------------------------------- 1 | Extend bubblesort for strings 2 | 3 | notice how simular it is to ints (identical, except for function 4 | parameters). 5 | 6 | need to extent Interface chapter with a sorting example., 7 | how to go from simple to interface based sorting example 8 | -------------------------------------------------------------------------------- /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/string2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unicode/utf8" 6 | ) 7 | 8 | func main() { 9 | str := "dsjkdshdjsdh....js" 10 | fmt.Printf("String %s\nLength: %d, Runes: %d\n", str, 11 | len([]byte(str)), utf8.RuneCount([]byte(str))) 12 | } 13 | -------------------------------------------------------------------------------- /tab/functions.tex: -------------------------------------------------------------------------------- 1 | \begin{tabular}{lllll} 2 | \key{close} &\key{new} &\key{panic} &\key{complex} \\ 3 | \key{delete} &\key{make} &\key{recover} &\key{real} \\ 4 | \key{len} &\key{append} &\key{print} &\key{imag} \\ 5 | \key{cap} &\key{copy} &\key{println} &\\ 6 | \end{tabular} 7 | -------------------------------------------------------------------------------- /src/scope3.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var a int 4 | 5 | func main() { 6 | a = 5 7 | println(a) 8 | f() 9 | } 10 | 11 | func f() { 12 | a := 6 13 | println(a) 14 | g() 15 | } 16 | 17 | func g() { 18 | println(a) 19 | } 20 | -------------------------------------------------------------------------------- /src/struct.go: -------------------------------------------------------------------------------- 1 | package main 2 | import "fmt" 3 | 4 | type NameAge struct { 5 | name string |\coderemark{Not exported}| 6 | age int |\coderemark{Not exported}| 7 | } 8 | 9 | func main() { 10 | a := new(NameAge) 11 | a.name = "Pete"; a.age = 42 12 | fmt.Printf("%v\n", a) 13 | } 14 | -------------------------------------------------------------------------------- /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-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-functions/src/var-arg.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | prtthem(1, 4, 5, 7, 4) 7 | prtthem(1, 2, 4) 8 | } 9 | 10 | func prtthem(numbers... int) {|\coderemark{numbers is slice of ints}| 11 | for _, d := range numbers { 12 | fmt.Printf("%d\n", d) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/types.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | var a int |\coderemark{Generic integer type}| 5 | var b int32 |\coderemark{32 bits integer type}| 6 | a = 15 7 | b = a + a |\coderemark{Illegal mixing of these types}| 8 | b = b + 5 |\coderemark{5 is a constant, so this is OK}| 9 | } 10 | -------------------------------------------------------------------------------- /ex-beyond/src/doubly-linked-list-container.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "container/list" 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 | -------------------------------------------------------------------------------- /src/array-and-slices.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | var array [100]int |\coderemark{Create array, index from 0 to 99}| 5 | slice := array[0:99] |\coderemark{Create slice, index from 0 to 98}| 6 | 7 | slice[98] = 'a' |\coderemark{OK}| 8 | slice[99] = 'a' |\coderemark{Error: "throw: index out of range"}| 9 | } 10 | -------------------------------------------------------------------------------- /ex-basics/src/for-arr.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var arr [10]int |\coderemark{Create an array with 10 elements}| 7 | for i := 0; i < 10; i++ { 8 | arr[i] = i |\coderemark{Fill it one by one}| 9 | } 10 | fmt.Printf("%v", arr) |\coderemark{With \%v Go prints the value for us}| 11 | } 12 | -------------------------------------------------------------------------------- /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 | } 18 | -------------------------------------------------------------------------------- /src/sleep.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "time" 5 | "fmt" 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) 15 | go ready("Coffee", 1) 16 | fmt.Println("I'm waiting") 17 | time.Sleep(5 * time.Second) 18 | } 19 | -------------------------------------------------------------------------------- /tab/precedence.tex: -------------------------------------------------------------------------------- 1 | \begin{tabular}{ll} 2 | %%\toprule 3 | \textbf{Precedence} & \textbf{Operator(s)} \\ \midrule 4 | Highest & \verb!* / % << >> & &^! \\ 5 | & \verb!+ - | ^! \\ 6 | & \verb+== != < <= > >=+ \\ 7 | & \verb!<-! \\ 8 | & \verb!&&! \\ 9 | Lowest & \verb!||! \\ 10 | %%\bottomrule 11 | \end{tabular} 12 | -------------------------------------------------------------------------------- /ex-basics/src/stringrev.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | s := "foobar" 7 | a := []rune(s) |\coderemark{Again a conversion}| 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] |\coderemark{Parallel assignment}| 10 | } 11 | fmt.Printf("%s\n", string(a)) |\coderemark{Convert it back}| 12 | } 13 | -------------------------------------------------------------------------------- /ex-packages/ex-calc.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Calculator},difficulty=2] 2 | \label{ex:calc} 3 | \Question\label{ex:calc q1} Create a reverse polish calculator. Use your 4 | stack package. 5 | 6 | \end{Exercise} 7 | 8 | \begin{Answer} 9 | \Question This is one answer: 10 | \lstinputlisting[caption=A (rpn) calculator]{ex-packages/src/calc.go} 11 | 12 | \end{Answer} 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-functions/src/bubblesort.go: -------------------------------------------------------------------------------- 1 | package main 2 | import "fmt" 3 | 4 | func main() { 5 | n := []int{5, -1, 0, 12, 3, 5} 6 | fmt.Printf("unsorted %v\n", n) 7 | bubblesort(n) 8 | fmt.Printf("sorted %v\n", n) 9 | } 10 | 11 | func bubblesort(n []int) { 12 | for i := 0; i < len(n) - 1; i++ { 13 | for j := i + 1; j < len(n); j++ { 14 | if n[j] < n[i] { 15 | n[i], n[j] = n[j], n[i] 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/sleep-chan.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "time" 5 | "fmt" 6 | ) 7 | 8 | var c chan int 9 | 10 | func ready(w string, sec int) { 11 | time.Sleep(time.Duration(sec) * time.Second) 12 | fmt.Println(w, "is ready!") 13 | c <- 1 14 | } 15 | 16 | func main() { 17 | c = make(chan int) 18 | go ready("Tea", 2) 19 | go ready("Coffee", 1) 20 | fmt.Println("I'm waiting, but not too long") 21 | <-c 22 | <-c 23 | } 24 | -------------------------------------------------------------------------------- /ex-functions/ex-queen8.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Eight Queens Puzzle},difficulty=2] 2 | \label{ex:queen8} 3 | \Question\label{ex:queen8 q1} 4 | %%http://en.wikipedia.org/wiki/Eight_queens_puzzle 5 | \end{Exercise} 6 | 7 | \begin{Answer} 8 | \Question The following function calculates the average: 9 | \lstinputlisting[caption=Average function in Go,linerange={3,14}]{ex-functions/src/ave.go} 10 | \showremarks 11 | \end{Answer} 12 | -------------------------------------------------------------------------------- /ex-functions/ex-average.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Average},difficulty=0] 2 | \label{ex:average} 3 | \Question\label{ex:average q1} Write a function that calculates 4 | the average of a \type{float64} slice. 5 | \end{Exercise} 6 | 7 | \begin{Answer} 8 | \Question The following function calculates the average: 9 | \lstinputlisting[caption=Average function in Go,linerange={3,14}]{ex-functions/src/ave.go} 10 | \showremarks 11 | \end{Answer} 12 | -------------------------------------------------------------------------------- /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-beyond/ex-map.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Map function with interfaces},difficulty=2] 2 | \label{ex:map function interfaces} 3 | \Question 4 | Use the answer from exercise Q\ref{ex:map function}, but now 5 | make it generic using interfaces. Make it at least work for 6 | ints and strings. 7 | \end{Exercise} 8 | 9 | \begin{Answer} 10 | \Question 11 | \lstinputlisting[label=src:map,caption=A generic map function in 12 | Go]{ex-beyond/src/map.go} 13 | \end{Answer} 14 | 15 | 16 | -------------------------------------------------------------------------------- /fig/scope2.tex: -------------------------------------------------------------------------------- 1 | \begin{lstlisting}[caption=Global scope,label=src:scope2] 2 | |\begin{tikzpicture}[overlay] 3 | \draw [->,thick] (2.9,-5.00) arc (-60:90:2.00cm); 4 | \draw [->,thick] (3.5,-7.00) arc (-60:90:3.15cm); 5 | \end{tikzpicture}| 6 | package main 7 | 8 | var a = 6 9 | 10 | func main() { 11 | p() 12 | q() 13 | p() 14 | } 15 | 16 | func p() { 17 | println(a) 18 | } 19 | 20 | func q() { 21 | a = 5|\coderemark{Assignment}| 22 | println(a) 23 | } 24 | \end{lstlisting} 25 | -------------------------------------------------------------------------------- /fig/scope1.tex: -------------------------------------------------------------------------------- 1 | \begin{lstlisting}[caption=Local scope,label=src:scope1] 2 | |\begin{tikzpicture}[overlay] 3 | \draw [->,thick] (3.1,-5.00) arc (-60:90:2.00cm); 4 | \draw [->,thick] (3.1,-7.00) arc (-60:90:0.20cm); 5 | \end{tikzpicture}| 6 | package main 7 | 8 | var a = 6 9 | 10 | func main() { 11 | p() 12 | q() 13 | p() 14 | } 15 | 16 | func p() { 17 | println(a) 18 | } 19 | 20 | func q() { 21 | a := 5 |\coderemark{Definition}| 22 | println(a) 23 | } 24 | \end{lstlisting} 25 | -------------------------------------------------------------------------------- /src/myeven.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import (|\longremark{Import the following packages;}| 4 | "even" |\longremark{The \emph{local} package \package{even} is imported here;}| 5 | "fmt" |\longremark{The official \package{fmt} package gets imported;}| 6 | ) 7 | 8 | func main() { 9 | i := 5 10 | fmt.Printf("Is %d even? %v\n", i, even.Even(i)) |\longremark{Use the function from the % 11 | \package{even} package. The syntax for accessing a function from a package is % 12 | \lstinline{.Function()}.}| 13 | } 14 | -------------------------------------------------------------------------------- /ex-beyond/ex-copy-array.ex: -------------------------------------------------------------------------------- 1 | ssuming slices of ints, you can do (not really tested): 2 | 3 | func concat(old1, old2 []int) []int { 4 | newslice := make([]int, len(old1) + len(old2)) 5 | copy(newslice, old1) 6 | copy(newslice[len(old1):], old2) 7 | return newslice 8 | } 9 | 10 | A fun little exercise might be to write 11 | 12 | func concat(slices ...[]int) []int 13 | 14 | That is, a function to concatenate efficiently an arbitrary number of slices, 15 | as opposed to just two. 16 | 17 | TODO, but nice exercise 18 | -------------------------------------------------------------------------------- /src/array-and-slices.2.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var array [100]int // Create array, index from 0 to 99 7 | slice := array[0:100] // Create slice, index from 0 to 99 8 | 9 | fmt.Printf("%d %d - %d %d\n", 10 | cap(array), len(array), cap(slice), len(slice)); 11 | 12 | slice[0] = 'a' 13 | slice[1] = 'a' 14 | slice[2] = 'a' 15 | slice[3] = 'a' 16 | slice[4] = 'a' 17 | slice[5] = '0' 18 | 19 | fmt.Printf("%d %d - %d %d\n", 20 | cap(array), len(array), cap(slice), len(slice)); 21 | } 22 | -------------------------------------------------------------------------------- /ex-functions/ex-for.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={For-loop II},difficulty=0] 2 | \label{ex:for-loop II} 3 | \Question Remember Q\ref{ex:for-loop} (see page \pageref{ex;for-loop}? 4 | We extend this a little and now ask you to put the body of the for loop 5 | the \key{fmt.Printf} - in a separate function. 6 | \end{Exercise} 7 | 8 | \begin{Answer} 9 | \begin{minipage}{\textwidth} 10 | \lstinputlisting[label=src:for-func,caption=Loop calls function]{ex-functions/src/for-func.go} 11 | \end{minipage} 12 | 13 | The presented program should be self explanatory. 14 | \end{Answer} 15 | -------------------------------------------------------------------------------- /ex-functions/ex-vararg.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Var args},difficulty=1] 2 | \label{ex:varargs} 3 | \Question\label{ex:varargs q1} 4 | Write a function that takes a variable number of ints and prints 5 | each integer on a separate line 6 | \end{Exercise} 7 | 8 | \begin{Answer} 9 | \Question 10 | For this we need the \lstinline{...}-syntax to signal we define a 11 | function that takes an arbitrary number of arguments. 12 | 13 | \lstinputlisting[label=src:varargs,caption=A function with variable number of arguments]{ex-functions/src/var-arg.go} 14 | 15 | \end{Answer} 16 | -------------------------------------------------------------------------------- /src/file.go: -------------------------------------------------------------------------------- 1 | package main 2 | import "os" 3 | 4 | func main() { 5 | buf := make([]byte, 1024) 6 | f, _ := os.Open("/etc/passwd") |\longremark{Open the file, \func{os.Open} returns a \type{*os.File}, which implements \type{io.Reader} and \type{io.Writer};}| 7 | defer f.Close() |\longremark{Make sure we close \var{f} again;}| 8 | for { 9 | n, _ := f.Read(buf) |\longremark{Read up to 1024 bytes at the time;}| 10 | if n == 0 { break } |\longremark{We have reached the end of the file;}| 11 | os.Stdout.Write(buf[:n]) |\longremark{Write the contents to \type{os.Stdout}}| 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ex-functions/src/ave.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func average(xs []float64) (avg float64) { |\longremark{We use a named return parameter;}| 4 | sum := 0.0 5 | switch len(xs) { 6 | case 0: |\longremark{If the length is zero, we return 0;}| 7 | avg = 0 8 | default: |\longremark{Otherwise we calculate the average;}| 9 | for _, v := range xs { 10 | sum += v 11 | } 12 | avg = sum / float64(len(xs)) |\longremark{We have to % 13 | convert the value to a \key{float64} to make the division work;}| 14 | } 15 | return |\longremark{We have an avarage, return it.}| 16 | } 17 | -------------------------------------------------------------------------------- /ex-communication/src/proc.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -l 2 | my (%child, $pid, $parent); 3 | my @ps=`ps -e -opid,ppid,comm`; |\coderemark{capture the output from `ps`}| 4 | foreach (@ps[1..$#ps]) { |\coderemark{discard the header line}| 5 | ($pid, $parent, undef) = split; |\coderemark{split the line, discard 'comm'}| 6 | push @{$child{$parent}}, $pid; |\coderemark{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-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-communication/src/echo.go: -------------------------------------------------------------------------------- 1 | package main 2 | import ( "net"; "fmt";"bufio" ) 3 | 4 | func main() { 5 | l, err := net.Listen("tcp", "127.0.0.1:8053") 6 | if err != nil { 7 | fmt.Printf("Failure to listen: %s\n", err.Error()) 8 | } 9 | for { 10 | if c, err := l.Accept(); err == nil { Echo(c) } 11 | } 12 | } 13 | 14 | func Echo(c net.Conn) { 15 | defer c.Close() 16 | line, err := bufio.NewReader(c).ReadString('\n') 17 | if err != nil { 18 | fmt.Printf("Failure to read: %s\n", err.Error()) 19 | return 20 | } 21 | _, err = c.Write([]byte(line)) 22 | if err != nil { 23 | fmt.Printf("Failure to write: %s\n", err.Error()) 24 | return 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /ex-functions/ex-fib.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Fibonacci},difficulty=1] 2 | \label{ex:fibonaci} 3 | \Question\label{ex:fibonaci q1} 4 | 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} + 6 | x_{n-2}\quad\forall n > 2 $. 7 | 8 | Write a function that takes an \type{int} value and gives 9 | that many terms of the Fibonacci sequence. 10 | 11 | \end{Exercise} 12 | 13 | \begin{Answer} 14 | \Question 15 | The following program calculates Fibonacci numbers: 16 | \lstinputlisting[label=src:fib,caption=Fibonacci function in Go]{ex-functions/src/fib.go} 17 | 18 | \showremarks 19 | \end{Answer} 20 | -------------------------------------------------------------------------------- /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-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/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-functions/ex-order.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Integer ordering},difficulty=0] 2 | \label{ex:ordering function} 3 | \Question Write a function that returns its (two) parameters in the right, 4 | numerical (ascending) order:\newline 5 | \lstinline{f(7,2)} $\rightarrow$ \lstinline{2,7}\newline 6 | \lstinline{f(2,7)} $\rightarrow$ \lstinline{2,7}\newline 7 | \end{Exercise} 8 | 9 | \begin{Answer} 10 | \Question 11 | Here we can use the multiple return values (section ``\titleref{sec:multiple return}'') 12 | from Go: 13 | \begin{lstlisting} 14 | func order(a, b int) (int, int) { 15 | if a > b { 16 | return b,a 17 | } 18 | return a,b 19 | } 20 | \end{lstlisting} 21 | 22 | \end{Answer} 23 | -------------------------------------------------------------------------------- /ex-communication/ex-quine.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Quine},difficulty=2] 2 | A \emph{Quine} is a program that prints itself. 3 | \label{ex:quine} 4 | \Question\label{ex:quine q1} Write a Quine in Go. 5 | \end{Exercise} 6 | 7 | \begin{Answer} 8 | \begin{lbar} 9 | This solution is from Russ Cox. It was posted to 10 | the Go Nuts mailing list. 11 | \end{lbar} 12 | \Question 13 | \begin{lstlisting}[caption=A Go quine] 14 | /* Go quine */ 15 | package main 16 | import "fmt" 17 | func main() { 18 | fmt.Printf("%s%c%s%c\n", q, 0x60, q, 0x60) 19 | } 20 | var q = `/* Go quine */ 21 | package main 22 | import "fmt" 23 | func main() { 24 | fmt.Printf("%s%c%s%c\n", q, 0x60, q, 0x60) 25 | } 26 | var q = ` 27 | \end{lstlisting} 28 | \end{Answer} 29 | -------------------------------------------------------------------------------- /ex-basics/ex-fizzbuzz.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={FizzBuzz},difficulty=0] 2 | \label{ex:fizzbuzz} 3 | \Question \label{ex:fizzbuzz q1} Solve this problem, called 4 | the Fizz-Buzz \cite{fizzbuzz} problem: 5 | \begin{quote} 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 the multiples of 8 | five print ``Buzz''. For numbers which are multiples of both three and 9 | five print ``FizzBuzz''. 10 | \end{quote} 11 | \end{Exercise} 12 | 13 | \begin{Answer} 14 | \Question A possible 15 | solution to this simple problem is the following program. 16 | \lstinputlisting[label=src:fizzbuzz,caption=Fizz-Buzz]{ex-basics/src/fizzbuzz.go} 17 | \showremarks 18 | \end{Answer} 19 | -------------------------------------------------------------------------------- /ex-functions/src/fib.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func fibonacci(value int) []int { 6 | x := make([]int, value) |\longremark{We create an \key{array} to hold the integers up to the value given in the function call;}| 7 | x[0], x[1] = 1, 1 |\longremark{Starting point of the Fibonacci calculation;}| 8 | for n := 2; n < value; n++ { 9 | x[n] = x[n-1] + x[n-2] |\longremark{$x_n = x_{n-1} + x_{n-2}$;}| 10 | } 11 | return x |\longremark{Return the \emph{entire} array;}| 12 | } 13 | 14 | func main() { 15 | for _, term := range fibonacci(10) { |\longremark{Using the \key{range} keyword we ``walk'' the numbers returned by the Fibonacci function. Here up to 10. And we print them.}| 16 | fmt.Printf("%v ", term) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ex-communication/ex-wordcount.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Word and letter count},difficulty=0] 2 | \label{ex:wc} 3 | \Question\label{ex:wc q1} Write a small program that reads text from 4 | standard input and performs the following actions: 5 | \begin{enumerate} 6 | \item{Count the number of characters (including spaces);} 7 | \item{Count the number of words;} 8 | \item{Count the numbers of lines.} 9 | \end{enumerate} 10 | In other words implement \prog{wc(1)} (check you local manual page), 11 | however you only have to read from standard input. 12 | \end{Exercise} 13 | 14 | \begin{Answer} 15 | \Question The following program is an implementation of \prog{wc(1)}. 16 | \lstinputlisting[caption=wc(1) in Go]{ex-communication/src/wc.go} 17 | \showremarks 18 | \end{Answer} 19 | -------------------------------------------------------------------------------- /tab/keywords.tex: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | %% %% 3 | %% This is a LaTeX2e table fragment exported from Gnumeric. %% 4 | %% %% 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | \begin{tabular}{lllll} 7 | \key{break} &\key{default} &\key{func} &\key{interface} &\key{select}\\ 8 | \key{case} &\key{defer} &\key{go} &\key{map} &\key{struct}\\ 9 | \key{chan} &\key{else} &\key{goto} &\key{package} &\key{switch}\\ 10 | \key{const} &\key{fallthrough} &\key{if} &\key{range} &\key{type}\\ 11 | \key{continue} &\key{for} &\key{import} &\key{return} &\key{var}\\ 12 | \end{tabular} 13 | -------------------------------------------------------------------------------- /todo.tex: -------------------------------------------------------------------------------- 1 | \section{To do} 2 | 3 | \begin{itemize} 4 | Run gotest -test.bench=Bench -test.cpuprofile=cpuprof 5 | 6 | \$(GC) y.go 7 | \$(LD) -o units y.\$O 8 | 9 | This will generate a cpu profile. You can examine it with gopprof: 10 | 11 | gopprof 8.out cpuprof 12 | 13 | http://blog.golang.org/2011/06/profiling-go-programs.html 14 | 15 | - Evan 16 | 17 | \item 18 | Embedding/composition 19 | \item 20 | Style! Make it a pleasant read 21 | \item 22 | In chapter 3 (Functions) add exercise for GCD and LCM 23 | \item 24 | Conversion 25 | \end{itemize} 26 | Exercise ideas 27 | \begin{itemize} 28 | \item 29 | equality for arrays/maps 30 | \item 31 | get system time and convert it in different formats: 32 | \item 33 | Extract uppercase words from a file 34 | \end{itemize} 35 | -------------------------------------------------------------------------------- /ex-communication/src/wc.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | "bufio" 7 | "strings" 8 | ) 9 | 10 | func main() { 11 | var chars, words, lines int 12 | r := bufio.NewReader(os.Stdin) |\longremark{Start a new reader that reads from standard input;}| 13 | for { 14 | switch s, ok := r.ReadString('\n'); true { |\longremark{Read a line from the input;}| 15 | case ok != nil: |\longremark{If we received an error, we assume it was because % 16 | of a EOF. So we print the current values;}| 17 | fmt.Printf("%d %d %d\n", chars, words, lines); 18 | return 19 | default: |\longremark{Otherwise we count the charaters, words and increment the % 20 | lines.}| 21 | chars += len(s) 22 | words += len(strings.Fields(s)) 23 | lines++ 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/buffile.go: -------------------------------------------------------------------------------- 1 | package main 2 | import ( "os"; "bufio") 3 | 4 | func main() { 5 | buf := make([]byte, 1024) 6 | f, _ := os.Open("/etc/passwd") |\longremark{Open the file;}| 7 | defer f.Close() 8 | r := bufio.NewReader(f) |\longremark{Turn \var{f} into a buffered \func{Reader}. % 9 | \func{NewReader} expects an \type{io.Reader}, so you % 10 | might think this will fail. But it does not. % 11 | \emph{Anything} that has such a \func{Read()} function implements this % 12 | interface. And from listing \ref{src:read} we can see % 13 | that \type{*os.File} indeed does so;}| 14 | w := bufio.NewWriter(os.Stdout) 15 | defer w.Flush() 16 | for { 17 | n, _ := r.Read(buf) |\longremark{Read from the Reader and write to the Writer, and thus % 18 | print the file to the screen.}| 19 | if n == 0 { break } 20 | w.Write(buf[0:n]) 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /ex-interfaces/ex-pointers-and-reflect.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Pointers and reflection},difficulty=1] 2 | \label{ex:pointers and reflection} 3 | \Question 4 | One of the last paragraphs in section ``\titleref{sec:introspection and reflection}'' 5 | on page \pageref{sec:introspection and reflection}, has 6 | the following words: 7 | \begin{quote} 8 | The code on the right works OK and sets the member \var{Name} 9 | to ``Albert Einstein''. Of course this only works when you call \func{Set()} 10 | with a pointer argument. 11 | \end{quote} 12 | Why is this the case? 13 | \end{Exercise} 14 | 15 | \begin{Answer} 16 | \Question 17 | When called with a non-pointer argument the variable is a copy (call-by-value). So you 18 | are doing the reflection voodoo on a copy. And thus you are \emph{not} 19 | changing the original value, but only this copy. 20 | \end{Answer} 21 | -------------------------------------------------------------------------------- /ex-beyond/ex-pointer-arith.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Pointer arithmetic},difficulty=1] 2 | \label{ex:pointer arithmetic} 3 | \Question 4 | In the main text on page \pageref{main:pointer arithmetic} 5 | there is the following text: 6 | 7 | \begin{quote} 8 | \ldots there is no pointer arithmetic, so if you write: 9 | \lstinline{*p++}, it is interpreted as \lstinline{(*p)++}: first 10 | dereference and then increment the value. 11 | \end{quote} 12 | When you increment a value like this, for which types will it work? 13 | \Question Why doesn't it work for all types? 14 | 15 | \end{Exercise} 16 | 17 | \begin{Answer} 18 | \Question This will only work for pointers to point to numerical (\type{int, uint}, etc) values. 19 | \Question The \func{++} is only defined for numerical types and because there 20 | is no operator overloading in Go it fails (compilation error) otherwise. 21 | \end{Answer} 22 | -------------------------------------------------------------------------------- /about-miekg.tex: -------------------------------------------------------------------------------- 1 | \begin{wrapfigure}{r}{0.3\textwidth} 2 | \begin{center} 3 | \includegraphics[width=3cm]{fig/avatar-miekg-300x300} 4 | \end{center} 5 | \end{wrapfigure} 6 | Miek Gieben has a master's degree in Computer Science from the Radboud University Nijmegen (Netherlands). 7 | He is involved in the development and now the deployment of the DNSSEC protocol -- 8 | the successor of the DNS and as such co-authored \cite{RFC4641}. 9 | 10 | After playing with the language Erlang, Go was the first concurrent language 11 | that actually stuck with him. 12 | 13 | He fills his spare time with coding in, and writing of Go. He is the maintainer 14 | of the Go DNS library: \url{https://github.com/miekg/dns}. 15 | He maintains a personal blog on \url{http://www.miek.nl} and tweets 16 | under the name \texttt{@miekg}. The postings and tweets may sometimes 17 | actually have to do something with Go. 18 | -------------------------------------------------------------------------------- /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 { 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 | -------------------------------------------------------------------------------- /src/stack.go: -------------------------------------------------------------------------------- 1 | // This package implementes a simple stack 2 | package stack 3 | 4 | import ( 5 | "strconv" 6 | ) 7 | 8 | // Stack hold 10 integer element and has an index 9 | type Stack struct { 10 | i int 11 | data [10]int 12 | } 13 | 14 | // Push an element on the stack and increment the index 15 | func (s *Stack) Push(k int) { 16 | if s.i+1 > 9 { 17 | return 18 | } 19 | s.data[s.i] = k 20 | s.i++ 21 | } 22 | 23 | // Pop an element from the stack and decrement the index 24 | func (s *Stack) Pop() (ret int) { 25 | if s.i-1 < 0 { 26 | return 0 27 | } 28 | ret = s.data[s.i] 29 | s.i-- 30 | return ret 31 | } 32 | 33 | // String returns a string representation of the stack 34 | func (s *Stack) String() string { 35 | var str string 36 | for i := 0; i < s.i; i++ { 37 | str = str + "[" + strconv.Itoa(i) + ":" + 38 | strconv.Itoa(s.data[i]) + "]" 39 | } 40 | return str 41 | } 42 | -------------------------------------------------------------------------------- /ex-basics/ex-average-no-func.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Average},difficulty=1] 2 | \label{ex:average no func} 3 | \Question\label{ex:average no func q1} Write code 4 | to calculate the average of a \type{float64} slice. In 5 | a later exercise (Q\ref{ex:average} you will make it into 6 | a function. 7 | \end{Exercise} 8 | 9 | \begin{Answer} 10 | \Question The following code calculates the average. 11 | \begin{lstlisting} 12 | sum := 0.0 13 | switch len(xs) { 14 | case 0: |\longremark{If the length is zero, we return 0;}| 15 | avg = 0 16 | default: |\longremark{Otherwise we calculate the average;}| 17 | for _, v := range xs { 18 | sum += v 19 | } 20 | avg = sum / float64(len(xs)) |\longremark{We have to convert the value to a % 21 | \key{float64} to make the division work.}| 22 | } 23 | \end{lstlisting} 24 | \showremarks 25 | \end{Answer} 26 | -------------------------------------------------------------------------------- /ex-communication/ex-uniq.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Uniq},difficulty=0] 2 | \label{ex:Uniq} 3 | \Question\label{ex:Uniq q1} Write a Go program that mimics the function 4 | of the Unix \prog{uniq} command. This program should work as follows, 5 | given a list with the following items: 6 | 7 | \begin{display} 8 | 'a' 'b' 'a' 'a' 'a' 'c' 'd' 'e' 'f' 'g' 9 | \end{display} 10 | 11 | it should print only those item which don't have the same successor: 12 | 13 | \begin{display} 14 | 'a' 'b' 'a' 'c' 'd' 'e' 'f' 15 | \end{display} 16 | \exdisfix 17 | Listing \ref{src:uniq} is a Perl implementation of the algorithm. 18 | \lstinputlisting[label=src:uniq,caption=uniq(1) in Perl,language=Perl]{ex-communication/src/uniq.pl} 19 | 20 | \end{Exercise} 21 | 22 | \begin{Answer} 23 | \Question The following is a uniq implementation in Go. 24 | \lstinputlisting[caption=uniq(1) in Go]{ex-communication/src/uniq.go} 25 | \end{Answer} 26 | -------------------------------------------------------------------------------- /tab/conversion.tex: -------------------------------------------------------------------------------- 1 | \begin{tabular}{llllllll} 2 | \textbf{From} & \verb|b []byte|& \verb|i []int| & \verb|r []rune| & \verb|s string| & \verb|f flt32| & \verb|i int| \\ \cmidrule(r){1-7} 3 | \textbf{To} & & & & & & \\ \cmidrule(r){1-1} 4 | \verb|[]byte| & $\texttimes$ & & & \verb|[]byte(s)| & & \\ 5 | \verb|[]int| & & $\texttimes$ & & \verb|[]int(s)| & & \\ 6 | \verb|[]rune| & & & $\texttimes$ & \verb|[]rune(s)| & & \\ 7 | \verb|string| &\verb|string(b)| &\verb|string(i)| & \verb|string(r)| & $\texttimes$ & & \\ 8 | \verb|ftl32| & & & & & $\texttimes$ & \verb|flt32(i)|\\ 9 | \verb|int| & & & & & \verb|int(f)| & $\texttimes$ \\ 10 | %%\bottomrule 11 | \end{tabular} 12 | -------------------------------------------------------------------------------- /ex-channels/ex-fib.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Fibonacci II},difficulty=2] 2 | \label{ex:fibonaci II} 3 | \Question\label{ex:fibonaci II q1} 4 | This is the same exercise as the one given page \pageref{ex:fibonaci} 5 | in exercise \ref{ex:fibonaci}. For completeness the complete question: 6 | 7 | \begin{quote} 8 | The Fibonacci sequence starts as follows: $1, 1, 2, 3, 5, 8, 13, \ldots$ 9 | Or in mathematical terms: $ x_1 = 1; x_2 = 1; x_n = x_{n-1} + 10 | x_{n-2}\quad\forall n > 2 $. 11 | 12 | Write a function that takes an \type{int} value and gives 13 | that many terms of the Fibonacci sequence. 14 | \end{quote} 15 | \emph{But} now the twist: You must use channels. 16 | 17 | \end{Exercise} 18 | 19 | \begin{Answer} 20 | \Question 21 | The following program calculates the Fibonacci numbers using channels. 22 | \lstinputlisting[label=src:fib II,caption=A Fibonacci function in Go]{ex-channels/src/fib.go} 23 | \end{Answer} 24 | 25 | 26 | -------------------------------------------------------------------------------- /ex-basics/src/fizzbuzz.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | const ( 7 | FIZZ = 3 |\longremark{Define two constants to make the code more % 8 | readable. See section "\titleref{sec:constants}";}| 9 | BUZZ = 5 10 | ) 11 | var p bool |\longremark{Holds if we already printed something;}| 12 | for i := 1; i < 100; i++ { |\longremark{for-loop, see section "\titleref{sec:for}"};| 13 | p = false 14 | if i%FIZZ == 0 { |\longremark{If divisible by FIZZ, print "Fizz";}| 15 | fmt.Printf("Fizz") 16 | p = true 17 | } 18 | if i%BUZZ == 0 { |\longremark{And if divisble by BUZZ, print % 19 | "Buzz". Note that we have also taken care of the FizzBuzz case;}| 20 | fmt.Printf("Buzz") 21 | p = true 22 | } 23 | if !p { |\longremark{If neither FIZZ nor BUZZ printed, print the value;}| 24 | fmt.Printf("%v", i) 25 | } 26 | fmt.Println() |\longremark{Format each output on a new line.}| 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /fig/scope3.tex: -------------------------------------------------------------------------------- 1 | \begin{lstlisting}[caption=Scope and function literals,label=src:scope3,float] 2 | |\begin{tikzpicture}[overlay] 3 | \draw [->,thick] (2.8,-4.10) arc (-60:90:0.20cm); 4 | \draw [->,thick] (2.8,-2.00) arc (-60:90:0.20cm); 5 | \draw [->,thick] (2.4,-1.60) arc (-60:90:0.50cm); 6 | % 7 | \draw [->,thick] (4.4,-8.75) arc (-60:80:4.30cm); 8 | % function f() 9 | \draw [->,thick] (4.4,-5.85) arc (-60:90:0.30cm); 10 | \draw [->,thick] (4.4,-5.25) arc (-60:90:0.90cm); 11 | % 12 | \draw [->,thick] (3.2,-7.45) arc (-60:65:2.00cm); 13 | \end{tikzpicture}| 14 | package main 15 | var a int 16 | func main() { 17 | a = 5 18 | println(a) 19 | f() 20 | } 21 | func f() { 22 | a := 6 23 | println(a) 24 | g() 25 | x := func() { 26 | a = 7 27 | println(a) 28 | } 29 | x() 30 | g() 31 | println(a) 32 | } 33 | func g() { 34 | println(a) 35 | } 36 | \end{lstlisting} 37 | -------------------------------------------------------------------------------- /ex-basics/ex-doc.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Documentation},difficulty=1] 2 | \label{ex:doc} 3 | \Question 4 | Go's documentation can be read with the \prog{godoc} program, which is 5 | included the Go distribution. 6 | 7 | \prog{godoc hash} gives information about the \package{hash} package: 8 | \vskip\baselineskip 9 | \begin{display} 10 | \pr \user{godoc hash} 11 | PACKAGE 12 | 13 | package hash 14 | 15 | ... 16 | ... 17 | ... 18 | 19 | SUBDIRECTORIES 20 | 21 | adler32 22 | crc32 23 | crc64 24 | fnv 25 | 26 | \end{display} 27 | \vskip\baselineskip 28 | With which \prog{godoc} command can you read the documentation of \package{fnv} contained in 29 | \package{hash}? 30 | 31 | \end{Exercise} 32 | 33 | \begin{Answer} 34 | \Question 35 | The package \package{fnv} is in a \emph{subdirectory} of 36 | \package{hash}, so you will only need\quad \texttt{godoc hash/fnv}. 37 | 38 | All the built-in functions are also accesible by using \prog{godoc builtin}. 39 | \end{Answer} 40 | -------------------------------------------------------------------------------- /ex-communication/src/proc.go: -------------------------------------------------------------------------------- 1 | package main 2 | import ( "fmt"; "os/exec"; "sort"; "strconv"; "strings") 3 | 4 | func main() { 5 | ps := exec.Command("ps", "-e", "-opid,ppid,comm") 6 | output, _ := ps.Output() 7 | child := make(map[int][]int) 8 | for i, s := range strings.Split(string(output), "\n") { 9 | if i == 0 { continue } |\coderemark{kill first line}| 10 | if len(s) == 0 { continue } |\coderemark{kill last line}| 11 | f := strings.Fields(s) 12 | fpp, _ := strconv.Atoi(f[1]) |\coderemark{parent's pid}| 13 | fp, _ := strconv.Atoi(f[0]) |\coderemark{child's pid}| 14 | child[fpp] = append(child[fpp], fp) 15 | } 16 | schild := make([]int, len(child)) 17 | i := 0 18 | for k, _ := range child { schild[i] = k; i++ } 19 | sort.Ints(schild) 20 | for _, ppid := range schild { 21 | fmt.Printf("Pid %d has %d child", ppid, len(child[ppid])) 22 | if len(child[ppid]) == 1 { 23 | fmt.Printf(": %v\n", child[ppid]) 24 | continue 25 | } 26 | fmt.Printf("ren: %v\n", child[ppid]) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ex-beyond/ex-doubly-linked-list.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Linked List},difficulty=1] 2 | \label{ex:linkedlist} 3 | \Question 4 | \label{ex:linkedlist q1} 5 | Make use of the package \package{container/list} to create 6 | a (doubly) linked list. Push the values 1, 2 and 4 to the list and then 7 | print it. 8 | 9 | \Question 10 | Create your own linked list implementation. And perform the same actions 11 | as in question \ref{ex:linkedlist q1} 12 | \end{Exercise} 13 | 14 | \begin{Answer} 15 | \Question The following is the implementation of a program using doubly 16 | linked lists from \package{container/list}. 17 | \lstinputlisting[label=src:doubly-linked-list-container,caption=Doubly linked list using \package{container/list}]{ex-beyond/src/doubly-linked-list-container.go} 18 | 19 | \Question The following is a program implementing a simple doubly 20 | linked list supporting \type{int} values. 21 | \lstinputlisting[label=src:doubly-linked-list,caption=Doubly linked list]{ex-beyond/src/doubly-linked-list.go} 22 | \showremarks 23 | \end{Answer} 24 | -------------------------------------------------------------------------------- /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 | "strconv" 11 | ) 12 | 13 | func main() { 14 | flag.Parse() 15 | ln, err := net.Listen("tcp", ":79") 16 | if err != nil { 17 | panic(err) 18 | } 19 | for { 20 | conn, err := ln.Accept() 21 | if err != nil { 22 | continue 23 | } 24 | go handleConnection(conn) 25 | } 26 | } 27 | 28 | func handleConnection(conn net.Conn) { 29 | defer conn.Close() 30 | reader := bufio.NewReader(conn) 31 | usr, _, _ := reader.ReadLine() 32 | 33 | if info, err := getUserInfo(string(usr)); err != nil { 34 | conn.Write([]byte(err.Error())) 35 | } else { 36 | conn.Write(info) 37 | } 38 | } 39 | 40 | func getUserInfo(usr string) ([]byte, error) { 41 | u, e := user.Lookup(usr) 42 | if e != nil { 43 | return nil, e 44 | } 45 | data, err := ioutil.ReadFile(u.HomeDir + ".plan") 46 | if err != nil { 47 | return data, errors.New("User doesn't have a .plan file!\n") 48 | } 49 | return data, nil 50 | } 51 | -------------------------------------------------------------------------------- /coderemarks.sty: -------------------------------------------------------------------------------- 1 | \ProvidesPackage{coderemarks} 2 | \RequirePackage{tikz} 3 | %% Code Remarks -- Miek Gieben 4 | %% define 2 commands 5 | %% \longremark[1] where you can say something about the code 6 | %% \showremarks - displays all remarks in a list after the code 7 | 8 | \newcounter{coderemarks} 9 | \setcounter{coderemarks}{0} 10 | \newcounter{codevar} 11 | \setcounter{codevar}{0} 12 | % 13 | \newcommand{\gocircle}[1]{% 14 | \tikz\node[text=white,font=\sffamily\bfseries,minimum size=3mm,inner sep=0mm,draw,circle,fill=black]{\small #1};} 15 | % 16 | \newcommand{\longremark}[1]{% 17 | \gocircle{\arabic{coderemarks}}% 18 | \global \expandafter\def \csname codebox\the\value{coderemarks}\endcsname{#1}% 19 | \stepcounter{coderemarks}} 20 | % 21 | \newcommand{\showremarks}{% 22 | \begin{list}{\gocircle{\arabic{codevar}}} % 23 | {} % 24 | \whiledo{\value{codevar} < \value{coderemarks}}{ % 25 | \item \expandafter\csname codebox\the\value{codevar}\endcsname % 26 | \stepcounter{codevar}} % 27 | \end{list} % 28 | \setcounter{coderemarks}{0}% 29 | \setcounter{codevar}{0}% 30 | } 31 | -------------------------------------------------------------------------------- /ex-communication/ex-finger.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Finger daemon},difficulty=1] 2 | \label{ex:finger} 3 | \Question 4 | Write a finger daemon that works with the finger(1) command. 5 | 6 | From the Debian package description: 7 | \begin{quote} 8 | Fingerd is a simple daemon based on RFC 1196 \cite{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 | \end{quote} 13 | 14 | Stick to the basics and only support a username argument. If the user has a \file{.plan} file 15 | show the contents of that file. So your program needs to be able to figure out: 16 | \begin{itemize} 17 | \item Does the user exist? 18 | \item If the user exists, show the contents of the \file{.plan} file. 19 | \end{itemize} 20 | \end{Exercise} 21 | 22 | \begin{Answer} 23 | \begin{lbar} 24 | This solution is from Fabian Becker. 25 | \end{lbar} 26 | \Question 27 | \lstinputlisting[label=src:fingerd,caption=A finger daemon]{ex-communication/src/finger.go} 28 | \end{Answer} 29 | -------------------------------------------------------------------------------- /go-contributors.tex: -------------------------------------------------------------------------------- 1 | \emph{Adam J. Gray}, 2 | \emph{Alex Sychev}, 3 | \emph{Alexey Chernenkov}, 4 | \emph{Andrea Spadaccini}, 5 | \emph{Andrey Mirtchovski}, 6 | \emph{Anthony Magro}, 7 | \emph{Babu Sreekanth}, 8 | \emph{Ben Bullock}, 9 | \emph{Bob Cunningham}, 10 | \emph{Brian Fallik}, 11 | \emph{Cecil New}, 12 | \emph{Damian Gryski}, 13 | \emph{Dan Kortschak}, 14 | \emph{David Otton}, 15 | \emph{Fabian Becker}, 16 | \emph{Filip Zaludek}, 17 | \emph{Hadi Amiri}, 18 | \emph{Haiping Fan}, 19 | \emph{Jaap Akkerhuis}, 20 | \emph{JC van Winkel}, 21 | \emph{Jeroen Bulten}, 22 | \emph{Jinpu Hu}, 23 | \emph{John Shahid}, 24 | \emph{Jonathan Kans}, 25 | \emph{Joshua Stein}, 26 | \emph{Makoto Inoue}, 27 | \emph{Mayuresh Kathe}, 28 | \emph{``mem''}, 29 | \emph{Michael Stapelberg}, 30 | \emph{Olexandr Shalakhin}, 31 | \emph{Paulo Pinto}, 32 | \emph{Peter Kleiweg}, 33 | \emph{Philipp Schmidt}, 34 | \emph{Robert Johnson}, 35 | \emph{Russel Winder}, 36 | \emph{Sonia Keys}, 37 | \emph{Stefan Schroeder}, 38 | \emph{Thomas Kapplet}, 39 | \emph{T.J. Yang}, 40 | \emph{``Cobold''}, 41 | \emph{``Simoc''}, 42 | \emph{``Uriel''}$\dagger$, 43 | \emph{Xing Xing}. 44 | -------------------------------------------------------------------------------- /ex-functions/ex-scope.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Scope},difficulty=1] 2 | \label{ex:scope} 3 | \Question\label{ex:scope q1} What is wrong with the following program? 4 | 5 | \begin{lstlisting}[numbers=right] 6 | package main 7 | 8 | import "fmt" 9 | 10 | func main() { 11 | for i := 0; i < 10; i++ { 12 | fmt.Printf("%v\n", i) 13 | } 14 | fmt.Printf("%v\n", i) 15 | } 16 | \end{lstlisting} 17 | 18 | \end{Exercise} 19 | 20 | \begin{Answer} 21 | \Question 22 | The program does not even compile, because \var{i} on line 9 is 23 | not defined: \var{i} is only defined within the \key{for}-loop. To fix 24 | this the function \func{main()} should become: 25 | \begin{lstlisting}[numbers=none] 26 | func main() { 27 | var i int 28 | for i = 0; i < 10; i++ { 29 | fmt.Printf("%v\n", i) 30 | } 31 | fmt.Printf("%v\n", i) 32 | } 33 | \end{lstlisting} 34 | Now \var{i} is defined outside the \key{for}-loop and still visible 35 | afterwards. This code will print the numbers 0 through 10. 36 | \end{Answer} 37 | -------------------------------------------------------------------------------- /ex-beyond/ex-cat.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Cat},difficulty=1] 2 | \label{ex:cat} 3 | \Question \label{ex:cat q1} Write a program which mimics the Unix program 4 | \prog{cat}. For those who don't know this program, the following 5 | invocation displays the contents of the file \dir{blah}: 6 | \begin{display} 7 | \pr cat blah 8 | \end{display} 9 | 10 | \Question Make it support the \-n flag, where each line is 11 | numbered. 12 | 13 | \Question The solution to the above question given in \ref{q:cat} contains a 14 | bug. Can you spot and fix it? 15 | \end{Exercise} 16 | 17 | \begin{Answer} 18 | \Question The following is implemention of \prog{cat} which also 19 | \label{q:cat} 20 | supports a \-n flag to number each line. 21 | \lstinputlisting[label=src:cat,caption=A cat program]{ex-beyond/src/cat.go} 22 | \showremarks 23 | 24 | \Question 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 | \lstinputlisting[label=src:cat2,caption=A better cat program]{ex-beyond/src/cat2.go} 29 | \end{Answer} 30 | -------------------------------------------------------------------------------- /ex-communication/ex-echo.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Echo server},difficulty=1] 2 | \label{ex:echo} 3 | \Question\label{ex:echo q1} 4 | Write a simple echo server. Make it listen to TCP port number 8053 on localhost. It should 5 | be able to read a line (up to the newline), echo back that line and then close the connection. 6 | 7 | \Question\label{ex:echo q2} 8 | Make the server concurrent so that every request is taken care of in a separate 9 | goroutine. 10 | 11 | \end{Exercise} 12 | 13 | \begin{Answer} 14 | \Question 15 | A simple echo server might be: 16 | \lstinputlisting[caption=A simple echo server]{ex-communication/src/echo.go} 17 | 18 | When started you should see the following: 19 | \vskip\baselineskip 20 | \begin{display} 21 | \pr \user{nc 127.0.0.1 8053} 22 | \user{Go is *awesome*} 23 | Go is *awesome* 24 | \end{display} 25 | 26 | \Question 27 | To make the connection handling concurrent we \emph{only need to change one line} in our 28 | echo server, the line: 29 | \begin{lstlisting} 30 | if c, err := l.Accept(); err == nil { Echo(c) } 31 | \end{lstlisting} 32 | becomes: 33 | \begin{lstlisting} 34 | if c, err := l.Accept(); err == nil { go Echo(c) } 35 | \end{lstlisting} 36 | \end{Answer} 37 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: once spell compilecheck fmtcheck 2 | 3 | all: go.pdf 4 | 5 | go.pdf: go-*.tex ex-*/*.tex src/*.go tab/*.tex fig/*.tex blocksbook.cls go.bib .fig .tab about-*.tex 6 | rm -f go.tex && ln -s go_a4.tex go.tex 7 | xelatex go.tex && bibtex go && makeindex go \ 8 | && xelatex go.tex && xelatex go.tex 9 | 10 | .fig: fig/*.svg 11 | ( cd fig; make all ) 12 | touch .fig 13 | 14 | .tab: 15 | ( cd tab; make all ) 16 | touch .tab 17 | 18 | clean: 19 | rm -f go.lol go.aux *.log map.log go.pdf go.bbl go.blg go.toc go.ind go.lot go.lof go.loe 20 | rm -f go.ilg go.idx go.lgpl missfont.log doc_data.txt go.ex .fig .tab 21 | rm -f go.code 22 | 23 | distclean: clean 24 | ( cd fig; make clean ) 25 | ( cd tab; make clean ) 26 | ( cd src; make clean ) 27 | 28 | spell: 29 | for i in *.tex ex-*/*.tex; do aspell check $$i; done 30 | once: 31 | xelatex go.tex 32 | 33 | compilecheck: 34 | @bin/go-lstinputlisting.pl ~/git/gobook *.tex 35 | @bin/go-lstinputlisting.pl ~/git/gobook ex-*/*.tex 36 | @bin/go-lstinputlisting.pl ~/git/gobook fig/*.tex 37 | @rm -f *.6 *.8 38 | 39 | fmtcheck: 40 | @bin/go-lstlisting.pl *.tex 41 | @bin/go-lstlisting.pl ex-*/*.tex 42 | @bin/go-lstlisting.pl fig/*.tex 43 | -------------------------------------------------------------------------------- /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-functions/ex-map.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Map function},difficulty=1] 2 | \label{ex:map function} 3 | A \func{map()}-function is a function that takes 4 | a function and a list. The function is applied to 5 | each member in the list and a new list containing 6 | these calculated values is returned. 7 | Thus: 8 | $$ \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)) $$ 9 | \Question \label{ex:map function q1} Write a simple 10 | \func{map()}-function in Go. It is sufficient 11 | for this function only to work for ints. 12 | \Question \label{ex:map function q2} Expand your code to also work on a list of strings. 13 | 14 | \end{Exercise} 15 | 16 | \begin{Answer} 17 | 18 | \Question 19 | \begin{lstlisting}[caption=A Map function] 20 | func Map(f func(int) int, l []int) []int { 21 | j := make([]int, len(l)) 22 | for k, v := range l { 23 | j[k] = f(v) 24 | } 25 | return j 26 | } 27 | 28 | func main() { 29 | m := []int{1, 3, 4} 30 | f := func(i int) int { 31 | return i * i 32 | } 33 | fmt.Printf("%v", (Map(f, m))) 34 | } 35 | \end{lstlisting} 36 | 37 | \Question Answer to question but now with strings 38 | \end{Answer} 39 | 40 | 41 | -------------------------------------------------------------------------------- /ex-interfaces/ex-interfaces.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Interfaces and compilation},difficulty=1] 2 | \Question 3 | The code in listing \ref{src:interface fail} on page 4 | \pageref{src:interface fail} compiles OK --- as stated 5 | in the text. But when you run it you'll get a runtime error, so 6 | something \emph{is} wrong. Why does the code compile cleanly then? 7 | \end{Exercise} 8 | 9 | \begin{Answer} 10 | \Question 11 | The code compiles because an integer type implements the empty interface 12 | and that is the check that happens at compile time. 13 | 14 | A proper way to fix this is to test if such an empty interface can 15 | be converted and, if so, call the appropriate method. The Go code 16 | that defines the function \func{g} in listing \ref{src:interface empty} 17 | -- repeated here: 18 | \begin{lstlisting} 19 | func g(any interface{}) int { return any.(I).Get() } 20 | \end{lstlisting} 21 | 22 | \noindent{}Should be changed to become: 23 | \begin{lstlisting} 24 | func g(any interface{}) int { 25 | if v, ok := any.(I); ok { |\coderemark{Check if any can be converted}| 26 | return v.Get() |\coderemark{If so invoke Get()}| 27 | } 28 | return -1 |\coderemark{Just so we return anything}| 29 | } 30 | \end{lstlisting} 31 | If \func{g()} is called now there are no run-time errors anymore. The 32 | idiom used is called ``comma ok'' in Go. 33 | \end{Answer} 34 | -------------------------------------------------------------------------------- /go-colophon.tex: -------------------------------------------------------------------------------- 1 | \noindent{}This work was created with \LaTeX. The main text is set in 2 | the Google Droid fonts. All typewriter text is typeset in DejaVu Mono. 3 | 4 | \section{Contributors} 5 | The following people have helped to make this book what it is today. 6 | \begin{itemize} 7 | \item{Miek Gieben \qquad\url{}}; 8 | \item{JC van Winkel}; 9 | \item{Xing Xing, Chinese translation, 这里是中文译本: {\url{http://www.mikespook.com/learning-go/}} . 10 | } 11 | %%\item{Filip Zaludek}. 12 | %%\item{Jeroen Bulten} 13 | \end{itemize} 14 | 15 | Help with proof reading, checking exercises and text improvements (no 16 | particular order and either real name or an alias): 17 | \input{go-contributors.tex} 18 | 19 | The following people provided smaller improvements, like nits, typos and 20 | other tweaks: 21 | \input{go-nits-contributors.tex} 22 | 23 | \subsection{Miek Gieben} 24 | \input{about-miekg} 25 | 26 | \section{License and copyright} 27 | This work is licensed under the Attribution-NonCommercial-ShareAlike 3.0 Unported License. To 28 | view a copy of this license, visit \url{http://creativecommons.org/licenses/by-nc-sa/3.0/} 29 | or send a letter to Creative Commons, 171 Second Street, Suite 300, San 30 | Francisco, California, 94105, USA.\newline 31 | All example code used in this book is hereby put in the public domain. 32 | 33 | \copyright Miek Gieben -- 2010, 2011. 34 | -------------------------------------------------------------------------------- /ex-beyond/src/cat.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | |\longremark{Include all the packages we need;}| 4 | import ( 5 | "io" 6 | "os" 7 | "fmt" 8 | "bufio" 9 | "flag" 10 | ) 11 | 12 | var numberFlag = flag.Bool("n", false, "number each line") |\longremark{Define a % 13 | new flag "n", which defaults to off. Note that we get the help for free;}| 14 | 15 | |\longremark{Start the function that actually reads the file's contents and displays it;}| 16 | func cat(r *bufio.Reader) { 17 | i := 1 18 | for { 19 | buf, e := r.ReadBytes('\n') |\longremark{Read one line at the time;}| 20 | if e == io.EOF { |\longremark{Or stop if we hit the end;}| 21 | break 22 | } 23 | if *numberFlag { |\longremark{If we should number % 24 | each line, print the line number and then the line itself;}| 25 | fmt.Fprintf(os.Stdout, "%5d %s", i, buf) 26 | i++ 27 | } else { |\longremark{Otherwise we could just print the line.}| 28 | fmt.Fprintf(os.Stdout, "%s", buf) 29 | } 30 | } 31 | return 32 | } 33 | 34 | func main() { 35 | flag.Parse() 36 | if flag.NArg() == 0 { 37 | cat(bufio.NewReader(os.Stdin)) 38 | } 39 | for i := 0; i < flag.NArg(); i++ { 40 | f, e := os.Open(flag.Arg(i)) 41 | if e != nil { 42 | fmt.Fprintf(os.Stderr, "%s: error reading from %s: %s\n", 43 | os.Args[0], flag.Arg(i), e.Error()) 44 | continue 45 | } 46 | cat(bufio.NewReader(f)) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /fig/reflection.tex: -------------------------------------------------------------------------------- 1 | \begin{lstlisting}[caption=Introspection using reflection,label=src:introspection] 2 | |\begin{tikzpicture}[overlay] 3 | \ubrace{3.2,-4.2}{2.2,-4.2}{% 4 | We are dealing with a \type{Type} and according % 5 | to the documentation\footnote{\texttt{go doc reflect}}:% 6 | \begin{quote} % 7 | // Elem returns a type's element type. \\ % 8 | // It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.\\ % 9 | \func{Elem() Type} % 10 | \end{quote} % 11 | So on \var{t} we use \func{Elem()} to get the value the pointer % 12 | points to;}% 13 | \ubrace{4.9,-4.2}{3.8,-4.2}{We have now dereferenced the pointer % 14 | and are "inside" our structure. % 15 | We now use \func{Field(0)} to access the zeroth field;}% 16 | % 17 | \ubrace{6.0,-4.2}{5.1,-4.2}{% 18 | The struct \type{StructField} has a \var{Tag} member which % 19 | returns the tag-name as a string. So on the $0^{th}$ field we can % 20 | unleash \func{.Tag} to access this name: \texttt{Field(0).Tag}. This % 21 | gives us \texttt{namestr}.} 22 | % 23 | \end{tikzpicture}| 24 | type Person struct { 25 | name string "namestr" |\coderemark{\texttt{"namestr"} is the tag}| 26 | age int 27 | } 28 | 29 | func ShowTag(i interface{}) { |\coderemark{Called with *Person}| 30 | switch t := reflect.TypeOf(i); t.Kind() { 31 | case reflect.Ptr: |\coderemark{A pointer, thus \var{reflect.Ptr}}| 32 | tag := t.Elem().Field(0).Tag 33 | \end{lstlisting} 34 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/callback.go: -------------------------------------------------------------------------------- 1 | // From: Jonathan Kans 2 | 3 | package main 4 | 5 | import ( 6 | "image" 7 | "image/png" 8 | "os" 9 | ) 10 | 11 | func DrawSquare(left, top, base int, draw func(x, y int)) { 12 | if draw == nil { 13 | return 14 | } 15 | 16 | right := left + base 17 | bottom := top + base 18 | 19 | for x := left; x <= right; x++ { 20 | draw(x, top) 21 | draw(x, bottom) 22 | } 23 | 24 | for y := top; y <= bottom; y++ { 25 | draw(left, y) 26 | draw(right, y) 27 | } 28 | } 29 | 30 | func main() { 31 | 32 | var thickFrame bool 33 | 34 | rgba := image.NewRGBA(300, 200) 35 | if rgba == nil { 36 | return 37 | } 38 | 39 | redColor := image.RGBAColor{255, 0, 0, 255} 40 | blueColor := image.RGBAColor{0, 0, 255, 255} 41 | 42 | pngFile, err := os.Open("squares.png", os.O_WRONLY|os.O_CREATE, 0644) 43 | if pngFile == nil || err != nil { 44 | return 45 | } 46 | defer pngFile.Close() 47 | 48 | frameSquare := func(x, y int) { 49 | // closure effortlessly passes local variables to callback 50 | if thickFrame { 51 | // draw 3 x 3 pixel block for thicker rectangle 52 | for x0 := x - 1; x0 <= x+1; x0++ { 53 | for y0 := y - 1; y0 <= y+1; y0++ { 54 | rgba.Set(x0, y0, redColor) 55 | } 56 | } 57 | } else { 58 | rgba.Set(x, y, blueColor) 59 | } 60 | } 61 | 62 | thickFrame = true 63 | DrawSquare(30, 20, 50, frameSquare) 64 | thickFrame = false 65 | DrawSquare(100, 120, 35, frameSquare) 66 | 67 | png.Encode(pngFile, rgba) 68 | } 69 | -------------------------------------------------------------------------------- /src/helloworld.go: -------------------------------------------------------------------------------- 1 | package main |\longremark{This first line is just required. All Go files start with % 2 | \lstinline{package }, \lstinline{package main} is required for a % 3 | standalone executable;}| 4 | 5 | import "fmt" |\longremark{This says we need \package{fmt} in % 6 | addition to \package{main}. A package other than \package{main} is commonly called a % 7 | library, a familiar concept in many programming languages (see chapter \ref{chap:packages}). % 8 | The line ends with a comment which is started with \lstinline|//|;}|// Implements formatted I/O. 9 | 10 | /* Print something */ |\longremark{This is also a comment, but this one is enclosed in % 11 | \lstinline|/*| and \lstinline|*/|;}| 12 | func main() { |\longremark{% 13 | Just as \lstinline{package main} was required to be first, % 14 | \lstinline{import} may come next. In Go, \lstinline{package} is always first, then % 15 | \lstinline{import}, then everything else. % 16 | When your Go program is executed, the first function called will be % 17 | \lstinline{main.main()}, which mimics the behavior from C. Here we declare % 18 | that function;}| 19 | |\longremark{% 20 | On line 8 we call a function from the package \package{fmt} to print a % 21 | string to the screen. The string is enclosed with \lstinline{"} and may % 22 | contain non-ASCII characters. Here we use Greek and Japanese.}| 23 | fmt.Printf("Hello, world; or |$\kappa\alpha\lambda\eta\mu\acute{\epsilon}\rho\alpha\hspace{1em}\kappa$\'o$ \sigma\mu\epsilon$|; or |こんにちは 世界|") 24 | } 25 | -------------------------------------------------------------------------------- /ex-functions/ex-bubblesort.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Bubble sort},difficulty=1] 2 | \label{ex:bubble} 3 | \Question\label{ex:bubble q1} Write a function that performs 4 | a bubble sort on a slice of ints. From \cite{bubblesort}: 5 | \begin{quote} 6 | It works by repeatedly stepping through the list to be sorted, comparing each 7 | pair of adjacent items and swapping them if they are in the wrong order. The 8 | pass through the list is repeated until no swaps are needed, which indicates 9 | that the list is sorted. The algorithm gets its name from the way smaller 10 | elements ``bubble'' to the top of the list. 11 | \end{quote} 12 | 13 | \cite{bubblesort} also gives an example in pseudo code: 14 | \begin{lstlisting}[language=pascal] 15 | procedure bubbleSort( A : list of sortable items ) 16 | do 17 | swapped = false 18 | for each i in 1 to length(A) - 1 inclusive do: 19 | if A[i-1] > A[i] then 20 | swap( A[i-1], A[i] ) 21 | swapped = true 22 | end if 23 | end for 24 | while swapped 25 | end procedure 26 | \end{lstlisting} 27 | \end{Exercise} 28 | 29 | \begin{Answer} 30 | \Question 31 | Bubble sort isn't terribly efficient, for $n$ elements it scales 32 | $O(n^2)$. See QuickSort \cite{quicksort} for a better sorting algorithm. 33 | 34 | But bubble sort is easy to implement: 35 | \lstinputlisting[caption=Bubble sort,linerange=4-19]{ex-functions/src/bubblesort.go} 36 | 37 | Because a slice is a reference type the \func{bubblesort} function works and 38 | does not need to return a sorted slice. 39 | \end{Answer} 40 | -------------------------------------------------------------------------------- /ex-beyond/ex-pointers.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Pointers},difficulty=1] 2 | \label{ex:pointers} 3 | 4 | \Question 5 | Suppose we have defined the following structure: 6 | \begin{lstlisting} 7 | type Person struct { 8 | name string 9 | age int 10 | } 11 | \end{lstlisting} 12 | 13 | What is the difference between the following two lines? 14 | \begin{lstlisting} 15 | var p1 Person 16 | p2 := new(Person) 17 | \end{lstlisting} 18 | 19 | \Question 20 | What is the difference between the following two allocations? 21 | \begin{lstlisting}[numbers=none] 22 | func Set(t *T) { 23 | x = t 24 | } 25 | \end{lstlisting} 26 | and 27 | \begin{lstlisting}[numbers=none] 28 | func Set(t T) { 29 | x= &t 30 | } 31 | \end{lstlisting} 32 | \end{Exercise} 33 | 34 | \begin{Answer} 35 | \Question 36 | In first line: \lstinline{var p1 Person} allocates a 37 | \texttt{Person}-\emph{value} to \var{p1}. The type of \var{p1} is 38 | \type{Person}. 39 | 40 | The second line: \lstinline{p2 := new(Person)} allocates memory 41 | and assigns a \emph{pointer} to \var{p2}. The type of \var{p2} is 42 | \type{*Person}. 43 | 44 | \Question 45 | In the second function, \var{x} points to a new 46 | (heap-allocated) variable \var{t} which contains 47 | a copy of whatever the actual argument value is. 48 | 49 | In the first function, \var{x} points to the same thing 50 | that \var{t} does, which is the same thing that the actual 51 | argument points to. 52 | 53 | So in the second function, we have an ``extra'' variable 54 | containing a copy of the interesting value. 55 | \end{Answer} 56 | -------------------------------------------------------------------------------- /ex-functions/ex-funcfunc.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Functions that return functions},difficulty=1] 2 | \label{ex:function} 3 | \Question\label{ex:function q1} Write a function that returns a function 4 | that performs a $+2$ on integers. Name the function \func{plusTwo}. 5 | You should then be able do the following: 6 | \begin{lstlisting} 7 | p := plusTwo() 8 | fmt.Printf("%v\n", p(2)) 9 | \end{lstlisting} 10 | Which should print 4. 11 | See section \titleref{sec:callbacks} on page \pageref{sec:callbacks} for information 12 | about this topic. 13 | 14 | \Question\label{ex:function q2} Generalize the function from \ref{ex:function q1}, 15 | and create a \func{plusX(x)} which returns functions that add \var{x} to an 16 | integer. 17 | \end{Exercise} 18 | 19 | \begin{Answer} 20 | \Question 21 | \begin{lstlisting} 22 | func main() { 23 | p2 := plusTwo() 24 | fmt.Printf("%v\n",p2(2)) 25 | } 26 | 27 | func plusTwo() func(int) int { |\longremark{Define a new function that returns a function. % 28 | See how you you can just write down what you mean;}| 29 | return func(x int) int { return x + 2 } |\longremark{Function literals at work, % 30 | we define the +2--function right there in the return statement.}| 31 | } 32 | \end{lstlisting} 33 | \showremarks 34 | 35 | \Question 36 | Here we use a closure: 37 | \begin{lstlisting} 38 | func plusX(x int) func(int) int { |\longremark{Again define a function that returns % 39 | a function;}| 40 | return func(y int) int { return x + y } |\longremark{Use the \emph{local} variable % 41 | \var{x} in the function literal.}| 42 | } 43 | \end{lstlisting} 44 | \showremarks 45 | \end{Answer} 46 | -------------------------------------------------------------------------------- /ex-functions/ex-minmax.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Minimum and maximum},difficulty=0] 2 | \label{ex:minmax} 3 | \Question\label{ex:minmax q1} Write a function that finds the 4 | maximum value in an \type{int} slice (\type{[]int}). 5 | 6 | \Question\label{ex:minmax q2} Write a function that finds the 7 | minimum value in an \type{int} slice (\type{[]int}). 8 | 9 | \end{Exercise} 10 | 11 | \begin{Answer} 12 | \Question This function returns the largest int in the slice \var{l}: 13 | \begin{lstlisting} 14 | func max(l []int) (max int) { |\longremark{We use a named return parameter;}| 15 | max = l[0] 16 | for _, v := range l { |\longremark{Loop over \var{l}. The index of the element is % 17 | not important;}| 18 | if v > max { |\longremark{If we find a new maximum, remember it;}| 19 | max = v 20 | } 21 | } 22 | return |\longremark{A ``lone'' return, the current value of \var{max} is now returned.}| 23 | } 24 | \end{lstlisting} 25 | \showremarks 26 | 27 | \Question This function returns the smallest int in the slice \var{l}. It is almost identical to \func{max}: 28 | \begin{lstlisting} 29 | func min(l []int) (min int) { 30 | min = l[0] 31 | for _, v := range l { 32 | if v < min { 33 | min = v 34 | } 35 | } 36 | return 37 | } 38 | \end{lstlisting} 39 | The interested reader may combine \func{max} and \func{min} into one function with a selector 40 | that lets you choose between the minimum or the maximum, or one that returns both values. 41 | \end{Answer} 42 | -------------------------------------------------------------------------------- /ex-interfaces/ex-minmax.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Interfaces and max()},difficulty=2] 2 | \Question 3 | In exercise Q\ref{ex:minmax} we created a max function that works on 4 | a slice of integers. 5 | The question now is to create 6 | a program that shows the maximum number and that works for both integers and floats. 7 | Try to make your program as generic as possible, although that is quite difficult in 8 | this case. 9 | \end{Exercise} 10 | 11 | \begin{Answer} 12 | \Question 13 | The following program calculates a maximum. It is as generic as you can get 14 | with Go. 15 | 16 | \begin{lstlisting}[caption=Generic way of calculating a maximum] 17 | package main 18 | 19 | func Less(l, r interface{}) bool { |\longremark{We could have chosen to make the % 20 | return type of this function an \mbox{\type{interface\{\}}}, but that would mean % 21 | that a caller would always have to do a type assertion to extract the actual type % 22 | from the interface;}| 23 | switch l.(type) { 24 | case int: 25 | if _, ok := r.(int); ok { 26 | return l.(int) < r.(int) |\longremark{All parameters are confirmed to be % 27 | integers. Now perform the comparison;}| 28 | } 29 | case float32: 30 | if _, ok := r.(float32); ok { 31 | return l.(float32) < r.(float32) |\longremark{Parameters are \type{float32};}| 32 | } 33 | } 34 | return false 35 | } 36 | 37 | func main() { 38 | var a, b, c int = 5, 15, 0 39 | var x, y, z float32 = 5.4, 29.3, 0.0 40 | 41 | if c = a; Less(a, b) { |\longremark{Get the maximum of \var{a} and \var{b};}| 42 | c = b 43 | } 44 | if z = x; Less(x, y) { |\longremark{Same for the floats.}| 45 | z = y 46 | } 47 | println(c, z) 48 | } 49 | \end{lstlisting} 50 | \showremarks 51 | \end{Answer} 52 | -------------------------------------------------------------------------------- /ex-packages/ex-stack-package.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Stack as package},difficulty=0] 2 | \label{ex:stack-package} 3 | \Question\label{ex:stack-package q1} 4 | See the Q\ref{ex:stack} exercise. In this exercise we want to create 5 | a separate package for that code. 6 | Create a proper package for your 7 | stack implementation, \func{Push}, \func{Pop} and the \type{Stack} type need to be 8 | exported. 9 | 10 | \Question\label{ex:stack-package q2} Write a simple unit test for this package. 11 | You should at least test that a \func{Pop} works after a \func{Push}. 12 | 13 | \end{Exercise} 14 | 15 | \begin{Answer} 16 | \Question There are a few details that should be changed to make a proper package 17 | for our stack. First, the exported functions should begin with a capital 18 | letter and so should \type{Stack}. The package file is named \file{stack-as-package.go} 19 | and contains: 20 | \lstinputlisting[caption=Stack in a package]{ex-packages/src/stack-as-package.go} 21 | 22 | \Question To make the unit testing work properly you need to do some 23 | preparations. We'll come to those in a minute. First the actual unit test. 24 | Create a file with the name \file{pushpop\_test.go}, with the following contents: 25 | \lstinputlisting[caption=Push/Pop test]{ex-packages/src/pushpop_test.go} 26 | 27 | For \prog{go test} to work we need to put our package files in a directory 28 | under \var{\$GOPATH/src}:\\ 29 | 30 | \begin{display} 31 | \pr \user{mkdir $GOPATH/src/stack} 32 | \pr \user{cp pushpop_test.go $GOPATH/src/stack} 33 | \pr \user{cp stack-as-package.go $GOPATH/src/stack} 34 | \end{display} 35 | 36 | Yields:\\ 37 | 38 | \begin{display} 39 | \pr \user{go test stack} 40 | ok stack 0.001s 41 | \end{display} 42 | 43 | \end{Answer} 44 | -------------------------------------------------------------------------------- /fig/function.tex: -------------------------------------------------------------------------------- 1 | \begin{lstlisting}[caption=A function declaration,label=src:function definition] 2 | |\begin{tikzpicture}[overlay] 3 | \ubrace{0.8,-1.5}{0.0,-1.5}{The keyword \key{func} is used to declare a function;} 4 | % 5 | \ubrace{2.9,-1.5}{0.9,-1.5}{A function can optionally be bound to a specific type. % 6 | This is called the \first{\emph{receiver}}{receiver}. A function with a receiver is % 7 | a \index{method}{method}. This will be explored in chapter \ref{chap:interfaces};} 8 | % 9 | \ubrace{4.6,-1.5}{3.1,-1.5}{\emph{funcname} is the name of your function;} 10 | % 11 | \ubrace{5.9,-1.5}{4.7,-1.5}{The variable \var{q} of type \type{int} is % 12 | the input parameter. The parameters are passed % 13 | \first{\emph{pass-by-value}}{pass-by-value} meaning they are copied;} 14 | % 15 | \ubrace{7.7,-1.5}{6.1,-1.5}{% 16 | The variables \var{r} and \var{s} are the % 17 | \index{named return parameters}{named return parameters} for this function. % 18 | Functions in Go can have multiple return values, see section % 19 | "\titleref{sec:multiple return}" on page \pageref{sec:multiple return}. % 20 | If you want the return % 21 | parameters not to be named you only give the types: % 22 | \lstinline{(int,int)}. If you have only one value to return you may omit % 23 | the parentheses. If your function is a subroutine and does not have % 24 | anything to return you may omit this entirely;} 25 | % 26 | \ubrace{10.7,-1.5}{8.0,-1.5}{This is the function's body. Note that % 27 | \func{return} is a statement so the braces around the parameter(s) are % 28 | optional.} 29 | \end{tikzpicture}| 30 | type mytype int |\coderemark{New type, see chapter \ref{chap:beyond}}| 31 | 32 | func (p mytype) funcname(q int) (r,s int) { return 0,0 } 33 | || 34 | \end{lstlisting} 35 | -------------------------------------------------------------------------------- /ex-communication/ex-numbercruncher.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Number cruncher},difficulty=2] 2 | \label{ex:numbercruncher} 3 | \begin{itemize} 4 | \item{Pick six (6) random numbers from this list: 5 | $$1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 25, 50, 75, 100$$ 6 | Numbers may be picked multiple times;} 7 | \item{Pick one (1) random number ($i$) in the range: $1 \ldots 1000$;} 8 | \item{Tell how, by combining the first 6 numbers (or a subset thereof) 9 | with the operators $+$,$-$,$*$ and $/$, you can make $i$;} 10 | \end{itemize} 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 | \Question\label{ex:cruncher q1} 18 | Implement a number cruncher that works like that. Make it print the 19 | solution in a similar format (i.e. output should be infix with 20 | parenthesis) as used above. 21 | \Question\label{ex:cruncher q2} 22 | Calculate \emph{all} possible solutions and show them (or only show how 23 | many there are). In the example above there are 544 ways to do it. 24 | \end{Exercise} 25 | 26 | \begin{Answer} 27 | \Question 28 | The following is one possibility. It uses recursion and backtracking to get 29 | an answer. 30 | \lstinputlisting[caption=Number cruncher]{ex-communication/src/permrec.go} 31 | 32 | \Question 33 | When starting \prog{permrec} we give 977 as the first argument: 34 | \vspace{1em} 35 | \begin{display} 36 | \pr ./permrec 977 37 | 1+(((6+7)*75)+(8/8)) = 977 #1 38 | ... ... 39 | ((75+(8*6))*8)-7 = 977 #542 40 | (((75+(8*6))*8)-7)*1 = 977 #543 41 | (((75+(8*6))*8)-7)/1 = 977 #544 42 | \end{display} 43 | 44 | \end{Answer} 45 | -------------------------------------------------------------------------------- /bin/go-lstinputlisting.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # extract Go code and compile it 3 | use strict; 4 | use warnings; 5 | 6 | my $quiet = 1; 7 | my $i = 1; 8 | my $basedir=$ARGV[0] if defined $ARGV[0]; 9 | if (!defined $basedir) { 10 | die "No basedir"; 11 | } 12 | shift; 13 | 14 | # remove |coderemarks| 15 | sub removeremark($) { 16 | my $file = shift; 17 | open GO, "+<", $file or die "Cannot open: $file"; 18 | my @go; 19 | my $skip = 0; 20 | while() { 21 | if ($skip) { 22 | # check if we have % again, if so, skip again 23 | if (/\%$/) { next; } 24 | $skip = 0; 25 | next; 26 | } 27 | 28 | if (/\%$/) { $skip = 1; next; } 29 | if (/\|\\begin/) { $skip = 1; next; } 30 | if (/\|\\draw/) { $skip = 1; next; } 31 | if (/\\end/) { $skip = 0; next; } 32 | 33 | s/\%.*$//; 34 | s/\\draw.*$//; 35 | s/\|\\coderemark.*?(\||\%$|$)//; 36 | s/\|\\longremark.*?(\||\%$|$)//; 37 | s/\\newline//; 38 | push @go, $_; 39 | } 40 | truncate GO, 0; 41 | seek GO, 0, 0; 42 | foreach(@go) { 43 | print GO $_; 44 | } 45 | close GO; 46 | } 47 | 48 | sub compile($) { 49 | my $file = shift; 50 | my $target = "/tmp/$$.go.$i"; 51 | $i++; 52 | system("cp $basedir/$file $target"); 53 | removeremark($target); 54 | system("6g $target"); 55 | unlink($target); 56 | $? >> 8; 57 | } 58 | 59 | my $inlisting = 0; 60 | my @listing; 61 | while(<>) { 62 | if (m|\\lstinputlisting(\[.*?\])?{(.*)}|) { 63 | my $gofile = $2; 64 | if ($gofile !~ /\.go$/) { 65 | print "No Go : $gofile\n" if not $quiet; 66 | next; 67 | } 68 | if (compile($gofile) != 0) { 69 | print "Compiling: 6g $gofile -- "; 70 | print "NOT OK\n"; 71 | } else { 72 | print "OK\n" if not $quiet; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /ex-basics/ex-for.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={For-loop},difficulty=0] 2 | \label{ex:for-loop} 3 | \Question \label{ex:for-loop q1} Create a simple loop with the \key{for} construct. Make it loop 4 | 10 times and print out the loop counter with the \package{fmt} package. 5 | 6 | \Question \label{ex:for-loop q2} Rewrite the loop from \ref{ex:for-loop q1}. to use \key{goto}. The 7 | keyword \key{for} may not be used. 8 | 9 | \Question \label{ex:for-loop q3} Rewrite the loop again so that it fills an array and then 10 | prints that array to the screen. 11 | \end{Exercise} 12 | 13 | \begin{Answer} 14 | 15 | \Question There are a multitude of possibilities, 16 | one of the solutions could be: 17 | \lstinputlisting[caption={Simple for loop},label=src:for]{ex-basics/src/for.go} 18 | Let's compile this and look at the output. 19 | \vskip\baselineskip 20 | \begin{display} 21 | \pr go build for.go 22 | \pr ./for 23 | 0 24 | 1 25 | . 26 | . 27 | . 28 | 9 29 | \end{display} 30 | \vskip\baselineskip 31 | 32 | \Question Rewriting the loop results in code that should look something 33 | like this (only showing the \func{main}-function): 34 | \begin{lstlisting} 35 | func main() { 36 | i := 0 |\coderemark{Define our loop variable}| 37 | Loop: |\coderemark{Define a label}| 38 | fmt.Printf("%d\n", i) 39 | if i < 10 { 40 | i++ 41 | goto Loop |\coderemark{Jump to the label}| 42 | } 43 | } 44 | \end{lstlisting} 45 | 46 | \Question 47 | The following is one possible solution: 48 | \lstinputlisting[label=src:for-arr,caption={For loop with an array},linerange={5,11}]{ex-basics/src/for-arr.go} 49 | You could even do this in one fell swoop by using a composite literal: 50 | \begin{lstlisting} 51 | a := [...]int{0,1,2,3,4,5,6,7,8,9} |\coderemark{Let Go count}| 52 | fmt.Printf("%v\n", a) 53 | \end{lstlisting} 54 | \end{Answer} 55 | -------------------------------------------------------------------------------- /ex-beyond/src/doubly-linked-list.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | |\longremark{Include all the packages we need.}| 4 | import ( 5 | "errors" 6 | "fmt" 7 | ) 8 | 9 | type Value int |\longremark{Declare a type for the value our list will contain;}| 10 | 11 | type Node struct { |\longremark{declare a type for the each node in our list;}| 12 | Value 13 | prev, next *Node 14 | } 15 | 16 | type List struct { 17 | head, tail *Node 18 | } 19 | 20 | |\longremark{Mimic the interface of container/list.}| 21 | func (l *List) Front() *Node { 22 | return l.head 23 | } 24 | 25 | func (n *Node) Next() *Node { 26 | return n.next 27 | } 28 | 29 | func (l *List) Push(v Value) *List { 30 | n := &Node{Value: v} |\longremark{When pushing, create a new Node with the provided value;}| 31 | 32 | if l.head == nil { |\longremark{if the list is empty, put the new node at the head;}| 33 | l.head = n 34 | } else { 35 | l.tail.next = n |\longremark{otherwise put it at the tail;}| 36 | n.prev = l.tail |\longremark{make sure the new node points back to the previously existing one;}| 37 | } 38 | l.tail = n |\longremark{point tail to the newly inserted node.}| 39 | 40 | return l 41 | } 42 | 43 | var errEmpty = errors.New("List is empty") 44 | 45 | func (l *List) Pop() (v Value, err error) { 46 | if l.tail == nil { |\longremark{When popping, return an error if the list is empty;}| 47 | err = errEmpty 48 | } else { 49 | v = l.tail.Value |\longremark{otherwise save the last value;}| 50 | l.tail = l.tail.prev |\longremark{discard the last node from the list;}| 51 | if l.tail == nil { 52 | l.head = nil |\longremark{and make sure the list is consistent if it becomes empty;}| 53 | } 54 | } 55 | 56 | return v, err 57 | } 58 | 59 | func main() { 60 | l := new(List) 61 | 62 | l.Push(1) 63 | l.Push(2) 64 | l.Push(4) 65 | 66 | for n := l.Front(); n != nil; n = n.Next() { 67 | fmt.Printf("%v\n", n.Value) 68 | } 69 | 70 | fmt.Println() 71 | 72 | for v, err := l.Pop(); err == nil; v, err = l.Pop() { 73 | fmt.Printf("%v\n", v) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /ex-communication/ex-processes.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Processes},difficulty=2] 2 | \label{ex:processes} 3 | \Question\label{ex:processes q1} 4 | Write a program that takes a list of all running processes and prints 5 | how many child processes each parent has spawned. The output should 6 | look like: 7 | %% For some reason the spacing in Exercise env. does weird things 8 | \vskip\baselineskip 9 | \begin{display} 10 | Pid 0 has 2 children: [1 2] 11 | Pid 490 has 2 children: [1199 26524] 12 | Pid 1824 has 1 child: [7293] 13 | \end{display} 14 | \vskip\baselineskip 15 | \begin{itemize} 16 | \item{For acquiring the process list, you'll need to capture the output 17 | of \verb|ps -e -opid,ppid,comm|. This output looks like: 18 | \vskip\baselineskip 19 | \begin{display} 20 | PID PPID COMMAND 21 | 9024 9023 zsh 22 | 19560 9024 ps 23 | \end{display} 24 | \vskip\baselineskip} 25 | \item{If a parent has one child you must print \verb|child|, if there is 26 | more than one print \verb|children|;} 27 | \item{The process list must be numerically sorted, so you start with 28 | pid 0 and work your way up.} 29 | \end{itemize} 30 | Here is a Perl version to help you on your way (or to create complete 31 | and utter confusion). 32 | \lstinputlisting[caption={Processes in Perl}]{ex-communication/src/proc.pl} 33 | \end{Exercise} 34 | 35 | \begin{Answer} 36 | \Question There is lots of stuff to do here. We can divide our program 37 | up in the following sections: 38 | \begin{enumerate} 39 | \item{Starting \verb|ps| and capturing the output;} 40 | \item{Parsing the output and saving the child PIDs for each PPID;} 41 | \item{Sorting the PPID list;} 42 | \item{Printing the sorted list to the screen} 43 | \end{enumerate} 44 | In the solution presented below, we've used a \type{map[int][]int}, 45 | i.e. a map indexed with integers, pointing to a slice of ints -- which holds the 46 | PIDs. The builtin \func{append} is used to grow the integer slice. 47 | 48 | A possible program is: 49 | \lstinputlisting[caption=Processes in Go]{ex-communication/src/proc.go} 50 | \end{Answer} 51 | -------------------------------------------------------------------------------- /ex-channels/ex-for-channels.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Channels},difficulty=1] 2 | \label{ex:channels} 3 | \Question\label{ex:channels q1} Modify the program you created in 4 | exercise Q\ref{ex:for-loop} 5 | to use channels, in other words, the function called in the body 6 | should now be a goroutine and communication should happen via 7 | channels. You should not worry yourself on how the goroutine 8 | terminates. 9 | 10 | \Question\label{ex:channels q2} There are a few annoying issues left if 11 | you resolve question \ref{ex:channels q1}. One of the problems is 12 | that the goroutine isn't neatly cleaned up when \func{main.main()} 13 | exits. And worse, due to a race condition between the exit of 14 | \func{main.main()} and \func{main.shower()} not all numbers are printed. 15 | It should print up until 9, but sometimes it prints only to 8. Adding 16 | a second quit-channel you can remedy both issues. Do this.\footnote{You 17 | will need the \func{select} statement.} 18 | 19 | \end{Exercise} 20 | 21 | \begin{Answer} 22 | \Question A possible program is: 23 | \lstinputlisting[label=go-chan,caption=Channels in Go,numbers=right]{ex-channels/src/for-chan.go} 24 | We start of in the usual way, then at line 6 we create a new channel of 25 | ints. In the next line we fire off the function \func{shower} with 26 | the \prog{ch} variable as it argument, so that we may communicate with 27 | it. Next we start our for-loop (lines 8-10) and in the loop 28 | we send (with \lstinline{<-}) our number to the function (now a goroutine) \func{shower}. 29 | 30 | In the function \func{shower} we wait (as this blocks) until we receive a number (line 31 | 15). Any received number is printed (line 16) and then continue the endless loop 32 | started on line 14. 33 | 34 | \Question An answer is 35 | \lstinputlisting[label=go-quit-chan,caption=Adding an extra quit channel,numbers=right]{ex-channels/src/for-quit-chan.go} 36 | On line 20 we read from the quit channel and we discard the value we 37 | read. We could have used \lstinline{q := <-quit}, but then we would have used 38 | the variable only once --- which is illegal in Go. Another trick you 39 | might have pulled out of your hat may be: \lstinline{_ = <-quit}. This is 40 | valid in Go, but the Go idiom favors the one given on line 20. 41 | \end{Answer} 42 | -------------------------------------------------------------------------------- /ex-basics/ex-strings.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Strings},difficulty=1] 2 | \label{ex:strings} 3 | \Question \label{ex:strings q1} Create a Go program that prints 4 | the following (up to 100 characters): 5 | \vskip\baselineskip 6 | \begin{display} 7 | A 8 | AA 9 | AAA 10 | AAAA 11 | AAAAA 12 | AAAAAA 13 | AAAAAAA 14 | ... 15 | \end{display} 16 | \vskip\baselineskip 17 | 18 | \Question \label{ex:strings q2} Create a program that counts 19 | the number of characters in this string: 20 | \begin{display} 21 | asSASA ddd dsjkdsjs dk 22 | \end{display} 23 | In addition, make it output the number of bytes in that string. 24 | \emph{Hint}: Check out the \package{utf8} package. 25 | 26 | \Question \label{ex:string q3} Extend/change the program from 27 | the previous question to replace the three runes at 28 | position 4 with 'abc'. 29 | 30 | \Question \label{ex:string q4} Write a Go program 31 | that reverses a string, so ``foobar'' is printed as ``raboof''. 32 | \emph{Hint}: You will need to know about 33 | conversion; skip ahead to section ``\titleref{sec:conversions}'' on 34 | page \pageref{sec:conversions}. 35 | 36 | \end{Exercise} 37 | 38 | \begin{Answer} 39 | 40 | \Question This program is a solution: 41 | 42 | \lstinputlisting[label=string1,caption=Strings]{ex-basics/src/string1.go} 43 | 44 | \Question To answer this question we need some help from 45 | the \package{unicode/utf8} package. First we check the documentation 46 | with \prog{godoc unicode/utf8 | less}. When we read the documentation 47 | we notice \lstinline{func RuneCount(p []byte) int}. Secondly 48 | we can convert \emph{string} to a \type{byte} slice with 49 | \begin{lstlisting} 50 | str := "hello" 51 | b := []byte(str) |\coderemark{Conversion, see page \pageref{sec:conversions}}| 52 | \end{lstlisting} 53 | 54 | Putting this together leads to the following program. 55 | 56 | \begin{minipage}{\textwidth} 57 | \lstinputlisting[label=src:string2,caption=Runes in strings]{ex-basics/src/string2.go} 58 | \end{minipage} 59 | 60 | \Question Something along the lines of: 61 | \begin{minipage}{\textwidth} 62 | \lstinputlisting[label=src:string3]{ex-basics/src/string3.go} 63 | \end{minipage} 64 | 65 | \Question Reversing a string can be done as follows. We start from the left (\var{i}) and 66 | the right (\var{j}) and swap the characters as we see them: 67 | 68 | \begin{minipage}{\textwidth} 69 | \lstinputlisting[label=src:stringrev,caption=Reverse a string,linerange={3,}]{ex-basics/src/stringrev.go} 70 | \end{minipage} 71 | 72 | \end{Answer} 73 | -------------------------------------------------------------------------------- /ex-beyond/ex-pointers-method.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Method calls},difficulty=2] 2 | \label{ex:methodcalls} 3 | \Question \label{ex:methodcalls q1} Suppose we have the following 4 | program. Note the package \package{container/vector} was once part 5 | of Go, but has been removed when the \func{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 | \begin{lstlisting} 9 | package main 10 | 11 | import "container/vector" 12 | 13 | func main() { 14 | k1 := vector.IntVector{} 15 | k2 := &vector.IntVector{} 16 | k3 := new(vector.IntVector) 17 | k1.Push(2) 18 | k2.Push(3) 19 | k3.Push(4) 20 | } 21 | \end{lstlisting} 22 | What are the types of \var{k1}, \var{k2} and \var{k3}? 23 | 24 | \Question Now, this program compiles and runs OK. All the \func{Push} 25 | operations work even though the variables are of a different type. The 26 | documentation for \func{Push} says: 27 | \begin{quote} 28 | func (p *IntVector) Push(x int) 29 | Push appends x to the end of the vector. 30 | \end{quote} 31 | So the receiver has to be of type \type{*IntVector}, why does the code 32 | above (the Push statements) work correct then? 33 | 34 | \end{Exercise} 35 | 36 | \begin{Answer} 37 | \Question The type of \var{k1} is \type{vector.IntVector}. Why? We use 38 | a composite literal (the \verb|{}|), so we get a value of that type 39 | back. The variable \var{k2} is of \type{*vector.IntVector}, because we 40 | take the address (\verb|&|) of the composite literal. And finally 41 | \var{k3} has also the type \type{*vector.IntVector}, because \func{new} 42 | returns a pointer to the type. 43 | 44 | \Question The answer is given in \cite{go_spec} in the section ``Calls'', 45 | where among other things it says: 46 | \begin{quote} 47 | A method call \func{x.m()} is valid if the method set of (the type of) 48 | \var{x} 49 | contains \func{m} and the argument list can be assigned to the parameter list 50 | of \func{m}. If \var{x} is addressable and \var{\&x}'s method set 51 | contains \func{m}, \func{x.m()} is shorthand for \func{(\&x).m()}. 52 | \end{quote} 53 | In other words because \var{k1} is addressable and 54 | \type{*vector.IntVector} \emph{does} have the \func{Push} method, the 55 | call \lstinline{k1.Push(2)} is translated by Go into 56 | \lstinline{(&k1).Push(2)} which makes the type system happy again (and 57 | you too --- now you know this).\footnote{Also see section 58 | ``\titleref{sec:methods}'' in this chapter.} 59 | 60 | \end{Answer} 61 | -------------------------------------------------------------------------------- /fonts/Paratype PT Sans Free Font License.txt: -------------------------------------------------------------------------------- 1 | Copyright © 2009 ParaType Ltd. 2 | with Reserved Names "PT Sans" and "ParaType". 3 | 4 | FONT LICENSE 5 | 6 | PERMISSION & CONDITIONS 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of the font software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the font software, subject to the following conditions: 8 | 9 | 1) Neither the font software nor any of its individual components, in original or modified versions, may be sold by itself. 10 | 11 | 2) Original or modified versions of the font software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 12 | 13 | 3) No modified version of the font software may use the Reserved Name(s) or combinations of Reserved Names with other words unless explicit written permission is granted by the ParaType. This restriction only applies to the primary font name as presented to the users. 14 | 15 | 4) The name of ParaType or the author(s) of the font software shall not be used to promote, endorse or advertise any modified version, except to acknowledge the contribution(s) of ParaType and the author(s) or with explicit written permission of ParaType. 16 | 17 | 5) The font software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. 18 | 19 | TERMINATION & TERRITORY 20 | This license has no limits on time and territory, but it becomes null and void if any of the above conditions are not met. 21 | 22 | DISCLAIMER 23 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL PARATYPE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. 24 | 25 | ParaType Ltd 26 | http://www.paratype.ru -------------------------------------------------------------------------------- /bin/go-lstlisting.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # extract Go code and compile it 3 | use strict; 4 | use warnings; 5 | 6 | my $quiet = 0; 7 | 8 | sub removeremark(@) { 9 | my @go; 10 | my $skip = 0; 11 | foreach(@_) { 12 | if ($skip) { 13 | # check if we have % again, if so, skip again 14 | if (/\%$/) { next; } 15 | $skip = 0; 16 | next; 17 | } 18 | 19 | if (/\%$/) { $skip = 1; next; } 20 | if (/\|\\begin/) { $skip = 1; next; } 21 | if (/\|\\draw/) { $skip = 1; next; } 22 | if (/\\end/) { $skip = 0; next; } 23 | 24 | 25 | s/\%[^a-zA-Z].*$//; 26 | s/\\draw.*$//; 27 | s/\|\\coderemark.*?(\||\%$|$)//; 28 | s/\|\\longremark.*?(\||\%$|$)//; 29 | s/\\newline//; 30 | s/\|.*\|//; 31 | push @go, $_; 32 | } 33 | @go; 34 | } 35 | 36 | sub nl(@) { 37 | my $i = 0; 38 | foreach(@_) { 39 | print ++$i, "\t", $_; 40 | } 41 | } 42 | 43 | sub gofmt(@) { 44 | open FMT, "|-", "gofmt > /dev/null"; 45 | foreach(@_) { 46 | print FMT $_; 47 | } 48 | close FMT; 49 | $?; 50 | } 51 | 52 | my $inlisting = 0; 53 | my @listing; 54 | my ($snip, $func); 55 | my (@func, @snip); 56 | while(<>) { 57 | if (m|\\begin{lstlisting}|) { 58 | $inlisting = 1; 59 | next; 60 | } 61 | if (m|\\end{lstlisting}|) { 62 | $inlisting = 0; 63 | 64 | @listing = removeremark(@listing); 65 | 66 | if ( grep { /package main/ } @listing ) { 67 | 68 | unshift @listing, "// Full program\n"; 69 | print "FULL FULL FULL -- " if not $quiet; 70 | if (gofmt(@listing) != 0) { 71 | print "\n"; 72 | nl @listing; 73 | print "$ARGV - NOT OK\n"; 74 | } else { 75 | print "OK\n" if not $quiet; 76 | } 77 | 78 | } elsif ( grep { /func .*?\(/ } @listing ) { 79 | push @func, "// $ARGV - Function " . ++$func . "\n"; 80 | grep { s/(import)/\/\/$1/} @listing; 81 | @func = (@func, @listing); 82 | } else { 83 | push @snip, "// $ARGV - Snippet " . ++$snip . "\n"; 84 | grep { s/(import)/\/\/$1/} @listing; 85 | @snip = (@snip, @listing); 86 | } 87 | @listing = (); 88 | next; 89 | } 90 | if ($inlisting == 1) { 91 | push @listing, $_; 92 | } 93 | } 94 | # snippets 95 | unshift @snip, < %% 4 | %% ---------------------------------------------------------- %% 5 | %% Licensed under Creative Commons Attribution-ShareAlike 3.0 %% 6 | %% http://creativecommons.org/licenses/by-sa/3.0/ %% 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | 9 | 10 | %% Images 11 | \newcommand{\CcImageBy}[1]{% 12 | \includegraphics[scale=#1]{creative_commons/cc_by_30.pdf}% 13 | } 14 | \newcommand{\CcImageCc}[1]{% 15 | \includegraphics[scale=#1]{creative_commons/cc_cc_30.pdf}% 16 | } 17 | \newcommand{\CcImageDevNations}[1]{% 18 | \includegraphics[scale=#1]{creative_commons/cc_dev_nations_30.pdf}% 19 | } 20 | \newcommand{\CcImageNc}[1]{% 21 | \includegraphics[scale=#1]{creative_commons/cc_nc_30.pdf}% 22 | } 23 | \newcommand{\CcImageNd}[1]{% 24 | \includegraphics[scale=#1]{creative_commons/cc_nd_30.pdf}% 25 | } 26 | \newcommand{\CcImagePd}[1]{% 27 | \includegraphics[scale=#1]{creative_commons/cc_pd_30.pdf}% 28 | } 29 | \newcommand{\CcImageSa}[1]{% 30 | \includegraphics[scale=#1]{creative_commons/cc_sa_30.pdf}% 31 | } 32 | \newcommand{\CcImageSampling}[1]{% 33 | \includegraphics[scale=#1]{creative_commons/cc_sampling_30.pdf}% 34 | } 35 | \newcommand{\CcImageSamplingPlus}[1]{% 36 | \includegraphics[scale=#1]{creative_commons/cc_sampling_plus_30.pdf}% 37 | } 38 | 39 | 40 | %% Groups 41 | \newcommand{\CcGroupBy}[1]{% zoom 42 | \CcImageBy{#1}% 43 | } 44 | \newcommand{\CcGroupByNc}[2]{% zoom, gap 45 | \CcImageBy{#1}\hspace*{#2}\CcImageNc{#1}% 46 | } 47 | \newcommand{\CcGroupByNcNd}[2]{% zoom, gap 48 | \CcImageBy{#1}\hspace*{#2}\CcImageNc{#1}\hspace*{#2}\CcImageNd{#1}% 49 | } 50 | \newcommand{\CcGroupByNcSa}[2]{% zoom, gap 51 | \CcImageBy{#1}\hspace*{#2}\CcImageNc{#1}\hspace*{#2}\CcImageSa{#1}% 52 | } 53 | \newcommand{\CcGroupByNd}[2]{% zoom, gap 54 | \CcImageBy{#1}\hspace*{#2}\CcImageNd{#1}% 55 | } 56 | \newcommand{\CcGroupBySa}[2]{% zoom, gap 57 | \CcImageBy{#1}\hspace*{#2}\CcImageSa{#1}% 58 | } 59 | \newcommand{\CcGroupDevNations}[1]{% zoom 60 | \CcImageDevNations{#1}% 61 | } 62 | \newcommand{\CcGroupNcSampling}[2]{% zoom, gap 63 | \CcImageNc{#1}\hspace*{#2}\CcImageSampling{#1}% 64 | } 65 | \newcommand{\CcGroupPd}[1]{% zoom 66 | \CcImagePd{#1}% 67 | } 68 | \newcommand{\CcGroupSampling}[1]{% zoom 69 | \CcImageSampling{#1}% 70 | } 71 | \newcommand{\CcGroupSamplingPlus}[1]{% zoom 72 | \CcImageSamplingPlus{#1}% 73 | } 74 | 75 | 76 | %% Text 77 | \newcommand{\CcLongnameBy}{Attribution} 78 | \newcommand{\CcLongnameByNc}{Attribution-NonCommercial} 79 | \newcommand{\CcLongnameByNcNd}{Attribution-NoDerivs} 80 | \newcommand{\CcLongnameByNcSa}{Attribution-NonCommercial-ShareAlike} 81 | \newcommand{\CcLongnameByNd}{Attribution-NoDerivs} 82 | \newcommand{\CcLongnameBySa}{Attribution-ShareAlike} 83 | 84 | \newcommand{\CcNote}[1]{% longname 85 | This work is licensed under the \textit{Creative Commons #1 3.0 License}.% 86 | } 87 | -------------------------------------------------------------------------------- /ex-communication/src/permrec.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( "fmt"; "strconv"; "flag") 4 | 5 | const ( 6 | _ = 1000 * iota 7 | ADD 8 | SUB 9 | MUL 10 | DIV 11 | MAXPOS = 11 12 | ) 13 | 14 | var mop = map[int]string{ADD: "+", SUB: "-", MUL: "*", DIV: "/"} 15 | var ( 16 | ok bool 17 | value int 18 | ) 19 | 20 | type Stack struct { 21 | i int 22 | data [MAXPOS]int 23 | } 24 | 25 | func (s *Stack) Reset() { s.i = 0 } 26 | func (s *Stack) Len() int { return s.i } 27 | func (s *Stack) Push(k int) { s.data[s.i] = k; s.i++ } 28 | func (s *Stack) Pop() int { s.i--; return s.data[s.i] } 29 | 30 | var found int 31 | var stack = new(Stack) 32 | 33 | func main() { 34 | flag.Parse() 35 | list := []int{1, 6, 7, 8, 8, 75, ADD, SUB, MUL, DIV} 36 | magic, ok := strconv.Atoi(flag.Arg(0)) // Arg0 is i 37 | if ok != nil { return } 38 | f := make([]int, MAXPOS) 39 | solve(f, list, 0, magic) 40 | } 41 | 42 | func solve(form, numberop []int, index, magic int) { 43 | var tmp int 44 | for i, v := range numberop { 45 | if v == 0 { goto NEXT } 46 | if v < ADD { // it's a number, save it 47 | tmp = numberop[i] 48 | numberop[i] = 0 49 | } 50 | form[index] = v 51 | value, ok = rpncalc(form[0 : index+1]) 52 | 53 | if ok && value == magic { 54 | if v < ADD { 55 | numberop[i] = tmp // reset and go on 56 | } 57 | found++ 58 | fmt.Printf("%s = %d #%d\n", rpnstr(form[0:index+1]), value, found) 59 | } 60 | 61 | if index == MAXPOS-1 { 62 | if v < ADD { 63 | numberop[i] = tmp // reset and go on 64 | } 65 | goto NEXT 66 | } 67 | solve(form, numberop, index+1, magic) 68 | if v < ADD { 69 | numberop[i] = tmp // reset and go on 70 | } 71 | NEXT: 72 | } 73 | } 74 | 75 | func rpnstr(r []int) (ret string) { // Convert rpn to infix notation 76 | s := make([]string, 0) // Still memory intensive 77 | for k, t := range r { 78 | switch t { 79 | case ADD, SUB, MUL, DIV: 80 | a, s := s[len(s)-1], s[:len(s)-1] 81 | b, s := s[len(s)-1], s[:len(s)-1] 82 | if k == len(r)-1 { 83 | s = append(s, b+mop[t]+a) 84 | } else { 85 | s = append(s, "("+b+mop[t]+a+")") 86 | } 87 | default: 88 | s = append(s, strconv.Itoa(t)) 89 | } 90 | } 91 | for _, v := range s { ret += v } 92 | return 93 | } 94 | 95 | func rpncalc(r []int) (int, bool) { 96 | stack.Reset() 97 | for _, t := range r { 98 | switch t { 99 | case ADD, SUB, MUL, DIV: 100 | if stack.Len() < 2 { return 0, false } 101 | a := stack.Pop() 102 | b := stack.Pop() 103 | if t == ADD { stack.Push(b + a) } 104 | if t == SUB { 105 | // disallow negative subresults 106 | if b-a < 0 { 107 | return 0, false 108 | } 109 | stack.Push(b - a) 110 | } 111 | if t == MUL { stack.Push(b * a) } 112 | if t == DIV { 113 | if a == 0 { 114 | return 0, false 115 | } 116 | // disallow fractions 117 | if b%a != 0 { 118 | return 0, false 119 | } 120 | stack.Push(b / a) 121 | } 122 | default: 123 | stack.Push(t) 124 | } 125 | } 126 | if stack.Len() == 1 { // there is only one! 127 | return stack.Pop(), true 128 | } 129 | return 0, false 130 | } 131 | -------------------------------------------------------------------------------- /README.mkd: -------------------------------------------------------------------------------- 1 | "Learning Go" is now available online. 2 | 3 | See and [this github repo](https://github.com/miekg/learninggo). 4 | 5 | Note this book's source has been rewritten in [mmark](https://mmark.nl) and *that* source is available at 6 | . 7 | 8 | > THIS REPO IS DEPRECATED. 9 | 10 | # `Learning Go` - a free PDF for learning the Go language. 11 | 12 | The book currently consists of the following chapters: 13 | 14 | 1. Introduction: Details the lineage of the language Go and shows the types, variables and control structures. 15 | 3. Functions: How to make and use functions. 16 | 4. Packages: Functions and data are grouped together in packages. Here you will see how to make your own package. How to unit test your package is also described. 17 | 5. Beyond the basics: Learn how to create your own data types and define functions on them (called methods in Go). 18 | 6. Interfaces: Go does not support Object Orientation in the traditional sense. In Go the central concept is interfaces. 19 | 7. Concurrency: With the go keyword functions can be started in separate routines (called goroutines). Communication with these goroutines is done via channels. 20 | 8. Communication : How to create/read/write from and to files. And how to do networking. 21 | 22 | Each chapter concludes with a number of exercises with answers to help you get some hands-on experience. Currently there are more than 30 exercises. 23 | 24 | * See http://www.golang.org for the homepage of Go. 25 | 26 | 27 | ## Building the book 28 | 29 | ### Package Prerequisites 30 | 31 | When building this book from LaTeX sources files you will need the following packages on Ubuntu (tested on 13.04). 32 | 33 | * `inkscape` 34 | * `gnumeric` 35 | * `ttf-droid` 36 | * `ttf-dejavu` 37 | * `ttf-sazanami-gothic` (Japanese font) 38 | * `ttf-arphic-ukai` 39 | * `texlive-fonts-recommended` 40 | * `texlive-extra-utils` 41 | * `texlive-xetex` 42 | * `texlive-latex-extra` 43 | * `texlive-latex-recommended` 44 | * `git-core` 45 | * `GNU make` 46 | 47 | 48 | 49 | ### Following is a shell script to automate the package prerequisites installation. 50 | 51 | You can copy and paste the following code to your vt100 session to kickoff the chains of many packages installation. 52 | ``` 53 | # tested on Ubuntu 13.04 54 | for i in inkscape \ 55 | gnumeric \ 56 | ttf-droid \ 57 | ttf-dejavu \ 58 | ttf-sazanami-gothic \ 59 | ttf-arphic-ukai \ 60 | texlive-fonts-recommended \ 61 | texlive-extra-utils \ 62 | texlive-xetex \ 63 | texlive-latex-extra \ 64 | texlive-latex-recommended \ 65 | latex-cjk-xcjk \ 66 | git-core \ 67 | make 68 | do 69 | sudo apt-get install $i -y 70 | done 71 | ``` 72 | 73 | ### Checking out the `Learning Go` LaTeX sources. 74 | 75 | Using http protocol. 76 | 77 | ``` 78 | me@ubuntu1204:~$git clone https://github.com/miekg/gobook.git 79 | Cloning into 'gobook'... 80 | remote: Counting objects: 4515, done. 81 | remote: Compressing objects: 100% (1385/1385), done. 82 | remote: Total 4515 (delta 3106), reused 4512 (delta 3104) 83 | Receiving objects: 100% (4515/4515), 1.53 MiB | 1.17 MiB/s, done. 84 | Resolving deltas: 100% (3106/3106), done. 85 | me@ubuntu1204:~$ 86 | ``` 87 | 88 | Using git protocol if you already have github account setup. 89 | 90 | ``` 91 | git clone git@github.com:tjyang/gobook.git 92 | ``` 93 | 94 | 95 | ### Make the `Learning Go` Book 96 | 97 | ``` 98 | make 99 | ``` 100 | 101 | ### Download the prebuilt `Learning Go` book 102 | 103 | Latest prebuilt pdf book [can be downloaded from http://www.miek.nl/downloads/Go/] [1] 104 | 105 | 106 | [1]: http://miek.nl/files/go/Learning-Go-latest.pdf "Download the prebuilt Learning Go book in PDF format" 107 | -------------------------------------------------------------------------------- /go-preface.tex: -------------------------------------------------------------------------------- 1 | \epi{``Is Go an object-oriented language? Yes and no.''} 2 | {\textit{Frequently asked questions}\\ \textsc{GO AUTHORS}} 3 | 4 | \section*{Audience} 5 | \noindent{}This is an introduction to the Go language from Google. Its aim 6 | is to provide a guide to this new and innovative language. 7 | 8 | This book assumes you already have Go installed on your system. 9 | 10 | The intended audience of this book is people who are familiar with programming 11 | and know some programming languages, be it C\cite{c}, C++\cite{c++}, 12 | Perl\cite{perl}, Java\cite{java}, Erlang\cite{erlang}, Scala\cite{scala} or 13 | Haskell\cite{haskell}. This is \emph{not} a book that teaches you how to 14 | program, this is a book that just teaches you how to use Go. 15 | 16 | As with 17 | learning new things, probably the best way to do this is to discover it for 18 | yourself by creating your own programs. 19 | Each chapter therefore includes a number of exercises (and answers) 20 | to acquaint you with the language. 21 | An exercise 22 | is numbered as \textbf{Q$n$}, where $n$ is a number. After the 23 | exercise number another number in parentheses displays the difficulty 24 | of this particular assignment. This difficulty ranges from 0 to 25 | 2: 26 | \begin{enumerate} 27 | \setcounter{enumi}{-1} 28 | \item easy; 29 | \item intermediate; 30 | \item difficult. 31 | \end{enumerate} 32 | 33 | Then a short name is given, for easier reference. 34 | For example: 35 | \begin{verse} 36 | \textbf{Q1}. (1) A map function \ldots 37 | \end{verse} 38 | introduces a question numbered \textbf{Q1} of a level 1 difficulty, concerning a 39 | \func{map()}-function. The answers are included after the exercises on a 40 | new page. 41 | The numbering and setup of the answers is identical to the 42 | exercises, except that an answer starts with \textbf{A$n$}, where the 43 | number $n$ corresponds with the number of the exercise. Some exercises 44 | don't have an answer; these are marked with an asterisk. 45 | 46 | \section*{Book layout} 47 | \begin{description} 48 | \item[Chapter \ref{chap:intro}: \titleref{chap:intro}] 49 | Describes the basic types, variables and control 50 | structures available in the language. 51 | 52 | \item[Chapter \ref{chap:functions}: \titleref{chap:functions}] 53 | In the third chapter we look at functions, the basic building blocks of Go programs. 54 | 55 | \item[Chapter \ref{chap:packages}: \titleref{chap:packages}] 56 | In chapter \ref{chap:packages} we see that functions and data can be grouped together 57 | in packages. You will also see how to document and test your packages. 58 | 59 | \item[Chapter \ref{chap:beyond}: \titleref{chap:beyond}] 60 | After that we look at creating your own types in chapter \ref{chap:beyond}. It also 61 | looks at allocation in Go. 62 | 63 | \item[Chapter \ref{chap:interfaces}: \titleref{chap:interfaces}] 64 | Go does not support object orientation in the traditional sense. 65 | In Go the central concept is interfaces. 66 | 67 | \item[Chapter \ref{chap:channels}: \titleref{chap:channels}] 68 | With the \func{go} keyword functions can be started in separate routines (called goroutines). 69 | Communication with those goroutines is done via channels. 70 | 71 | \item[Chapter \ref{chap:communication}: \titleref{chap:communication}] 72 | In the last chapter we show how to interface with the rest of the world from within 73 | a Go program. How to create files and read and write from and to them. We also briefly 74 | look into networking. 75 | \end{description} 76 | 77 | I hope you will enjoy this book and the language Go. 78 | 79 | \section*{Translations} 80 | The content of this book is freely available. This has already led to translations: 81 | \begin{itemize} 82 | \item{Chinese translation by Xing Xing, 这里是中文译本: 83 | {\url{http://www.mikespook.com/learning-go/}} .} 84 | \end{itemize} 85 | 86 | \begin{flushright} 87 | Miek Gieben, 2011, 2012 -- \url{miek@miek.nl} 88 | \end{flushright} 89 | -------------------------------------------------------------------------------- /creative_commons/cc_by_30.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 20 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 56 | 59 | 69 | 70 | 72 | 75 | 76 | 85 | 86 | 87 | 88 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /creative_commons/cc_nd_30.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 20 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 56 | 59 | 60 | 69 | 70 | 73 | 76 | 77 | 79 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /ex-functions/ex-stack.tex: -------------------------------------------------------------------------------- 1 | \begin{Exercise}[title={Stack},difficulty=1] 2 | \label{ex:stack} 3 | \Question \label{ex:stack q1} Create a simple stack which can hold a 4 | fixed number of ints. It does not have to grow beyond this limit. 5 | Define \func{push} -- put something on the stack -- and \func{pop} 6 | -- retrieve something from the stack -- functions. The stack should be 7 | a LIFO (last in, first out) stack. 8 | 9 | \begin{figure}[H] 10 | \caption{A simple LIFO stack} 11 | \label{fig:stack} 12 | \begin{center} 13 | \includegraphics[scale=0.65]{fig/stack.pdf} 14 | \end{center} 15 | \end{figure} 16 | 17 | \Question \label{ex:stack q2} Bonus. Write a \func{String} method which 18 | converts the stack to a string representation. This way you can print the stack using: 19 | \lstinline{fmt.Printf("My stack %v\n", stack)} 20 | 21 | \noindent{}The stack in the figure could be represented as: 22 | \texttt{[0:m] [1:l] [2:k]} 23 | 24 | \end{Exercise} 25 | 26 | \begin{Answer} 27 | 28 | \Question 29 | %%\subsection*{Define our type} maybe nice to do this 30 | First we define a new type that represents a stack; we need an 31 | array (to hold the keys) and an index, which points to the last element. 32 | Our small stack can only hold 10 elements. 33 | 34 | \begin{lstlisting} 35 | type stack struct { |\coderemark{\emph{stack} is not exported}| 36 | i int 37 | data [10]int 38 | } 39 | \end{lstlisting} 40 | 41 | Next we need the \func{push} and \func{pop} functions to actually 42 | use the thing. \emph{First we show the \emph{wrong}{} solution!} 43 | In Go data passed to functions is \emph{passed-by-value} meaning a copy 44 | is created and given to the function. The first stab for the function 45 | \func{push} could be: 46 | 47 | \begin{lstlisting} 48 | func (s stack) push(k int) { |\coderemark{Works on copy of argument}| 49 | if s.i+1 > 9 { 50 | return 51 | } 52 | s.data[s.i] = k 53 | s.i++ 54 | } 55 | \end{lstlisting} 56 | The function works on the \var{s} which is of the type \type{stack}. To 57 | use this we just call \lstinline{s.push(50)}, to push the integer 50 on 58 | the stack. But the push function gets a copy of \var{s}, so it is 59 | \emph{not} working the \emph{real} thing. Nothing gets pushed to our 60 | stack this way, for example the following code: 61 | 62 | \begin{lstlisting} 63 | var s stack |\coderemark{make \var{s} a simple \type{stack} variable}| 64 | s.push(25) 65 | fmt.Printf("stack %v\n", s); 66 | s.push(14) 67 | fmt.Printf("stack %v\n", s); 68 | \end{lstlisting} 69 | prints: 70 | \vskip\baselineskip 71 | \begin{display} 72 | stack [0:0] 73 | stack [0:0] 74 | \end{display} 75 | \vskip\baselineskip 76 | 77 | To solve this we need to give the function \func{push} a pointer 78 | to the stack. This means we need to change \func{push} from 79 | 80 | \lstinline{func (s stack) push(k int)} 81 | $\rightarrow$ 82 | \lstinline{func (s *stack) push(k int)} 83 | 84 | We should now use \func{new()} (see ``\titleref{sec:allocation with new}'' 85 | in chapter \ref{chap:beyond}) to create a \emph{pointer} to a newly 86 | allocated \type{stack}, so line 1 from the example above needs to be 87 | \lstinline{s := new(stack)} 88 | 89 | \noindent{}And our two functions become: 90 | \begin{lstlisting} 91 | func (s *stack) push(k int) { 92 | s.data[s.i] = k 93 | s.i++ 94 | } 95 | 96 | func (s *stack) pop() int { 97 | s.i-- 98 | return s.data[s.i] 99 | } 100 | \end{lstlisting} 101 | Which we then use as follows 102 | \begin{lstlisting} 103 | func main() { 104 | var s stack 105 | s.push(25) 106 | s.push(14) 107 | fmt.Printf("stack %v\n", s) 108 | } 109 | \end{lstlisting} 110 | 111 | \Question While this was a bonus question, having the ability to print 112 | the stack was very valuable when writing the code for this exercise. 113 | According to the Go documentation \lstinline{fmt.Printf("%v")} can 114 | print any value (\%v) that satisfies the \func{Stringer} interface. 115 | For this to work we only need to define a \func{String()} function for 116 | our type: 117 | \begin{lstlisting}[caption=stack.String()] 118 | func (s stack) String() string { 119 | var str string 120 | for i := 0; i <= s.i; i++ { 121 | str = str + "[" + 122 | strconv.Itoa(i) + ":" + strconv.Itoa(s.data[i]) + "]" 123 | } 124 | return str 125 | } 126 | \end{lstlisting} 127 | \end{Answer} 128 | -------------------------------------------------------------------------------- /creative_commons/cc_sa_30.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 20 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 56 | 59 | 60 | 69 | 70 | 73 | 76 | 77 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /go_a4.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper,twoside,openleft]{blocksbook} 2 | \usepackage{fontspec}% provides font selecting commands 3 | \usepackage{xunicode}% provides unicode character macros 4 | \usepackage{xltxtra} % provides some fixes/extras 5 | \usepackage[answerdelayed,lastexercise]{exercise} 6 | \usepackage[labelsep=period,labelfont=it,textfont=it]{caption} 7 | \usepackage{alltt} 8 | \usepackage{url} 9 | \usepackage{listings} 10 | \usepackage{color} 11 | \usepackage{graphicx} 12 | \usepackage{relsize} 13 | \usepackage[boldfont,slantfont]{xeCJK} 14 | \usepackage{scalefnt} 15 | \usepackage{wrapfig} 16 | \usepackage{everypage} 17 | % Tables from Gnumeric. 18 | \usepackage{array} 19 | \usepackage{longtable} 20 | \usepackage{calc} 21 | \usepackage{multirow} 22 | \usepackage{hhline} 23 | \usepackage{ifthen} 24 | \usepackage{upquote} 25 | 26 | \usepackage{tikz} 27 | \usetikzlibrary{arrows,decorations.pathreplacing} 28 | \usepackage{float} 29 | %\usepackage{natbib} 30 | %% Local tex stuff. 31 | \usepackage{coderemarks} 32 | %% Must go last. 33 | \usepackage{hyperref} 34 | \input{go-setup.tex} 35 | \input{go-cc-license.tex} 36 | 37 | \begin{document} 38 | \thispagestyle{empty} 39 | \newcommand{\version}{1.0} 40 | \strictpagecheck 41 | 42 | %% Title page. 43 | \begin{center} 44 | \hspace{1.0cm}{\scalefont{6.00}{\sffamily{\mbox{\vspace{1.0cm}Learning Go}}}}\\ 45 | \end{center} 46 | \vspace*{2cm} 47 | \begin{figure}[h!] 48 | \begin{center} 49 | \includegraphics[scale=0.65]{fig/bumper-inverse.png} 50 | \end{center} 51 | \end{figure} 52 | \vspace*{0.02\stockheight} 53 | \begin{minipage}{0.4\textwidth} 54 | \begin{flushleft} \large 55 | \hspace*{2,0cm}Author:\\ 56 | \hspace*{2.0cm}\emph{Miek Gieben}\\ 57 | \vfill 58 | \end{flushleft} 59 | \end{minipage} 60 | \hspace{5mm} 61 | \begin{minipage}{0.4\textwidth} 62 | \begin{flushright} \large 63 | Thanks to:\\ 64 | \emph{Go Authors}, \emph{Google}\\ 65 | \vfill 66 | \end{flushright} 67 | \end{minipage} 68 | \vspace*{0.5cm} 69 | \begin{center} 70 | With the help and contributions from: 71 | 72 | ({\small in alphabetical order}) 73 | 74 | \input{go-contributors.tex} 75 | 76 | And with minor contributions from: 77 | 78 | \input{go-nits-contributors.tex} 79 | \end{center} 80 | 81 | 82 | \vfill 83 | \begin{center} 84 | \hspace*{1cm}\CcGroupByNcSa{0.83}{0.95ex}\\[2.5ex] 85 | \hspace*{1cm}{\tiny\CcNote{\CcLongnameByNcSa}} 86 | \end{center} 87 | \begin{center} 88 | \hspace*{1cm}\emph{Miek Gieben -- \copyright 2010 - 2012} 89 | \end{center} 90 | \vspace{-3em} 91 | %% End title page. 92 | 93 | \newpage 94 | 95 | \thispagestyle{empty} 96 | \begin{figure}[H] 97 | \emph{ 98 | This work is licensed under the Attribution-NonCommercial-ShareAlike 3.0 Unported License. To 99 | view a copy of this license, visit \url{http://creativecommons.org/licenses/by-nc-sa/3.0/} 100 | or send a letter 101 | to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.} 102 | \vspace{2em} 103 | 104 | \emph{All example code used in this book is hereby put in the public domain.} 105 | \end{figure} 106 | 107 | ``Learning Go'' has been translated into: 108 | \begin{itemize} 109 | \item Chinese, by Xing Xing, 这里是中文译本: {\url{http://www.mikespook.com/learning-go/}} 110 | \end{itemize} 111 | 112 | \begin{center} 113 | \vfill 114 | \emph{Learning as we Go} 115 | (\emph{\version}) 116 | 117 | \tiny{Supports the Go 1.1 release} 118 | \vspace{.2\stockheight} 119 | \end{center} 120 | 121 | \clearpage 122 | 123 | \pagenumbering{roman} 124 | \tableofcontents* 125 | \listofex* 126 | \clearpage 127 | 128 | \chapter*{Preface} 129 | \label{chap:preface} 130 | \input{go-preface.tex} 131 | 132 | \pagenumbering{arabic} 133 | %% renamed from Basics 134 | \chapter{Introduction} 135 | \label{chap:intro} 136 | \input{go-basics.tex} 137 | 138 | \chapter{Functions} 139 | \label{chap:functions} 140 | \input{go-functions.tex} 141 | 142 | \chapter{Packages} 143 | \label{chap:packages} 144 | \input{go-packages.tex} 145 | 146 | \chapter{Beyond the basics} 147 | \label{chap:beyond} 148 | \input{go-beyond.tex} 149 | 150 | \chapter{Interfaces} 151 | \label{chap:interfaces} 152 | \input{go-interfaces.tex} 153 | 154 | \chapter{Concurrency} 155 | \label{chap:channels} 156 | \input{go-channels.tex} 157 | 158 | \chapter{Communication} 159 | \label{chap:communication} 160 | \input{go-communication.tex} 161 | 162 | \appendix 163 | 164 | \chapter{Colophon} 165 | \input{go-colophon} 166 | 167 | \begin{twocolumn} 168 | \chapter{Index} 169 | \printindex 170 | \end{twocolumn} 171 | \begin{onecolumn} 172 | 173 | \bibliographystyle{plain} 174 | \bibliography{go} 175 | \newpage 176 | \thispagestyle{empty} 177 | \begin{center} 178 | \emph{This page is intentionally left blank.} 179 | \end{center} 180 | \end{onecolumn} 181 | \end{document} 182 | -------------------------------------------------------------------------------- /creative_commons/cc_nc_30.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 20 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 56 | 59 | 60 | 69 | 70 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /creative_commons/cc_dev_nations_30.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 20 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 56 | 59 | 60 | 69 | 70 | 73 | 74 | 77 | 78 | 81 | 82 | 85 | 86 | 89 | 90 | 93 | 94 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /creative_commons/cc_pd_30.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 20 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 56 | 59 | 60 | 69 | 70 | 73 | 77 | 78 | 80 | 84 | 85 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /creative_commons/cc_cc_30.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 20 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 58 | 61 | 70 | 73 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /go-setup.tex: -------------------------------------------------------------------------------- 1 | \setmonofont[Path=fonts/,Scale=0.90,BoldFont={SourceCodePro-Bold}]{SourceCodePro-Regular} 2 | %% Fontfeatures after setting the mono font to keep 3 | %% lstlisting fonts happy 4 | %%\defaultfontfeatures{Scale=MatchLowercase,Mapping=tex-text} 5 | \defaultfontfeatures{Mapping=tex-text} 6 | \setmainfont[Path=fonts/,ItalicFont={PTS56F},BoldFont={PTS75F}]{PTS55F} 7 | \def\inputGnumericTable{} 8 | 9 | \setulmarginsandblock{2.5cm}{2.5cm}{*} 10 | \checkandfixthelayout 11 | \setlength{\textwidth}{1.1\textwidth} 12 | \setlength{\parindent}{0pt} 13 | \setlength{\parskip}{0.7ex plus 0.5ex minus 0.2ex} 14 | 15 | %% list of answers 16 | \newlistof{listofex}{ex}{List of Exercises} 17 | \newlistentry{exercise}{ex}{0} 18 | 19 | \renewcommand{\tocheadstart}{} 20 | \renewcommand{\aftertoctitle}{\pagestyle{blocks}} 21 | \renewcommand{\aftertoctitle}{\thispagestyle{empty}\afterchaptertitle\pagestyle{blocks}} 22 | 23 | %%\renewcommand{\printtoctitle}[1]{} 24 | \renewcommand{\contentsname}{Contents} 25 | \renewcommand{\tocmark}{\markboth{\myfamily \typename: \contentsname}{\myfamily \contentsname}} 26 | %% new print the titles as section not as chapter, that explains 27 | %% why the page is headerless. the page style is empty 28 | %% lof 29 | \renewcommand{\lofheadstart}{} 30 | \renewcommand{\afterloftitle}{\thispagestyle{blocks}} 31 | \renewcommand{\printloftitle}[1]{\section*{#1}} 32 | \renewcommand{\lotmark}{\markboth{\myfamily \typename: 33 | \contentsname}{\myfamily \listfigurename}} 34 | %% lot 35 | \renewcommand{\lotheadstart}{} 36 | \renewcommand{\afterlottitle}{\thispagestyle{blocks}} 37 | \renewcommand{\printlottitle}[1]{\section*{#1}} 38 | \renewcommand{\lofmark}{\markboth{\myfamily \typename: 39 | \contentsname}{\myfamily \listtablename}} 40 | %% ex 41 | \renewcommand{\exheadstart}{} 42 | \renewcommand{\afterextitle}{\thispagestyle{blocks}} 43 | \renewcommand{\printextitle}[1]{\section*{#1}} 44 | \renewcommand{\exmark}{\markboth{\myfamily \typename: \contentsname}{\myfamily List of Exercises}} 45 | 46 | \nobibintoc 47 | \renewcommand*{\indexmark}{% 48 | \markboth{\myfamily \typename{} \thechapter: \indexname}{\myfamily\indexname}% 49 | } 50 | 51 | \onecolindexfalse %% doesn't do its things as advertised 52 | \noindexintoc 53 | \makeindex 54 | 55 | %% make quote print italics 56 | \newcommand{\qquote}{{\scalefont{4.00}{``}}} 57 | \expandafter\def\expandafter\quote\expandafter{\quote\em} 58 | 59 | %% Listings 60 | \newfontfamily\listingsfont[Path=fonts/,Scale=0.90,BoldFont={SourceCodePro-Bold}]{SourceCodePro-Regular} 61 | 62 | \lstdefinelanguage{Go} 63 | {morekeywords={append,break,cap,case,chan,const,continue,copy,default,defer,else,fallthrough,% 64 | for,func,go,goto,if,import,interface,len,make,map,new,package,range,return,select,% 65 | struct,switch,type,var,% % types 66 | uint8,uint16,uint32,uint64,int8,int16,int32,int64,float32,float64,byte,% 67 | complex,complex128,complex64,% 68 | int,rune,uint,bool,uintptr,string,% 69 | error,iota,% 70 | },% 71 | otherkeywords={<-,!,;,\{,\}},% %% nog beter maken 72 | sensitive=true,% 73 | morecomment=[l]{//},% 74 | morecomment=[s]{/*}{*/},% 75 | morecomment=[n]{(*}{*)},% 76 | morestring=[b]",% 77 | morestring=[b]',% 78 | morestring=[b]`,% 79 | }[]% 80 | \lstset{language=Go,inputencoding=utf8,extendedchars=false,texcl,escapechar=\|,basicstyle=\ttfamily,keywordstyle=\bfseries,numbers=none,numberblanklines=false,showstringspaces=false,breaklines=true,numberstyle=\small\ttfamily,xleftmargin=\parindent,xrightmargin=1em,linewidth=0.98\linewidth} 81 | %,literate={"}{\textasciiquote}{1}} 82 | 83 | \newcommand{\coderemark}[1]{\sffamily\normalfont\qquad$\leftarrow \textit{\footnotesize #1}$} 84 | 85 | %% Cite style 86 | %%\bibpunct{[}{]}{;}{s}{,}{,} 87 | 88 | %% Exercises 89 | \renewcommand{\ExerciseHeaderTitle}{\ExerciseTitle} 90 | \renewcommand{\ExerciseHeaderLabel}{} 91 | \renewcommand{\ExerciseName}{} %% was 'Exercise' 92 | \renewcommand{\ExerciseHeaderNB}{\theExercise} 93 | %% This one is actually used 94 | \renewcommand{\ExerciseHeader}{\vspace{.7ex}\noindent\textbf{Q\theExercise}. (\number\ExerciseDifficulty) \ExerciseTitle\quad% 95 | \addcontentsline{ex}{exercise}{\numberline{\theExercise}(\number\ExerciseDifficulty) \ExerciseTitle}} 96 | \renewcommand{\AnswerHeader}{\vspace{.7ex}\noindent\textbf{A\theExercise}. (\number\ExerciseDifficulty) \ExerciseTitle\quad} 97 | 98 | %% Style commands 99 | \newcommand{\func}[1]{\texttt{#1}} 100 | \newcommand{\key}[1]{\texttt{#1}} 101 | \newcommand{\type}[1]{\texttt{#1}} 102 | \newcommand{\prog}[1]{\texttt{#1}} 103 | \newcommand{\flag}[1]{\textit{#1}} 104 | \newcommand{\dir}[1]{\texttt{#1}} 105 | \newcommand{\file}[1]{\texttt{#1}} 106 | \newcommand{\var}[1]{\texttt{#1}} 107 | \newcommand{\rem}[1]{\texttt{\textit{#1}}} 108 | \newcommand{\package}[1]{{\textit{#1}}} 109 | \newcommand{\first}[2]{#1\index{#2}} 110 | \newcommand{\error}[1]{\texttt{#1}} 111 | \newcommand{\pr}{\%} %% a prompt (also bold) 112 | \newcommand{\user}[1]{\textbf{#1}} %% text a user should type 113 | \newcommand{\userinput}[1]{\textit{#1}} %% text a user should choose 114 | \newcommand{\gorelease}[1]{\texttt{#1}} 115 | 116 | %% Footnotes 117 | \renewcommand*{\thefootnote}{\textbf{\emph\alph{footnote}}} 118 | 119 | %% Epigraph 120 | \newcommand{\epi}[2]{\epigraph{#1}{#2}} 121 | \setlength{\epigraphwidth}{1.2\epigraphwidth} 122 | 123 | %% Margin notes 124 | \setmarginnotes{0.04\stockwidth}{0.12\stockwidth}{\onelineskip} 125 | \newcommand{\gomarginpar}[1]{% 126 | \marginpar{\itshape\small#1}} 127 | %% typeset text in margin and index arg 2 128 | \newcommand{\gomarginindex}[2]{\gomarginpar{#1}\index{#2}} 129 | \newcommand{\gopher}{% 130 | \begin{figure}[H]% 131 | \includegraphics[scale=0.20, width=.70\marginparwidth]{fig/gopher.png}% 132 | \end{figure}% 133 | } 134 | 135 | \setCJKmainfont{AR PL UKai CN} 136 | 137 | \newcommand{\ubrace}[3]{% 138 | \draw [thick,decorate,decoration={brace,amplitude=4pt},xshift=0pt,yshift=0pt] % 139 | (#1) -- (#2) node [black,midway,below=4pt,xshift=0pt] % 140 | {\longremark{#3}}; % 141 | } 142 | 143 | %% fixes 144 | \newcommand{\exdisfix}{\vspace{1ex}} 145 | -------------------------------------------------------------------------------- /creative_commons/cc_sampling_30.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 20 | 41 | 43 | 44 | 46 | image/svg+xml 47 | 49 | 50 | 51 | 52 | 57 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /creative_commons/cc_sampling_plus_30.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 18 | 20 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 56 | 59 | 60 | 69 | 70 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /blocksbook.cls: -------------------------------------------------------------------------------- 1 | \NeedsTeXFormat{LaTeX2e}[1995/12/01] 2 | \ProvidesClass{blocksbook}[2006/06/10 v0.1 3 | Layout with blocks] 4 | \RequirePackage{ifthen} 5 | \RequirePackage{scalefnt} 6 | 7 | \newenvironment{display}{\def\FrameCommand{\hskip\parindent}%% 8 | \MakeFramed{\advance\hsize-\width\FrameRestore}%% 9 | \vspace*{-2ex}\small\begin{alltt}}% 10 | {\end{alltt}\vspace*{-2ex}\endMakeFramed} 11 | 12 | \newenvironment{lbar}[1][]{% 13 | \def\FrameCommand{\rightskip=\parindent\hskip\parindent\vrule width 1pt \hspace{10pt}}% 14 | \MakeFramed{\rightskip=\parindent\advance\hsize-\width\FrameRestore\noindent\hskip-0.6ex}% 15 | {% 16 | \ifthenelse{\equal{#1}{}}{}{\hskip0.6ex\normalfont\myfamily\myheadseries{#1}\\\\}}% 17 | }% 18 | {\endMakeFramed} 19 | 20 | %% supported options: 21 | %% draft - place DRAFT in the left hand side and give to memoir 22 | %% serif - don't use sans serif fonts 23 | %% headbold - display the head also in bold 24 | %% bold - use also bold in description, etc 25 | 26 | %% Class Options Defaults 27 | \newcommand{\headplaceholder}{} 28 | \newcommand{\myheadplaceholder}{} 29 | \newcommand{\myfamily}{\sffamily} 30 | \newcommand{\myseries}{\bfseries} 31 | \newcommand{\myheadseries}{} 32 | \newcommand{\mytitlepage}{} 33 | \newcounter{bottomline} 34 | 35 | \newcommand{\typename}{} 36 | \newlength{\gnat} 37 | 38 | \DeclareOption{draft}{ 39 | \renewcommand{\myheadplaceholder} 40 | {\myfamily\bfseries\headplaceholder{}\normalfont\scshape{} draft} 41 | \PassOptionsToClass{draft}{memoir} 42 | } 43 | \DeclareOption{serif}{ 44 | \renewcommand{\myfamily}{\rmfamily} 45 | } 46 | \DeclareOption{headbold}{ 47 | \renewcommand{\myheadseries}{\bfseries} 48 | } 49 | \DeclareOption{bold}{ 50 | \renewcommand{\myheadseries}{\myseries} 51 | } 52 | \DeclareOption{bottomline}{ 53 | \setcounter{bottomline}{1} 54 | } 55 | 56 | \DeclareOption{titlepagenr}{ 57 | \renewcommand{\mytitlepage}{ 58 | \addtolength{\fboxsep}{0.5ex} 59 | \framebox{\myfamily\thepage} 60 | } 61 | } 62 | 63 | %% Pass all unknown options to memoir 64 | \DeclareOption*{\PassOptionsToClass{\CurrentOption}{memoir}} 65 | \ProcessOptions 66 | \LoadClass{memoir} 67 | 68 | \setsecnumdepth{chapter} %% nice :-) 69 | 70 | \makepagestyle{blocks} 71 | \aliaspagestyle{chapter}{empty} 72 | \aliaspagestyle{part}{empty} 73 | \setlength{\headwidth}{\textwidth} 74 | \addtolength{\headwidth}{\marginparsep} 75 | \addtolength{\headwidth}{\marginparwidth} 76 | 77 | \makepsmarks{blocks}{ 78 | \let\@mkboth\markboth 79 | \def\chaptermark##1{\markboth{\myfamily \typename{} \thechapter: ##1}{\myfamily##1}} %% left & right marks 80 | \def\sectionmark##1{\markright{ %% right mark 81 | \ifnum \c@secnumdepth>\z@ 82 | \normalfont\myfamily\myheadseries\thesection{ } 83 | \fi 84 | \normalfont\myheadseries\myfamily##1}} 85 | } 86 | 87 | \makerunningwidth{blocks}{\headwidth} 88 | \makeevenhead{blocks}{ 89 | \addtolength{\fboxsep}{0.5ex} 90 | \hspace{-0.35cm} 91 | \framebox{\myfamily\thepage} 92 | % hack to get spacing correct 93 | \vspace{-0.1mm} 94 | \hrule 95 | }{ 96 | \raisebox{0.2ex}{\parbox{\headwidth}{ 97 | \settowidth{\gnat}{\thepage} 98 | \hspace{\gnat} 99 | \hspace{1em} 100 | { }\normalfont\leftmark % 101 | \vspace{1.1mm} 102 | }} 103 | }{\myheadplaceholder} 104 | 105 | \makeoddhead{blocks}{\myheadplaceholder} 106 | { 107 | \raisebox{0.2ex}{\parbox{\headwidth}{ 108 | \raggedleft 109 | \normalfont\rightmark % 110 | \hspace{1.2em} 111 | \settowidth{\gnat}{\thepage} 112 | \hspace{\gnat} 113 | \vspace{1.1mm} 114 | } } 115 | } 116 | { 117 | \addtolength{\fboxsep}{0.5ex} 118 | \framebox{\myfamily{\thepage}} 119 | %% hack to get spacing correct 120 | \vspace{-0.14mm} 121 | \hspace{-1.2mm} 122 | \hrule 123 | %% \rule{\linewidth}{0.1mm} 124 | } 125 | \ifthenelse{\value{bottomline} = 1}% 126 | {\makefootrule{blocks}{\headwidth}{\normalrulethickness}{\footruleskip}}% 127 | {} 128 | %% centreert de header wat meer als ik dit uit zet, anders wordt ie 129 | %% echt breed 130 | %%\makeheadposition{blocks}{flushright}{flushleft}{flushright}{flushleft} 131 | \addtolength{\headsep}{\headsep} 132 | 133 | %% chapter style 134 | \makechapterstyle{blocks}{% 135 | \renewcommand{\chapterheadstart}{\vspace*{-5em}} 136 | \renewcommand{\printchaptername}{} 137 | \renewcommand{\typename}{\chaptername} 138 | \renewcommand{\chapternamenum}{} 139 | %% \renewcommand{\printchapternonum}{% 140 | %% \addtolength{\fboxsep}{2ex} 141 | %% \framebox{\myseries\myfamily\scalefont{6.0}{*}} 142 | %% \afterchapternum 143 | %%} 144 | \renewcommand{\printchapternum}{% 145 | \addtolength{\fboxsep}{2ex} %% \numtoName 146 | \framebox{\myseries\myfamily\scalefont{6.0}{\thechapter}} 147 | } 148 | \renewcommand{\afterchapternum}{\hskip 5mm} 149 | \renewcommand{\printchaptertitle}[1]{% 150 | \normalfont\raggedright\HUGE{{\myfamily##1}}% 151 | \chaptermark{\myfamily##1}% 152 | } 153 | \renewcommand{\afterchaptertitle}{% 154 | \vskip\onelineskip \vskip\onelineskip} 155 | } 156 | % appendix style 157 | \addtodef{\appendix}{}{\renewcommand{\typename}{\appendixname}} 158 | 159 | %% part style 160 | \makepagestyle{part} 161 | \renewcommand{\partname}{} 162 | \renewcommand{\partnumfont}{\myseries\myfamily} 163 | \renewcommand{\parttitlefont}{\myseries\myfamily} 164 | \renewcommand{\printparttitle}[1]{\vspace{10ex}\parttitlefont\scalefont{3.0}{#1}} 165 | \renewcommand{\printpartnum}{% 166 | \raggedright 167 | \addtolength{\fboxsep}{5ex} 168 | \framebox{\partnumfont\scalefont{6.0}{\thepart}} 169 | } 170 | 171 | %% bibliography style 172 | \renewcommand{\bibsection}{% 173 | \chapter{\bibname} 174 | \bibmark 175 | \ifnobibintoc\else 176 | \phantomsection 177 | \addcontentsline{toc}{chapter}{\bibname} 178 | \fi 179 | \prebibhook 180 | \markboth{\myfamily \typename{} \thechapter: \bibname}{\myfamily\bibname} 181 | } 182 | 183 | %% index style 184 | \makeatletter 185 | \renewenvironment{theindex}{% 186 | \if@twocolumn 187 | \@restonecolfalse 188 | \else 189 | \@restonecoltrue 190 | \fi 191 | \ifonecolindex 192 | \onecolumn 193 | \chapter*{\indexname} 194 | \preindexhook 195 | \else 196 | \setlength{\columnseprule}{\indexrule}% 197 | \setlength{\columnsep}{\indexcolsep}% 198 | %% \twocolumn[\@makeschapterhead{\indexname} %% disabled 199 | %% \preindexhook]% 200 | \fi 201 | \indexmark 202 | \ifnoindexintoc\else 203 | \phantomsection 204 | \addcontentsline{toc}{chapter}{\indexname}% 205 | \fi 206 | \thispagestyle{chapter}\parindent\z@ 207 | \parskip\z@ \@plus .3\p@\relax 208 | \let\item\@idxitem}% 209 | {\if@restonecol\onecolumn\else\twocolumn\fi} 210 | \makeatother 211 | 212 | %% title page style - always odd... XXX 213 | \makepagestyle{tblocks} 214 | \makeoddfoot{tblocks}{}{\mytitlepage}{} 215 | 216 | %% section style 217 | \setsecheadstyle{\raggedright\myfamily\LARGE} 218 | \setbeforesecskip{-\onelineskip} 219 | \setaftersecskip{\onelineskip} 220 | 221 | %% subsection 222 | \setsubsecheadstyle{\sethangfrom{\noindent ##1}\raggedright\myfamily\slshape} 223 | %%\setsubsecheadstyle{\raggedleft\myfamily\thesubsection\raggedright\myfamily\hskip 1em} 224 | \setbeforesubsecskip{-\onelineskip} 225 | \setaftersubsecskip{\onelineskip} 226 | 227 | %% subsubsection 228 | \setsubsubsecheadstyle{\sethangfrom{\noindent ##1}\raggedright\myfamily\slshape} 229 | \setbeforesubsubsecskip{-\onelineskip} 230 | \setaftersubsubsecskip{\onelineskip} 231 | 232 | %% paragraph 233 | \setparaheadstyle{\sethangfrom{\noindent ##1}\raggedright\myfamily\slshape} 234 | 235 | %% description 236 | \renewcommand*{\descriptionlabel}[1]{\hspace\labelsep 237 | \normalfont\rmfamily\textit{#1}\hskip\textwidth} 238 | 239 | %% tableofcontents 240 | \renewcommand{\cftpartfont}{\myfamily\myseries} 241 | \renewcommand{\cftchapterfont}{\myfamily\myseries} 242 | 243 | %% set the options for the document 244 | \captiontitlefont{\small\myfamily} %% small? TODO 245 | \captionnamefont{\myfamily} 246 | \pagestyle{blocks} 247 | \chapterstyle{blocks} 248 | \aliaspagestyle{title}{tblocks} 249 | -------------------------------------------------------------------------------- /go-communication.tex: -------------------------------------------------------------------------------- 1 | \epi{``Good communication is as stimulating as black coffee, and just as hard 2 | to sleep after.''}{\textsc{ANNE MORROW LINDBERGH}} 3 | \noindent{}In this chapter we are going to look at the building blocks in Go for 4 | communicating with the outside world. We will look at files, directories, networking 5 | and executing other programs. Central to Go's I/O are the interfaces \type{io.Reader} 6 | and \type{io.Writer}. 7 | 8 | Reading from (and writing to) files is easy in Go. This program 9 | only uses the \package{os} package to read data from the file \file{/etc/passwd}. 10 | \lstinputlisting[caption=Reading from a file (unbuffered),label=src:read]{src/file.go} 11 | The following is happening here: 12 | \showremarks 13 | If you want to use \first{buffered}{buffered} IO there is the 14 | \package{bufio}\index{package!bufio} package: 15 | \lstinputlisting[caption=Reading from a file (buffered),label=src:bufread]{src/buffile.go} 16 | \showremarks 17 | 18 | \section{io.Reader} 19 | As mentioned above the \first{io.Reader}{io.Reader} is an important interface in the language Go. A lot 20 | (if not all) functions that need to read from something take an \type{io.Reader}\index{package!io} 21 | as input. To fulfill the interface a type needs to implement only one method: \func{Read(p []byte) (n 22 | int, err error)}. The writing side is (you may have guessed) an \type{io.Writer}, which has 23 | the \func{Write} method. 24 | 25 | If you think of a new type in your program or package and you make it fulfill the \type{io.Reader} 26 | or \type{io.Writer} interface, \emph{the whole standard Go library can be used} on that type! 27 | 28 | \section{Some examples} 29 | The previous program reads a file in its entirety, but a more common scenario is that 30 | you want to read a file on a line-by-line basis. The following snippet shows a way 31 | to do just that: 32 | 33 | \begin{lstlisting} 34 | f, _ := os.Open("/etc/passwd"); defer f.Close() 35 | r := bufio.NewReader(f) |\coderemark{Make it a bufio to access the ReadString method}| 36 | s, ok := r.ReadString('\n') |\coderemark{Read a line from the input}| 37 | // ... \coderemark{\var{s} holds the string, with the \package{strings} package you can parse it} 38 | \end{lstlisting} 39 | 40 | A more robust method (but slightly more complicated) is \func{ReadLine}, see the documentation 41 | of the \package{bufio} package. 42 | 43 | A common scenario in shell scripting is that you want to check if a directory 44 | exists and if not, create one. 45 | 46 | \begin{minipage}{.5\textwidth} 47 | \begin{lstlisting}[language=sh,caption={Create a directory with the shell}] 48 | if [ ! -e name ]; then 49 | mkdir name 50 | else 51 | # error 52 | fi 53 | \end{lstlisting} 54 | \end{minipage} 55 | \hspace{1em} 56 | \begin{minipage}{.5\textwidth} 57 | \begin{lstlisting}[caption={Create a directory with Go}] 58 | if f, e := os.Stat("name"); e != nil { 59 | os.Mkdir("name", 0755) 60 | } else { 61 | // error 62 | } 63 | \end{lstlisting} 64 | \end{minipage} 65 | The similarity between these two examples have prompted comments that Go has a 66 | ``script''-like feel to it, i.e. programming in Go can be compared to programming in 67 | an interpreted language (Python, Ruby, Perl or PHP). 68 | 69 | \section{Command line arguments} 70 | \label{sec:option parsing} 71 | Arguments from the command line are available inside your program via 72 | the string slice \var{os.Args}, provided you have imported the package 73 | \package{os}. The \package{flag} package has a more sophisticated 74 | interface, and also provides a way to parse flags. Take this example 75 | from a DNS query tool: 76 | \begin{lstlisting} 77 | dnssec := flag.Bool("dnssec", false, "Request DNSSEC records") |\longremark{Define a \texttt{bool} flag, %% 78 | \texttt{-dnssec}. The variable must be a pointer otherwise the package can not set its value;}| 79 | port := flag.String("port", "53", "Set the query port") |\longremark{Idem, but for a \texttt{port} option;}| 80 | flag.Usage = func() { |\longremark{Slightly redefine the \func{Usage} function, to be a little more verbose;}| 81 | fmt.Fprintf(os.Stderr, "Usage: %s [OPTIONS] [name ...]\n", os.Args[0]) 82 | flag.PrintDefaults() |\longremark{For every flag given, \func{PrintDefaults} will output the help string;}| 83 | } 84 | flag.Parse() |\longremark{Parse the flags and fill the variables.}| 85 | \end{lstlisting} 86 | \showremarks 87 | After the flags have been parsed you can used them: 88 | \begin{lstlisting} 89 | if *dnssec { |\coderemark{Dereference the \var{dnssec} flag variable}| 90 | // do something 91 | } 92 | \end{lstlisting} 93 | 94 | \section{Executing commands} 95 | The \package{os/exec}\index{package!os/exec} package has functions to run external commands, and is the premier way to 96 | execute commands from within a Go program. It works by defining a \var{*exec.Cmd} structure for which it 97 | defines a number of methods. 98 | Let's execute \verb|ls -l|: 99 | \begin{lstlisting} 100 | import "os/exec" 101 | 102 | cmd := exec.Command("/bin/ls", "-l") |\coderemark{Create a \var{*cmd}}| 103 | err := cmd.Run() |\coderemark{\func{Run()} it}| 104 | \end{lstlisting} 105 | The above example just runs ``ls -l'' without doing anything with the returned data, 106 | capturing the standard output from a command is done as follows: 107 | \begin{lstlisting} 108 | import "os/exec" 109 | 110 | cmd := exec.Command("/bin/ls", "-l") 111 | buf, err := cmd.Output() |\coderemark{\var{buf} is a (\type{[]byte})}| 112 | \end{lstlisting} 113 | 114 | \section{Networking} 115 | All network related types and functions can be found in the package \package{net}. One of the 116 | most important functions in there is \func{Dial}\index{networking!Dial}. When you \func{Dial} 117 | into a remote system the function returns a \var{Conn} interface type, which can be used 118 | to send and receive information. The function \func{Dial} neatly abstracts away the network 119 | family and transport. So IPv4 or IPv6, TCP or UDP can all share a common interface. 120 | 121 | Dialing a remote system (port 80) over TCP, then UDP and lastly TCP over IPv6 looks 122 | like this\footnote{In case 123 | you are wondering, 192.0.32.10 and 2620:0:2d0:200::10 are \url{www.example.org}.}: 124 | \begin{lstlisting} 125 | conn, e := Dial("tcp", "192.0.32.10:80") 126 | conn, e := Dial("udp", "192.0.32.10:80") 127 | conn, e := Dial("tcp", "[2620:0:2d0:200::10]:80") |\coderemark{Mandatory brackets}| 128 | \end{lstlisting} 129 | 130 | If there were no errors (returned in \var{e}), you can use \var{conn} to read and write. 131 | The primitives defined in the package \package{net} are: 132 | \begin{quote} 133 | // \func{Read} reads data from the connection.\\ 134 | \lstinline{Read(b []byte) (n int, err error)} 135 | \end{quote} 136 | This makes \var{conn} an \type{io.Reader}. 137 | 138 | \begin{quote} 139 | // \func{Write} writes data to the connection.\\ 140 | \lstinline{Write(b []byte) (n int, err error)} 141 | \end{quote} 142 | This makes \var{conn} also an \type{io.Writer}, in fact \var{conn} is an 143 | \type{io.ReadWriter}.\footnote{The variable \var{conn} also implements a \func{close} method, this really makes 144 | it an \type{io.ReadWriteCloser}.} 145 | 146 | But these are the low level nooks and crannies\footnote{Exercise Q\ref{ex:echo} is about using 147 | these.}, you will almost always use higher level packages. 148 | Such as the \package{http} package. For instance a simple Get for http: 149 | \begin{lstlisting} 150 | package main 151 | import ( "io/ioutil"; "http"; "fmt" ) |\longremark{The imports needed;}| 152 | 153 | func main() { 154 | r, err := http.Get("http://www.google.com/robots.txt") |\longremark{Use http's \func{Get} to retrieve the html;}| 155 | if err != nil { fmt.Printf("%s\n", err.String()); return } |\longremark{Error handling;}| 156 | b, err := ioutil.ReadAll(r.Body) |\longremark{Read the entire document into \var{b};}| 157 | r.Body.Close() 158 | if err == nil { fmt.Printf("%s", string(b)) } |\longremark{If everything was OK, print the document.}| 159 | } 160 | \end{lstlisting} 161 | \showremarks 162 | 163 | \section{Exercises} 164 | \input{ex-communication/ex-processes.tex} 165 | 166 | \input{ex-communication/ex-wordcount.tex} 167 | 168 | \input{ex-communication/ex-uniq.tex} 169 | 170 | \input{ex-communication/ex-quine.tex} 171 | 172 | \input{ex-communication/ex-echo.tex} 173 | 174 | \input{ex-communication/ex-numbercruncher.tex} 175 | 176 | \input{ex-communication/ex-finger.tex} 177 | 178 | \cleardoublepage 179 | \section{Answers} 180 | \shipoutAnswer 181 | -------------------------------------------------------------------------------- /go.bib: -------------------------------------------------------------------------------- 1 | @misc{go_web, 2 | author = "{G}o Authors", 3 | howpublished = {\url{http://golang.org/}}, 4 | title = "{G}o website", 5 | year = 2010 6 | } 7 | 8 | @misc{go_tutorial, 9 | author = "{G}o Authors", 10 | howpublished = {\url{http://golang.org/doc/go_tutorial.html}}, 11 | title = "{G}o tutorial", 12 | year = 2010 13 | } 14 | 15 | @misc{effective_go, 16 | author = "{G}o Authors", 17 | howpublished = {\url{http://golang.org/doc/effective_go.html}}, 18 | title = "{E}ffective {G}o", 19 | year = 2010 20 | } 21 | 22 | @misc{csp, 23 | author = "Wikipedia", 24 | howpublished = {\url{http://en.wikipedia.org/wiki/Communicating_sequential_processes}}, 25 | title = "Communicating sequential processes", 26 | year = 2010 27 | } 28 | 29 | @misc{duck_typing, 30 | author = "Wikipedia", 31 | howpublished = {\url{http://en.wikipedia.org/wiki/Duck_typing}}, 32 | title = "Duck typing", 33 | year = 2010 34 | } 35 | 36 | @misc{bubblesort, 37 | author = "{W}ikipedia", 38 | howpublished = {\url{http://en.wikipedia.org/wiki/Bubble_sort}}, 39 | title = "Bubble sort", 40 | year = 2010 41 | } 42 | 43 | @misc{go_nuts, 44 | author = "{G}o Community", 45 | title = "{G}o {N}uts mailing list", 46 | howpublished = {\url{http://groups.google.com/group/golang-nuts}}, 47 | year = 2010 48 | } 49 | 50 | @misc{go_spec, 51 | author = "{G}o {A}uthors", 52 | title = "{G}o language specification", 53 | howpublished = { \url{http://golang.org/doc/go_spec.html}}, 54 | year = 2010 55 | } 56 | 57 | @misc{go_interfaces, 58 | author = "Ian Lance Taylor", 59 | title = "{G}o interfaces", 60 | howpublished = {\url{http://www.airs.com/blog/archives/277}}, 61 | year = 2010 62 | } 63 | 64 | @misc{go_install, 65 | author = "{G}o {A}uthors", 66 | title = "{G}etting {S}tarted", 67 | howpublished = {\url{http://golang.org/doc/install/}}, 68 | year = 2012 69 | } 70 | 71 | @misc{go_intro, 72 | author = "Mark C. Chu-Carroll", 73 | title = "{G}oogle's new language: {G}o", 74 | howpublished = {\url{http://scienceblogs.com/goodmath/2009/11/googles_new_language_go.php}}, 75 | year = 2010 76 | } 77 | 78 | @misc{go_doc, 79 | author = "{G}o {A}uthors", 80 | title = "{G}o package documentation", 81 | howpublished = {\url{http://golang.org/doc/pkg/}}, 82 | year = 2010 83 | } 84 | 85 | @misc{go_cpp, 86 | author = "{G}o {A}uthors", 87 | title = "{G}o for {C}++ programmers", 88 | howpublished = {\url{http://golang.org/doc/go_for_cpp_programmers.html}}, 89 | year = 2010 90 | } 91 | 92 | @misc{go_blog, 93 | author = "{G}o {A}uthors", 94 | title = "The {G}o programming language blog", 95 | howpublished = {\url{http://blog.golang.org/}}, 96 | year = 2010 97 | } 98 | 99 | @misc{erlang, 100 | author = "{E}ricsson {C}ooperation", 101 | title = "Erlang", 102 | howpublished = {\url{http://www.erlang.se/}}, 103 | year = 1986 104 | } 105 | 106 | @misc{scala, 107 | author = "{LAMP} {G}roup at EPFL", 108 | title = "Scala", 109 | howpublished = { 110 | \url{http://www.scala-lang.org/}}, 111 | year = 2003 112 | } 113 | 114 | @misc{c, 115 | author = "Dennis Ritchie, Brian Kernighan", 116 | title = "The {C} Programming Language", 117 | year = 1975 118 | } 119 | 120 | @misc{C++, 121 | author = "Bjarne Stroustrup", 122 | title = "The {C}++ programming language", 123 | year = 1983 124 | } 125 | 126 | @misc{java, 127 | title = "Java", 128 | author = "James {G}osling et al", 129 | howpublished = {\url{http://oracle.com/java/}}, 130 | year = 1995 131 | } 132 | 133 | @misc{perl, 134 | title = "Perl", 135 | author = "Larry Wall et al", 136 | howpublished = {\url{http://perl.org/}}, 137 | year = 1987 138 | } 139 | 140 | @misc{haskell, 141 | title = "Haskell", 142 | author = "Haskell Authors", 143 | howpublished = {\url{http://www.haskell.org/}}, 144 | year = 1990 145 | } 146 | 147 | @misc{go_youtube, 148 | author = "{G}o Authors", 149 | title = "{G}o Youtube channel", 150 | howpublished = {\url{http://youtube.com/gocoding/}}, 151 | year = 2010 152 | } 153 | 154 | @misc{perl-packages, 155 | author = "Perl Package Authors", 156 | title = "Comprehensive Perl archive network", 157 | howpublished = {\url{http://cpan.org/}}, 158 | year = 2010 159 | } 160 | 161 | @misc{plan9, 162 | author = "Plan 9 Authors", 163 | title = "Plan 9", 164 | howpublished = {\url{http://plan9.bell-labs.com/plan9/index.html}}, 165 | year = 1992 166 | } 167 | 168 | @misc{inferno, 169 | author = "Inferno Authors", 170 | title = "Inferno", 171 | howpublished = {\url{http://www.vitanuova.com/inferno/}}, 172 | year = 1995 173 | } 174 | 175 | @misc{limbo, 176 | author = "Plan 9 Authors", 177 | title = "Limbo", 178 | howpublished = {\url{http://www.vitanuova.com/inferno/papers/limbo.html}}, 179 | year = 1995 180 | } 181 | 182 | @misc{Newsqueak, 183 | author = "Rob Pike", 184 | title = "Newsqueak: A language for communicating with mice", 185 | howpublished = {\url{http://swtch.com/~rsc/thread/newsqueak.pdf}}, 186 | publisher = "AT\&T Bell Laboratories", 187 | year = 1989 188 | } 189 | 190 | @misc{Hoare, 191 | author = "C. A. R. Hoare", 192 | title = "Communicating sequential processes (CSP)", 193 | howpublished = {\url{http://www.usingcsp.com/cspbook.pdf}}, 194 | year = 1985 195 | } 196 | 197 | @misc{quicksort, 198 | author = "C. A. R. Hoare", 199 | title = "QuickSort", 200 | howpublished = {\url{http://en.wikipedia.org/wiki/Quicksort}}, 201 | year = 1960 202 | } 203 | 204 | @misc{iota, 205 | author = "Wikipedia", 206 | title = "Iota", 207 | howpublished = {\url{http://en.wikipedia.org/wiki/Iota}}, 208 | year = 2010 209 | } 210 | 211 | @misc{fizzbuzz, 212 | author = "Imran On Tech", 213 | title = "Using FizzBuzz to find developers...", 214 | howpublished = 215 | {\url{http://imranontech.com/2007/01/24/using-fizzbuzz-to-find-developers-who-grok-coding/}}, 216 | year = 2010 217 | } 218 | 219 | @misc{go_course_day2, 220 | author = "Rob Pike", 221 | title = "The {G}o programming language, day 2", 222 | howpublished = {\url{http://golang.org/doc/{G}oCourseDay2.pdf}}, 223 | year = 2010 224 | } 225 | 226 | @misc{go_course_day3, 227 | author = "Rob Pike", 228 | title = "The {G}o programming language, day 3", 229 | howpublished = {\url{http://golang.org/doc/{G}oCourseDay3.pdf}}, 230 | year = 2010 231 | } 232 | 233 | @misc{go_nuts_interfaces, 234 | author = "{G}o Community", 235 | title = "Function accepting a slice of interface types", 236 | howpublished = 237 | {\url{http://groups.google.com/group/golang-nuts/browse_thread/thread/225fad3b5c6d0321}}, 238 | year = 2010 239 | } 240 | 241 | # {G}o issues 242 | @misc{go_issue_65, 243 | author = "{G}o Community", 244 | title = "{G}o Issue 65: Compiler can't spot guaranteed return in if statement", 245 | howpublished = 246 | {\url{http://code.google.com/p/go/issues/detail?id=65}}, 247 | year = 2010 248 | } 249 | 250 | @misc{go_blog_panic, 251 | author = "{G}o Authors", 252 | title = "Defer, Panic, and Recover", 253 | howpublished = 254 | {\url{http://blog.golang.org/2010/08/defer-panic-and-recover.html}}, 255 | year = 2010 256 | } 257 | 258 | @misc{go_faq, 259 | author = "{G}o Authors", 260 | title = "{G}o FAQ", 261 | howpublished = {\url{http://golang.org/doc/go_faq.html}}, 262 | year = 2010 263 | } 264 | 265 | @misc{go_release_hist, 266 | author = "{G}o Authors", 267 | title = "{G}o Release History", 268 | howpublished = {\url{http://golang.org/doc/devel/release.html}}, 269 | year = 2010, 270 | } 271 | 272 | @misc{go_profiling, 273 | author = "Russ Cox", 274 | title = "Profiling {G}o Programs", 275 | howpublished = {\url{http://blog.golang.org/2011/06/profiling-go-programs.html}}, 276 | year = 2011, 277 | } 278 | 279 | @misc{RFC1196, 280 | author = "D. Zimmerman", 281 | title = "The Finger User Information Protocol", 282 | howpublished = {\url{http://www.ietf.org/rfc/rfc1196.txt}}, 283 | year = 1990, 284 | } 285 | 286 | @misc{RFC4627, 287 | author = "D. Crockford", 288 | title = "The application/json Media Type for JavaScript Object Notation (JSON)", 289 | howpublished = {\url{http://www.ietf.org/rfc/rfc4627.txt}}, 290 | year = 2006, 291 | } 292 | 293 | @misc{RFC4641, 294 | author = "Kolkman \& Gieben", 295 | title = "DNSSEC Operational Practices", 296 | howpublished = {\url{http://www.ietf.org/rfc/rfc4641.txt}}, 297 | year = 2006, 298 | } 299 | -------------------------------------------------------------------------------- /go-channels.tex: -------------------------------------------------------------------------------- 1 | \epi{% 2 | \begin{itemize} 3 | \item{``Parallelism is about performance;} 4 | \item{Concurrency is about program design.''} 5 | \end{itemize}% 6 | }{\textit{Google IO 2010}\\\textsc{ROB PIKE}} 7 | \noindent{}In this chapter we will show off Go's ability for 8 | concurrent programming using channels and goroutines. Goroutines 9 | are the central entity in Go's ability for concurrency. But what 10 | \emph{is} a goroutine? From \cite{effective_go}: 11 | \begin{quote} 12 | They're called goroutines because the existing terms --- threads, coroutines, 13 | processes, and so on --- convey inaccurate connotations. A goroutine has a simple 14 | model: \emph{it is a function executing in parallel with other goroutines in the same 15 | address space}. It is lightweight, costing little more than the allocation of 16 | stack space. And the stacks start small, so they are cheap, and grow by 17 | allocating (and freeing) heap storage as required. 18 | \end{quote} 19 | A \first{goroutine}{goroutine} is a normal function, except that you start 20 | it with the keyword \first{\key{go}}{keyword!go}. 21 | \begin{lstlisting} 22 | ready("Tea", 2) |\coderemark{Normal function call}| 23 | go ready("Tea", 2) |\coderemark{\func{ready()} started as goroutine}| 24 | \end{lstlisting} 25 | The following idea for a program was taken from \cite{go_course_day3}. 26 | We run a function as two goroutines, the goroutines wait for an amount of 27 | time and then print something to the screen. 28 | On the lines 14 and 15 we start the goroutines. 29 | The \func{main} function 30 | waits long enough, so that both goroutines will have printed their text. Right 31 | now we wait for 5 seconds on line 17, but in fact we have no idea how 32 | long we should wait until all goroutines have exited. 33 | \lstinputlisting[numbers=right,label=src:sleeping,firstnumber=8,caption=Go routines in action,linerange={8,18}]{src/sleep.go} 34 | Listing \ref{src:sleeping} outputs: 35 | \begin{display} 36 | I'm waiting \coderemark{Right away} 37 | Coffee is ready! \coderemark{After 1 second} 38 | Tea is ready! \coderemark{After 2 seconds} 39 | \end{display} 40 | 41 | If we did not wait for the goroutines (i.e. remove line 17) the program 42 | would be terminated immediately and any running goroutines would 43 | \emph{die with it}. 44 | To fix this we need some kind of mechanism which allows us to 45 | communicate with the goroutines. This mechanism is available 46 | to us in the form of \first{channels}{channels}. A 47 | \first{channel}{channel} can be 48 | compared to a two-way pipe in Unix shells: you can send to and receive 49 | values from it. Those values can only be of a specific type: the 50 | type of the channel. If we define a channel, we must also define the 51 | type of the values we can send on the channel. Note that we must use 52 | \key{make} to create a channel: 53 | \begin{lstlisting} 54 | ci := make(chan int) 55 | cs := make(chan string) 56 | cf := make(chan interface{}) 57 | \end{lstlisting} 58 | Makes \var{ci} a channel on which we can send and receive integers, 59 | makes \var{cs} a channel for strings and \var{cf} a channel for types 60 | that satisfy the empty interface. 61 | Sending on a channel and receiving from it, is done with the same operator: 62 | \lstinline{<-}. \index{operator!channel} 63 | Depending on the operands it figures out what to do: 64 | \begin{lstlisting} 65 | ci <- 1 |\coderemark{\emph{Send} the integer 1 to the channel \var{ci}}| 66 | <-ci |\coderemark{\emph{Receive} an integer from the channel \var{ci}}| 67 | i := <-ci |\coderemark{\emph{Receive} from the channel \var{ci} and store it in \var{i}}| 68 | \end{lstlisting} 69 | Let's put this to use. 70 | \begin{lstlisting}[numbers=none,caption=Go routines and a channel,label=src:sleeping with channels] 71 | var c chan int |\longremark{Declare \var{c} to be a variable that is a % 72 | channel of ints. That is: this channel can move integers. Note % 73 | that this variable is global so that the goroutines have access to it;}| 74 | 75 | func ready(w string, sec int) { 76 | time.Sleep(time.Duration(sec) * time.Second) 77 | fmt.Println(w, "is ready!") 78 | c <- 1 |\longremark{Send the integer 1 on the channel \var{c};}| 79 | } 80 | 81 | func main() { 82 | c = make(chan int) |\longremark{Initialize \var{c};}| 83 | go ready("Tea", 2) |\longremark{Start the goroutines with the keyword \key{go};}| 84 | go ready("Coffee", 1) 85 | fmt.Println("I'm waiting, but not too long") 86 | <-c |\longremark{Wait until we receive a value from the channel. Note that the value we receive is discarded;}| 87 | <-c |\longremark{Two goroutines, two values to receive.}| 88 | } 89 | \end{lstlisting} 90 | 91 | \showremarks 92 | There is still some remaining ugliness; we have to read twice from 93 | the channel (lines 14 and 15). This is OK in this case, but what if 94 | we don't know how many goroutines we started? This is where another 95 | Go built-in comes in: \first{\key{select}}{keyword!select}. With \key{select} you 96 | can (among other things) listen for incoming data on a channel. 97 | 98 | Using \key{select} in our program does not really make it shorter, 99 | because we run too few go\-routines. We remove the lines 14 and 15 and 100 | replace them with the following: 101 | \begin{lstlisting}[caption=Using select,numbers=right,firstnumber=14] 102 | L: for { 103 | select { 104 | case <-c: 105 | i++ 106 | if i > 1 { 107 | break L 108 | } 109 | } 110 | } 111 | \end{lstlisting} 112 | We will now wait as long as it takes. Only when we have received more than 113 | one reply on the channel \var{c} will we exit the loop \var{L}. 114 | 115 | \subsection{Make it run in parallel} 116 | While our goroutines were running concurrently, they were not running in 117 | parallel. When you do not tell Go anything there can only be one 118 | goroutine running at a time. With \func{runtime.GOMAXPROCS(n)} you 119 | can set the number of goroutines that can run in parallel. From 120 | the documentation: 121 | \begin{quote} 122 | GOMAXPROCS sets the maximum number of CPUs that can be executing 123 | simultaneously and returns the previous setting. If n < 1, it does not 124 | change the current setting. \emph{This call will go away when the scheduler 125 | improves.} 126 | \end{quote} 127 | If you do not want to change any source code you can also set an 128 | environment variable \verb|GOMAXPROCS| to the desired value. 129 | %% test 130 | %%\marginpar{% 131 | %%$$\left\{ 132 | %%\begin{array}{l} 133 | %%\parbox{2cm}{ 134 | %%hallo Yppp hallo Yppp hallo Yppp 135 | %%hallo Yppp hallo Yppp hallo Yppp 136 | %%hallo Yppp 137 | %%} 138 | %%\end{array} 139 | %%\right.$$ 140 | %%} 141 | 142 | %%\section{So many channels and still \ldots} 143 | \section{More on channels} 144 | \label{sec:more on channels} 145 | When you create a channel in Go with \lstinline{ch := make(chan bool)}, 146 | an \first{unbuffered channel}{channel!unbuffered} for 147 | bools is created. What does this mean for your program? For one, if you 148 | read (\lstinline{value := <-ch}) it will block until there is data to 149 | receive. Secondly anything sending (\lstinline{ch<-5}) will block until there 150 | is somebody to read it. 151 | Unbuffered channels make a perfect tool for synchronizing multiple 152 | goroutines. 153 | \index{channel!blocking read} 154 | \index{channel!blocking write} 155 | 156 | But Go allows you to specify the buffer size of 157 | a channel, which is quite simply how many elements a channel can hold. 158 | \lstinline{ch := make(chan bool, 4)}, creates a buffered channel of 159 | bools that can hold 4 elements. The first 4 elements in this channel 160 | are written without any blocking. 161 | When you write the 5$^{th}$ element, your 162 | code \emph{will} block, until another goroutine reads some elements from the 163 | channel to make room. 164 | \index{channel!non-blocking read} 165 | \index{channel!non-blocking write} 166 | 167 | In conclusion, the following is true in Go: 168 | $$ 169 | \textrm{\lstinline{ch := make(chan type, value)}} 170 | \left\{ 171 | \begin{array}{ll} 172 | value == 0 & \rightarrow \textrm{unbuffered)} \\ 173 | value > 0 & \rightarrow \textrm{buffer \emph{value} elements} 174 | \end{array} 175 | \right. 176 | $$ 177 | 178 | \subsection{Closing channels} 179 | When a channel is closed the reading side needs to know this. 180 | The following code will check if a channel is closed. 181 | \begin{lstlisting} 182 | x, ok = <-ch 183 | \end{lstlisting} 184 | Where \lstinline{ok} is set to \lstinline{true} the channel is not closed 185 | \emph{and} we've read something. 186 | Otherwise \var{ok} is set to \lstinline{false}. In that case the channel 187 | was closed. 188 | 189 | \section{Exercises} 190 | \input{ex-channels/ex-for-channels.tex} 191 | 192 | \input{ex-channels/ex-fib.tex} 193 | 194 | \cleardoublepage 195 | \section{Answers} 196 | \shipoutAnswer 197 | --------------------------------------------------------------------------------