├── common.txt
├── .gitignore
├── _static
├── favicon.ico
└── images
│ └── gophercolor.png
├── _theme
└── gobook
│ ├── static
│ ├── note.png
│ ├── remember.png
│ ├── philosophy.png
│ └── default.css
│ ├── theme.conf
│ ├── search.html
│ └── layout.html
├── packages.rst
├── contents.rst
├── README
├── index.rst
├── colophon.rst
├── preface.rst
├── hello.rst
├── first.rst
├── Makefile
├── pointers.rst
├── conf.py
├── more-methods.rst
├── basic.rst
├── control.rst
├── more-interfaces.rst
├── maps.rst
├── composite.rst
├── functions.rst
├── methods.rst
├── even-more-functions.rst
└── more-functions.rst
/common.txt:
--------------------------------------------------------------------------------
1 | .. common substitution strings and misc.
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | _build
2 | app.yaml
3 | _static/fonts/
4 | _theme/gobook/analytics.html
5 |
--------------------------------------------------------------------------------
/_static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initpy/go-book/HEAD/_static/favicon.ico
--------------------------------------------------------------------------------
/_theme/gobook/static/note.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initpy/go-book/HEAD/_theme/gobook/static/note.png
--------------------------------------------------------------------------------
/_static/images/gophercolor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initpy/go-book/HEAD/_static/images/gophercolor.png
--------------------------------------------------------------------------------
/_theme/gobook/theme.conf:
--------------------------------------------------------------------------------
1 | [theme]
2 | inherit = basic
3 | stylesheet = default.css
4 | pygments_style = trac
5 |
--------------------------------------------------------------------------------
/_theme/gobook/static/remember.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initpy/go-book/HEAD/_theme/gobook/static/remember.png
--------------------------------------------------------------------------------
/_theme/gobook/static/philosophy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/initpy/go-book/HEAD/_theme/gobook/static/philosophy.png
--------------------------------------------------------------------------------
/_theme/gobook/search.html:
--------------------------------------------------------------------------------
1 | {% extends "basic/search.html" %}
2 | {% block bodyclass %}{% endblock %}
3 | {% block sidebarwrapper %}{% endblock %}
--------------------------------------------------------------------------------
/packages.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | .. Don't forget to mention how functions are exposed and exported from packages
4 | .. to code that includes them by capitalizing the first letter of the function.
5 | .. And also the fact that lower case function names are not available to code
6 | .. which includes the package.
7 | .. Include an example to illustrate.
8 |
9 |
--------------------------------------------------------------------------------
/contents.rst:
--------------------------------------------------------------------------------
1 | Table of contents
2 | *****************
3 |
4 | .. toctree::
5 | :maxdepth: 1
6 |
7 | preface
8 | first
9 | hello
10 | basic
11 | pointers
12 | control
13 | functions
14 | composite
15 | slices
16 | maps
17 | more-functions
18 | even-more-functions
19 | methods
20 | more-methods
21 | interfaces
22 | more-interfaces
23 | colophon
24 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | Welcome to the Go Book
2 | **********************
3 |
4 | This humble work (in progress) is an online book for learning the Go Programming
5 | Language (golang) - It is meant for anyone interested in Go, and aims to be easy
6 | and fun to read --despite my weak English.
7 |
8 | You can read it online at: http://go-book.appspot.com
9 |
10 | It is written in reStructuredText and the rendering is done with Sphinx.
11 |
12 | Your feedback is really appreciated :)
13 |
14 | -Yuuta
15 |
--------------------------------------------------------------------------------
/index.rst:
--------------------------------------------------------------------------------
1 | Hey, you! Yes, you!
2 | *******************
3 | .. image:: _static/images/gophercolor.png
4 | :class: rightfloat
5 |
6 | See the little gopher? Isn't it cute? Yes it is! He is the mascot of the Go
7 | programming language *---Go, what?* Why Go, the programming language of course!
8 |
9 | This website is an online book that aims to introduce people to this awesome
10 | language. And if you, actually, stumbled upon it while looking for real gophers,
11 | let me still invite you to read it and learn something cool! C'mon, go-pher it!
12 |
13 | Welcome aboard
14 | ==============
15 | .. container:: side
16 |
17 | In this part, we will learn the very basic things about Go. The basic syntax
18 | for programs, how to declare variables, pointers and how to use basic
19 | control structures.
20 |
21 | .. toctree::
22 | :maxdepth: 1
23 |
24 | preface
25 | first
26 | hello
27 | basic
28 | pointers
29 | control
30 |
31 |
32 | Let's combine stuff
33 | ===================
34 | .. container:: side
35 |
36 | Now, it's time to play like children with Legos. Technical Legos. "Tegos"? ;)
37 | We use primitive data types and basic control structures, that we saw in
38 | the previous part, to build composite types and functions.
39 |
40 | .. toctree::
41 | :maxdepth: 1
42 |
43 | functions
44 | composite
45 | slices
46 | maps
47 |
48 | And be smart and awesome
49 | ========================
50 | .. container:: side
51 |
52 | We will learn smarter and nicer things about functions, and will have fun
53 | writing code to represent and solve real world problems (well... real as in
54 | objects. --- You know what I mean)
55 |
56 | .. toctree::
57 | :maxdepth: 1
58 |
59 | more-functions
60 | even-more-functions
61 | methods
62 | more-methods
63 | interfaces
64 | more-interfaces
65 |
66 | Like a maestro with his orchestra
67 | =================================
68 | .. container:: side
69 |
70 | Why think of programs as a sequential ballade executed by a single musician?
71 | We can do better by making every musician do what he/she has to do, and make
72 | them *communicate* with one another.
73 |
74 | * Introduction to concurrency with Go
75 | * Sharing and Caring (Communicating with channels)
76 | * Channels on steroids
77 | * ...
78 |
79 | .. toctree::
80 | :maxdepth: 1
81 |
82 | colophon
83 |
84 | And still be open and friendly
85 | ==============================
86 | This is the goal of this humble work. I hope that you'll enjoy reading it, and
87 | I'd love to hear back from you! You can post issues, typos and suggestions on
88 | the `github repository`_
89 |
90 | .. _github repository: https://github.com/initpy/go-book/issues
91 |
92 | .. toctree::
93 | :hidden:
94 |
95 | contents
96 |
--------------------------------------------------------------------------------
/colophon.rst:
--------------------------------------------------------------------------------
1 | Colophon
2 | ********
3 | This humble work was and is still being done on vim_ using Sphinx_ with the help
4 | of Graphviz_ (for the various drawings and diagrams) and some tea as the
5 | author's fuel.
6 |
7 | The font used for the titles is `Rancho Regular`_ released by `Sideshow`_ under
8 | the `Apache License, version 2.0`_
9 |
10 | The examples provided in this book are in public domain. You can do whatever you
11 | want with them and I claim no responsibility over their use. Just leave me
12 | alone.
13 |
14 | The whole work is produced in HTML5, and I don't care if your browser is old.
15 | It's easier for you to upgrade your browser than for me to rewrite the template
16 | used to generate this. I don't care :)
17 |
18 | The Go gopher was drawn by `Renée French`_, the artist who also made Glenda_
19 | the `Plan 9`_ bunny.
20 |
21 | License
22 | =======
23 | This work is licensed under a `Creative Commons
24 | Attribution-NonCommercial-ShareAlike 3.0 Unported License`_. The source code is
25 | available on github at `https://github.com/initpy/go-book/
26 | `_.
27 |
28 | Your pull requests for new content, typos, better ideas... are more than
29 | welcome! If you want to translate this work, please let me know, I'd love to
30 | share your translation here too.
31 |
32 | A little request, and I know most of you won't do it anyway. But I'd hate it if
33 | this work was copied and pasted to spam search engines and make money out of it.
34 | Really.
35 |
36 | Credits
37 | =======
38 | I, `Big Yuuta`_, am the author and the maintainer of this project, and despite
39 | my weak English, I'm doing my best to keep it fun and -I hope- useful for people
40 | wanting to learn Go.
41 |
42 | *But* I wouldn't be able to do this alone. In fact, I'd like to thank these
43 | people from the bottom of my heart.
44 |
45 | - `Wayne E. Seguin`_: This man is a real *machine*, he reviewed everything,
46 | asked questions, suggested, and corrected many sentences, gave me some great
47 | advice... And added more fun and humor to the whole thing. Wayne, you rock!
48 |
49 | - `Adam (hammerandtongs)`_: Thank you so much for those many spelling and
50 | grammar fixes!
51 |
52 | - `Calvin (csmcanarney)`_: Thanks for being the first to give a hand and for
53 | your fixes.
54 |
55 | - The whole golang-nuts_ community for their support and cheers, and the huge
56 | amount of inspiration and ideas they share everyday in that group.
57 |
58 | .. external links and footnotes:
59 |
60 | .. _vim: http://www.vim.org
61 | .. _Sphinx: http://sphinx.pocoo.org/
62 | .. _Graphviz: http://graphviz.org/
63 | .. _Rancho Regular: http://www.google.com/webfonts/specimen/Rancho
64 | .. _Sideshow: https://profiles.google.com/sideshowfonts/about
65 | .. _Apache License, version 2.0: http://www.apache.org/licenses/LICENSE-2.0.html
66 | .. _Renée French: http://www.reneefrench.com/
67 | .. _Glenda: http://cm.bell-labs.com/plan9/glenda.html
68 | .. _Plan 9: http://cm.bell-labs.com/plan9/
69 | .. _Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License:
70 | http://creativecommons.org/licenses/by-nc-sa/3.0/
71 |
72 | .. credits
73 |
74 | .. _Big Yuuta: http://big.appspot.com
75 | .. _Wayne E. Seguin: https://github.com/wayneeseguin
76 | .. _Adam (hammerandtongs): https://github.com/hammerandtongs
77 | .. _Calvin (csmcanarney): https://github.com/csmcanarney
78 | .. _golang-nuts: http://groups.google.com/group/golang-nuts
79 |
--------------------------------------------------------------------------------
/preface.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | Preface
4 | *******
5 | Go_ is a programming language created by a team of *very* talented folks at
6 | Google_ with the help of many people from the Open Source community. Its source
7 | code is open source itself and can be viewed and modified freely.
8 |
9 | This book will try to teach you how to write some code in Go, while having fun
10 | doing so. It comes with many illustrative examples and diagrams in order to make
11 | the studied concepts easy to understand.
12 |
13 | Why Go?
14 | =======
15 | There are gazillions (not that many actually) of programming languages already in
16 | the wild. So one could, and rightly so, ask why yet another language?
17 | The fact is Go is easy to grok, and fun to use but also efficient and well
18 | designed.
19 |
20 | Go is a compiled language, i.e. a language that produces machine code that
21 | can be executed without the need of an external interpreter like Python, Ruby,
22 | Perl and other scripting languages.
23 |
24 | In fact, if we were to compare Go to something, it would be a modern C. Yes,
25 | that's a strong statement that calls for a justification. Being a C programmer
26 | myself, C has its very own dear place in my heart, a place that won't be shared
27 | by anything else. But Go earned my respect and that of many others thanks to its
28 | simplicity, efficiency and smart concepts that this book aims to demonstrate.
29 |
30 | Go comes with some new syntax and idioms but not too many. Enough to make things
31 | evolve, but not too many to alienate people who are used to some other
32 | programming language. This balance, and -I'd dare to say- *minimalism* are what
33 | makes Go fun to learn.
34 |
35 | Go has the efficiency of statically-typed languages, yet it provides some easy
36 | syntax and concepts that make it as *cool* as dynamic languages.
37 |
38 | Go programs are compiled fast and run fast. Go also natively supports
39 | concurrency and communication.
40 |
41 | Why this book?
42 | ==============
43 | This modest work is an introduction to the Go language. It is meant to be easy
44 | to understand by everyone and tries to make this learning experience fun and
45 | easy. Yes, that's quite a challenge, but... *aude aliquid dignum!* [#f1]_.
46 |
47 | I personally don't buy the *"learn the hard way"* method. Learning shouldn't be
48 | *hard*! Just remember that we've learnt how to speak while playing when we were
49 | younger and stupider. And Go, or any other language for that matter, is actually
50 | a lot easier than any spoken language; there are fewer words, fewer syntax
51 | rules, fewer idioms...
52 |
53 | So here's the deal and the only condition for learning with this book: take it
54 | easy. Really, consider it as a game.
55 |
56 | We will play with data and code, learn something new every time. There will be
57 | some diversity, from simple, or even silly things, to some very serious and
58 | smart concepts.
59 |
60 | Also, almost -if not all- the provided programs can be tested online in the `Go
61 | Playground`_ simply by copying/pasting them there.
62 |
63 | A work in progress
64 | ==================
65 | This is a personal initiative, I have no deadlines with any publisher. I do this
66 | for fun, and during my free time. I will strive to improve it as much as I can.
67 | I don't claim to be *perfect* ---no one is!
68 |
69 | So your help, criticism, suggestions are more than welcome. And the more you
70 | contribute, the better it will be.
71 |
72 | Thanks for your attention, and have fun!
73 |
74 | .. external links and footnotes:
75 |
76 | .. _Go: http://golang.org
77 | .. _google: http://google.com
78 | .. _Go Playground: http://play.golang.org/
79 | .. [#f1] 16th century Latin for "Dare something worthy"
80 |
--------------------------------------------------------------------------------
/_theme/gobook/layout.html:
--------------------------------------------------------------------------------
1 | {% extends "basic/layout.html" %}
2 |
3 | {%- block doctype -%}
4 |
5 | {%- endblock %}
6 |
7 | {%- macro secondnav() %}
8 | {%- if prev %}
9 | « previous
10 | {{ reldelim2 }}
11 | {%- endif %}
12 | {%- if parents %}
13 | up
14 | {%- else %}
15 | up
16 | {%- endif %}
17 | {%- if next %}
18 | {{ reldelim2 }}
19 | next »
20 | {%- endif %}
21 | {%- endmacro %}
22 |
23 | {% block extrahead %}
24 | {{ super() }}
25 | {% include "analytics.html" ignore missing %}
26 | {% endblock %}
27 |
28 | {% block content %}
29 |
110 |
111 | {%- endif %}
112 | {% endblock %}
113 |
--------------------------------------------------------------------------------
/hello.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | Konnichiwa, World!
4 | ******************
5 | Before starting to write Go applications like a wizard, we should start with the
6 | very basic ingredients. You just can't craft an airplane when you don't know
7 | what a wing is! So in this chapter we're going to learn the very basic syntax
8 | idioms to get our feet wet.
9 |
10 | The program
11 | ===========
12 | This is a tradition. And we do respect some traditions [#f1]_. The very first program
13 | one should write when learning a programming language is a small one that
14 | outputs the sentence: ``Hello World``.
15 |
16 | Ready? Go!
17 |
18 | .. code-block:: go
19 | :linenos:
20 |
21 | package main
22 |
23 | import "fmt"
24 |
25 | func main() {
26 | fmt.Printf("Hello, world; καλημ ́ρα κóσμ or こんにちは世界\n")
27 | }
28 |
29 | Output:
30 |
31 | .. container:: output
32 |
33 | | Hello, world; καλημ ́ρα κóσμ or こんにちは世界
34 |
35 | The details
36 | ===========
37 |
38 | The notion of packages
39 | ----------------------
40 | A Go program is constructed as a "package", which may in turn use facilities
41 | from other packages.
42 |
43 | The statement ``package `` (in our example: ```` is main)
44 | tells which package this file is part of.
45 |
46 | In order to print on screen the text "Hello, world..." we use a function called
47 | ``Printf`` that comes from the ``fmt`` package that we imported using the
48 | statement ``import "fmt"`` on the 3rd line.
49 |
50 | .. note::
51 | Every standalone Go program contains a package called main
52 | and its main function, after initialization, is where execution starts.
53 | The main.main function takes no arguments and returns no value.
54 |
55 | This is actually the same idea as in perl packages and python modules. And as
56 | you may see, the big advantage here is: modularity and reusability.
57 |
58 | By *modularity*, I mean that you can divide your program into several pieces each
59 | one answering a specific need. And by *reusability*, I mean that packages that
60 | you write, or that already are brought to your by Go itself, can be used many
61 | times without rewriting the functionalities they provide each and every time you
62 | need them.
63 |
64 | For now, you can just think of packages from the perspective of their *rasion
65 | d'être* and advantages. Later we will see how to create our own packages.
66 |
67 | The main function
68 | -----------------
69 | On line 5, we declare our main function with the keyword ``func`` and its body
70 | is enclosed between ``{`` and ``}`` just like in C, C++, Java and other
71 | languages.
72 |
73 | Notice that our ``main()`` function takes no arguments. But we will see when we
74 | will study functions, that in Go, they can take arguments, and return no, or one,
75 | or many values!
76 |
77 | So on line 6, we called the function ``Printf`` that is defined in the ``fmt``
78 | packages that we imported in line 3.
79 |
80 | The ``dot notation`` is what is used in Go to refer to data, or functions
81 | located in imported packages. Again, this is not a Go's invention, since this
82 | technique is used in several other languages such as Python:
83 | ``.``
84 |
85 | UTF-8 Everywhere!
86 | -----------------
87 | Notice that the string we printed using ``Printf`` contains non-ASCII
88 | characters (greek and japanese). In fact, Go, natively supports UTF-8 for string
89 | *and* identifiers.
90 |
91 | Conclusion
92 | ==========
93 | Go uses packages (like python's modules) to organize code. The function
94 | ``main.main`` (function main located the in main package) is the entry-point of
95 | every standalone Go program. Go uses UTF-8 for strings and identifiers and is
96 | not limited to the old ASCII character set.
97 |
98 |
99 | .. external links and footnotes:
100 |
101 | .. [#f1] It is said that the first "hello, world" program was written by Brian
102 | Kernighan in his tutorial "Programming in C: A Tutorial" at Bell Labs in
103 | 1974. And there is a "hello, world" example in the seminal book "The C
104 | programming Language" much often refered to as "K&R" by Brian Kernighan and
105 | Dennis Ritchie.
106 |
--------------------------------------------------------------------------------
/first.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | If you're not a programmer
4 | **************************
5 | This chapter is for people who have never written a single program in an
6 | imperative programming language. If you are used to languages likes C, C++, Python, Perl,
7 | Ruby or if you know what the words variable, constant, type,
8 | instruction, assignation mean you may (No! You SHOULD!) skip this section entirely.
9 |
10 |
11 | How do programs work?
12 | =====================
13 | In the programming world there are many families of languages: functional,
14 | logic, imperative.
15 |
16 | Go, like C, C++, Python, Perl and some others are said to be imperative
17 | languages because you write down what the processor should execute. It's an
18 | imperative way to describe tasks assigned to the computer.
19 |
20 | An imperative program is a sequence of *instructions* that the processor
21 | executes when the program is compiled and *transformed* to a binary form that
22 | the processor understands.
23 |
24 | Think of it as a list of steps to assemble or build something. We said
25 | *"sequence"* because the **order** of these steps generally matters a LOT! You
26 | can't paint the walls of a house when you haven't built the walls yet. See?
27 | Order matters!
28 |
29 | What are variables?
30 | ===================
31 | When you solve math problems (mind you it won't be about math this time), you
32 | say that the variable ``x`` is set to the value ``1`` for example.
33 |
34 | Sometimes you have to solve equations like: ``2x + 1 = 5``. Solving here means
35 | finding out the value of the variable ``x``.
36 |
37 | So it's safe to say that ``x`` is a container that can contain different values
38 | of a given type.
39 |
40 | Think of them as boxes labeled with *identifiers* that store values.
41 |
42 | What is assignation?
43 | ====================
44 | We assign a value to a variable to say that this variable is *equal* to this
45 | value from the assignation act on, until another assignation changes its value.
46 |
47 | .. code-block:: go
48 | :linenos:
49 |
50 | //assign the value 5 to the variable x
51 | x = 5
52 | // Now x is equal to 5. We write this like this: x == 5
53 | x = x + 3 //now, we assign to x its value plus 3
54 | //so now, x == 8
55 |
56 | Assignation is the act of *storing* values inside variables. In the previous
57 | snippet, we assigned the value ``5`` to the variable whose identifier is ``x``
58 | (we say simply the variable ``x``) and just after, we assigned to the variable
59 | ``x`` its own value (``5`` is what we assigned to it in the previous
60 | instruction) plus ``3``. So now, x contains the value ``5+3`` which is ``8``.
61 |
62 | .. graphviz::
63 |
64 | digraph variable_use {
65 | //rankdir=LR;
66 | graph [bgcolor=transparent, resolution=96, fontsize="10"];
67 | edge [arrowsize=.5, arrowhead="vee", color="#ff6600", penwidth=.4];
68 | node [shape=box, fontsize=8, height=.2, penwidth=.4]
69 | value[shape="circle", label="5", fixedsize="false"]
70 | value2[shape="circle", label="x+3", fixedsize="false"]
71 | variable[label="x"];
72 | variable2[label="x"];
73 | value->variable
74 | value2->variable2
75 | {rank=sink; variable2 value2}
76 | }
77 |
78 | What is a type?
79 | ===============
80 | Each declared variable is of a given type. A type is a set of the values that
81 | the variable can store. In other words: A type is the set of values that we can
82 | assign to a given variable.
83 |
84 | For example: A variable x of the type ``int``\eger can be used to store
85 | integer values: 0, 1, 2, ...
86 |
87 | The phrase *"Hello world"* can be assigned to variables of type ``string``.
88 |
89 | So we actually *declare* variables of a given *type* in order to use them with
90 | values of that type.
91 |
92 | What is a constant?
93 | ===================
94 | A constant is an identifier that is assigned a given value, which can't be
95 | changed by your program.
96 |
97 | We *declare* a constant with a given value.
98 |
99 | .. code-block:: go
100 | :linenos:
101 |
102 | // Pi is a constant whose value is 3.14
103 | const Pi = 3.14
104 |
105 | // Let's use the constant Pi
106 | var x float32 //we declare a variable x of type float32
107 | x = 3 * Pi //when compiled, x == 3 * 3.14
108 |
109 | var y float32
110 | y = 4 * Pi //when compiled, y == 4 * 3.14
111 |
112 | For example, we can declare the constant ``Pi`` to be equal to ``3.14``. During
113 | the execution of the program, the value of ``Pi`` won't and can not be changed.
114 | There is no assignation of values to constants.
115 |
116 | Constants are useful to make programs easy to read and to maintain. In effect,
117 | writing ``Pi`` instead of the floating point number ``3.14`` in many spots of
118 | your program make it easier to read.
119 |
120 | Also, if we decide to make the ouput of our program that uses ``Pi`` more
121 | precise, we can change the constant's declared value once to be ``3.14159``
122 | instead of the earlier ``3.14`` and the new value will be used all along when
123 | the program is compilled again.
124 |
125 | Conclusion
126 | ==========
127 | Imperative programming is easy. Easy as putting values in boxes. Once you
128 | understand this very basic thing, complex (notice, I didn't say complicated)
129 | things can be seen as a composition of simpler things.
130 |
131 | Easy and fun. Fun as playing with Lego sets :)
132 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | PAPER =
8 | BUILDDIR = _build
9 |
10 | # Internal variables.
11 | PAPEROPT_a4 = -D latex_paper_size=a4
12 | PAPEROPT_letter = -D latex_paper_size=letter
13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
14 | # the i18n builder cannot share the environment and doctrees with the others
15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
16 |
17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
18 |
19 | help:
20 | @echo "Please use \`make ' where is one of"
21 | @echo " html to make standalone HTML files"
22 | @echo " dirhtml to make HTML files named index.html in directories"
23 | @echo " singlehtml to make a single large HTML file"
24 | @echo " pickle to make pickle files"
25 | @echo " json to make JSON files"
26 | @echo " htmlhelp to make HTML files and a HTML help project"
27 | @echo " qthelp to make HTML files and a qthelp project"
28 | @echo " devhelp to make HTML files and a Devhelp project"
29 | @echo " epub to make an epub"
30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
31 | @echo " latexpdf to make LaTeX files and run them through pdflatex"
32 | @echo " text to make text files"
33 | @echo " man to make manual pages"
34 | @echo " texinfo to make Texinfo files"
35 | @echo " info to make Texinfo files and run them through makeinfo"
36 | @echo " gettext to make PO message catalogs"
37 | @echo " changes to make an overview of all changed/added/deprecated items"
38 | @echo " linkcheck to check all external links for integrity"
39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)"
40 |
41 | clean:
42 | -rm -rf $(BUILDDIR)/*
43 |
44 | html:
45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
46 | @echo
47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
48 |
49 | dirhtml:
50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
51 | @echo
52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
53 |
54 | singlehtml:
55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
56 | @echo
57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
58 |
59 | pickle:
60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
61 | @echo
62 | @echo "Build finished; now you can process the pickle files."
63 |
64 | json:
65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
66 | @echo
67 | @echo "Build finished; now you can process the JSON files."
68 |
69 | htmlhelp:
70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
71 | @echo
72 | @echo "Build finished; now you can run HTML Help Workshop with the" \
73 | ".hhp project file in $(BUILDDIR)/htmlhelp."
74 |
75 | qthelp:
76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
77 | @echo
78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \
79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/gobook.qhcp"
81 | @echo "To view the help file:"
82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/gobook.qhc"
83 |
84 | devhelp:
85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
86 | @echo
87 | @echo "Build finished."
88 | @echo "To view the help file:"
89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/gobook"
90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/gobook"
91 | @echo "# devhelp"
92 |
93 | epub:
94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
95 | @echo
96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
97 |
98 | latex:
99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
100 | @echo
101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \
103 | "(use \`make latexpdf' here to do that automatically)."
104 |
105 | latexpdf:
106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
107 | @echo "Running LaTeX files through pdflatex..."
108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf
109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
110 |
111 | text:
112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
113 | @echo
114 | @echo "Build finished. The text files are in $(BUILDDIR)/text."
115 |
116 | man:
117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
118 | @echo
119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
120 |
121 | texinfo:
122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
123 | @echo
124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
125 | @echo "Run \`make' in that directory to run these through makeinfo" \
126 | "(use \`make info' here to do that automatically)."
127 |
128 | info:
129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
130 | @echo "Running Texinfo files through makeinfo..."
131 | make -C $(BUILDDIR)/texinfo info
132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
133 |
134 | gettext:
135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
136 | @echo
137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
138 |
139 | changes:
140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
141 | @echo
142 | @echo "The overview file is in $(BUILDDIR)/changes."
143 |
144 | linkcheck:
145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
146 | @echo
147 | @echo "Link check complete; look for any errors in the above output " \
148 | "or in $(BUILDDIR)/linkcheck/output.txt."
149 |
150 | doctest:
151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
152 | @echo "Testing of doctests in the sources finished, look at the " \
153 | "results in $(BUILDDIR)/doctest/output.txt."
154 |
--------------------------------------------------------------------------------
/pointers.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | Pointers and memory
4 | *******************
5 | Most people think of pointers as an *advanced* topic. And honestly, the more you
6 | think of them as advanced, the more you'll fear them and the less you'll
7 | understand such a simple thing. You are not an idiot, let me prove that for you.
8 |
9 | When you declare a variable in your program, you know that this variable
10 | occupies a place in your memory (RAM), right? Because when you access it, when
11 | you change its value, it must exist somewhere!
12 |
13 | And this *somewhere* is the variable's *address* in memory.
14 |
15 | .. graphviz::
16 |
17 | digraph ram {
18 | rankdir=LR;
19 | graph [bgcolor=transparent, resolution=96, fontsize="10"];
20 | edge [arrowsize=.5, arrowhead="vee", color="#ff6600", penwidth=.4];
21 | node [shape=record, fontsize=8, height=.2, penwidth=.4]
22 | ram[label="...|i|ok|hello|...|f|..."];
23 | node[shape="oval", fixedsize="false"]
24 | exnode0 [label="var i int"];
25 | exnode1 [label="var ok bool"];
26 | exnode2 [label="var hello string"];
27 | exnode4 [label="var f float32"];
28 | exnode0->ram:f0;
29 | exnode1->ram:f1;
30 | exnode2->ram:f2;
31 | exnode4->ram:f4;
32 | RAM[label="This is your RAM", shape=plaintext, fontcolor=blue];
33 | RAM->ram:n [color=blue, style=dotted];
34 | }
35 |
36 | Now, when you buy your RAM, it's nowadays sold in GB (Giga Bytes), that is how
37 | many *bytes* are available to be used by your program and its variables. And you
38 | guess, that the string "Hello, world" doesn't occupy the same amount of RAM as a
39 | simple integer.
40 |
41 | For example, the variable ``i`` can occupy 4 bytes of your RAM starting from the
42 | 100th byte to the 103th, and the string ``"Hello world"`` can occupy more ram
43 | starting from the 105th byte to the 116th byte.
44 |
45 | The first byte's number of the space occupied by the variable is called its
46 | address.
47 |
48 | And we use the ``&`` operator to find out the address of a given variable.
49 |
50 | .. code-block:: go
51 | :linenos:
52 |
53 | package main
54 |
55 | import "fmt"
56 |
57 | var (
58 | i int = 9
59 | hello string = "Hello world"
60 | pi float32 = 3.14
61 | c complex64 = 3+5i
62 | )
63 |
64 | func main() {
65 | fmt.Println("Hexadecimal address of i is: ", &i)
66 | fmt.Println("Hexadecimal address of hello is: ", &hello)
67 | fmt.Println("Hexadecimal address of pi is: ", &pi)
68 | fmt.Println("Hexadecimal address of c is: ", &c)
69 | }
70 |
71 | Output:
72 |
73 | .. container:: output
74 |
75 | | Hexadecimal address of i is: 0x4b8018
76 | | Hexadecimal address of hello is: 0x4b8108
77 | | Hexadecimal address of pi is: 0x4b801c
78 | | Hexadecimal address of c is: 0x4b80b8
79 |
80 | You see? Each variable has its own address, and you can guess that the addresses
81 | of variables depend on the amount of RAM occupied by some other variables.
82 |
83 | The variables that can *store* other variables' addresses are called *pointers*
84 | to these variables.
85 |
86 | How to declare a pointer?
87 | =========================
88 | For any given type ``T``, there is an associated type ``*T`` for pointers
89 | to variables of type ``T``.
90 |
91 | Example:
92 |
93 | .. code-block:: go
94 | :linenos:
95 |
96 | var i int
97 | var hello string
98 | var p *int //p is of type *int, so p is a pointer to variables of type int
99 |
100 | //we can assign to p the address of i like this:
101 | p = &i //now p points to i (i.e. p stores the address of i
102 | hello_ptr := &hello //hello_ptr is a pointer variable of type *string and it points hello
103 |
104 |
105 | How to access the value of a pointed-to variable?
106 | =================================================
107 |
108 | If ``Ptr`` is a pointer to ``Var`` then ``Ptr == &Var``. And ``*Ptr == Var``.
109 |
110 | In other words: you precede a variable with the ``&`` operator to obtain its
111 | address (a pointer to it), and you precede a pointer by the ``*`` operator to
112 | obtain the value of the variable it points to. And this is called:
113 | *dereferencing*.
114 |
115 | .. admonition:: Remember
116 |
117 | * ``&`` is called the address operator.
118 | * ``*`` is called the dereferencing operator.
119 |
120 | .. code-block:: go
121 | :linenos:
122 |
123 | package main
124 | import "fmt"
125 |
126 | func main() {
127 | hello := "Hello, mina-san!"
128 | //declare a hello_ptr pointer variable to strings
129 | var hello_ptr *string
130 | // make it point our hello variable. i.e. assign its address to it
131 | hello_ptr = &hello
132 | // and int variable and a pointer to it
133 | i := 6
134 | i_ptr := &i //i_ptr is of type *int
135 |
136 | fmt.Println("The string hello is: ", hello)
137 | fmt.Println("The string pointed to by hello_ptr is: ", *hello_ptr)
138 | fmt.Println("The value of i is: ", i)
139 | fmt.Println("The value pointed to by i_ptr is: ", *i_ptr)
140 | }
141 |
142 | Output:
143 |
144 | .. container:: output
145 |
146 | | The string hello is: Hello, mina-san!
147 | | The string pointed to by hello_ptr is: Hello, mina-san!
148 | | The value of i is: 6
149 | | The value pointed to by i_ptr is: 6
150 |
151 | .. graphviz::
152 |
153 | digraph ram {
154 | rankdir=LR;
155 | graph [bgcolor=transparent, resolution=96, fontsize="10" ];
156 | edge [arrowsize=.5, arrowtail="dot", color="#ff6600", penwidth=.4];
157 | node [shape=box, fontsize=8, height=.1, penwidth=.4]
158 | i [label="var i int"];
159 | i_ptr [label="var i_ptr *int", shape="oval"];
160 | hello [label="var hello string"];
161 | hello_ptr [label="var hello_ptr *string", shape="oval"];
162 | i_ptr->i;
163 | hello_ptr->hello;
164 | }
165 |
166 |
167 | And that is all! Pointers are variables that store other variables addresses, and
168 | if a variable is of type ``int``, its pointer will be of type ``*int``, if it is
169 | of type ``float32``, its pointer is of type ``*float32`` and so on...
170 |
171 | Why do we need pointers?
172 | ========================
173 | Since we can access variables, assign values to them using only their names, one
174 | might wonder why and how pointers are useful.
175 | This is a very legitimate question, and you'll see the answer is quite simple.
176 |
177 | Suppose that your program as it runs needs some to store some results in some
178 | new variables not already declared. How would it do that?
179 | You'll say: I'll prepare some variables just in case. But wait, what if the
180 | number of new variables differs on each execution of your program?
181 |
182 | The answer is *runtime allocation*: your program will *allocate* some memory to
183 | store some data while it is running.
184 |
185 | .. _function-new:
186 |
187 | Go has a built-in allocation function called ``new`` which allocates exactly
188 | the amount of memory required to store a variable of a given type, and after
189 | it allocates the memory, it returns a pointer.
190 |
191 | You use it like this: ``new(Type)`` where ``Type`` is the type of the variable
192 | you want to use.
193 |
194 | Here's an example to explain the ``new`` function.
195 |
196 | .. code-block:: go
197 | :linenos:
198 |
199 | package main
200 | import "fmt"
201 |
202 | func main() {
203 | sum := 0
204 | var double_sum *int //a pointer to int
205 | for i:=0; i<10; i++{
206 | sum += i
207 | }
208 | double_sum = new(int) //allocate memory for an int and make double_sum point to it
209 | *double_sum = sum*2 //use the allocated memory, by dereferencing double_sum
210 | fmt.Println("The sum of numbers from 0 to 10 is: ", sum)
211 | fmt.Println("The double of this sum is: ", *double_sum)
212 | }
213 |
214 | .. container:: output
215 |
216 | | The sum of numbers from 0 to 10 is: 45
217 | | The double of this sum is: 90
218 |
219 | Another good reason, that we will see when we will study *functions* is that
220 | passing parameters by reference can be useful in many cases. But that's a story
221 | for another day. Until then, I hope that you have assimilated the notion of
222 | pointers, but don't worry, we will work with them gradually in the next
223 | chapters, and you'll see that the fear some people have about them is
224 | unjustified.
225 |
--------------------------------------------------------------------------------
/conf.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # gobook documentation build configuration file, created by
4 | # sphinx-quickstart on Mon Oct 17 19:58:23 2011.
5 | #
6 | # This file is execfile()d with the current directory set to its containing dir.
7 | #
8 | # Note that not all possible configuration values are present in this
9 | # autogenerated file.
10 | #
11 | # All configuration values have a default; values that are commented out
12 | # serve to show the default.
13 |
14 | import sys, os
15 |
16 | # If extensions (or modules to document with autodoc) are in another directory,
17 | # add these directories to sys.path here. If the directory is relative to the
18 | # documentation root, use os.path.abspath to make it absolute, like shown here.
19 | #sys.path.insert(0, os.path.abspath('.'))
20 |
21 | # -- General configuration -----------------------------------------------------
22 |
23 | # If your documentation needs a minimal Sphinx version, state it here.
24 | #needs_sphinx = '1.0'
25 |
26 | # Add any Sphinx extension module names here, as strings. They can be extensions
27 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
28 | extensions = ['sphinx.ext.graphviz']
29 |
30 | # Add any paths that contain templates here, relative to this directory.
31 | templates_path = ['_templates']
32 |
33 | # The suffix of source filenames.
34 | source_suffix = '.rst'
35 |
36 | # The encoding of source files.
37 | #source_encoding = 'utf-8-sig'
38 |
39 | # The master toctree document.
40 | master_doc = 'index'
41 |
42 | # General information about the project.
43 | project = u'gobook'
44 | copyright = u'2011, Big Yuuta'
45 |
46 | # The version info for the project you're documenting, acts as replacement for
47 | # |version| and |release|, also used in various other places throughout the
48 | # built documents.
49 | #
50 | # The short X.Y version.
51 | version = '1'
52 | # The full version, including alpha/beta/rc tags.
53 | release = '1'
54 |
55 | # The language for content autogenerated by Sphinx. Refer to documentation
56 | # for a list of supported languages.
57 | #language = None
58 |
59 | # There are two options for replacing |today|: either, you set today to some
60 | # non-false value, then it is used:
61 | #today = ''
62 | # Else, today_fmt is used as the format for a strftime call.
63 | #today_fmt = '%B %d, %Y'
64 |
65 | # List of patterns, relative to source directory, that match files and
66 | # directories to ignore when looking for source files.
67 | exclude_patterns = []
68 |
69 | # The reST default role (used for this markup: `text`) to use for all documents.
70 | #default_role = None
71 |
72 | # If true, '()' will be appended to :func: etc. cross-reference text.
73 | #add_function_parentheses = True
74 |
75 | # If true, the current module name will be prepended to all description
76 | # unit titles (such as .. function::).
77 | #add_module_names = True
78 |
79 | # If true, sectionauthor and moduleauthor directives will be shown in the
80 | # output. They are ignored by default.
81 | #show_authors = False
82 |
83 | # The name of the Pygments (syntax highlighting) style to use.
84 | pygments_style = 'monokai'
85 |
86 | # A list of ignored prefixes for module index sorting.
87 | #modindex_common_prefix = []
88 |
89 |
90 | # -- Options for HTML output ---------------------------------------------------
91 |
92 | # The theme to use for HTML and HTML Help pages. See the documentation for
93 | # a list of builtin themes.
94 | html_theme = 'gobook'
95 |
96 | # Theme options are theme-specific and customize the look and feel of a theme
97 | # further. For a list of options available for each theme, see the
98 | # documentation.
99 | #html_theme_options = {}
100 |
101 | # Add any paths that contain custom themes here, relative to this directory.
102 | html_theme_path = ["_theme"]
103 |
104 | # The name for this set of Sphinx documents. If None, it defaults to
105 | # " v documentation".
106 | html_title = "Let's learn Go!"
107 |
108 | # A shorter title for the navigation bar. Default is the same as html_title.
109 | #html_short_title = None
110 |
111 | # The name of an image file (relative to this directory) to place at the top
112 | # of the sidebar.
113 | #html_logo = None
114 |
115 | # The name of an image file (within the static path) to use as favicon of the
116 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
117 | # pixels large.
118 | #html_favicon = None
119 |
120 | # Add any paths that contain custom static files (such as style sheets) here,
121 | # relative to this directory. They are copied after the builtin static files,
122 | # so a file named "default.css" will overwrite the builtin "default.css".
123 | html_static_path = ['_static']
124 |
125 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
126 | # using the given strftime format.
127 | #html_last_updated_fmt = '%b %d, %Y'
128 |
129 | # If true, SmartyPants will be used to convert quotes and dashes to
130 | # typographically correct entities.
131 | #html_use_smartypants = True
132 |
133 | # Custom sidebar templates, maps document names to template names.
134 | #html_sidebars = {}
135 |
136 | # Additional templates that should be rendered to pages, maps page names to
137 | # template names.
138 | #html_additional_pages = {}
139 |
140 | # If false, no module index is generated.
141 | #html_domain_indices = True
142 |
143 | # If false, no index is generated.
144 | #html_use_index = True
145 |
146 | # If true, the index is split into individual pages for each letter.
147 | #html_split_index = False
148 |
149 | # If true, links to the reST sources are added to the pages.
150 | #html_show_sourcelink = True
151 |
152 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
153 | #html_show_sphinx = True
154 |
155 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
156 | #html_show_copyright = True
157 |
158 | # If true, an OpenSearch description file will be output, and all pages will
159 | # contain a tag referring to it. The value of this option must be the
160 | # base URL from which the finished HTML is served.
161 | #html_use_opensearch = ''
162 |
163 | # This is the file name suffix for HTML files (e.g. ".xhtml").
164 | #html_file_suffix = None
165 |
166 | # Output file base name for HTML help builder.
167 | htmlhelp_basename = 'gobookdoc'
168 |
169 |
170 | # -- Options for LaTeX output --------------------------------------------------
171 |
172 | latex_elements = {
173 | # The paper size ('letterpaper' or 'a4paper').
174 | #'papersize': 'letterpaper',
175 |
176 | # The font size ('10pt', '11pt' or '12pt').
177 | #'pointsize': '10pt',
178 |
179 | # Additional stuff for the LaTeX preamble.
180 | #'preamble': '',
181 | }
182 |
183 | # Grouping the document tree into LaTeX files. List of tuples
184 | # (source start file, target name, title, author, documentclass [howto/manual]).
185 | latex_documents = [
186 | ('index', 'gobook.tex', u'gobook Documentation',
187 | u'Big Yuuta', 'manual'),
188 | ]
189 |
190 | # The name of an image file (relative to this directory) to place at the top of
191 | # the title page.
192 | #latex_logo = None
193 |
194 | # For "manual" documents, if this is true, then toplevel headings are parts,
195 | # not chapters.
196 | #latex_use_parts = False
197 |
198 | # If true, show page references after internal links.
199 | #latex_show_pagerefs = False
200 |
201 | # If true, show URL addresses after external links.
202 | #latex_show_urls = False
203 |
204 | # Documents to append as an appendix to all manuals.
205 | #latex_appendices = []
206 |
207 | # If false, no module index is generated.
208 | #latex_domain_indices = True
209 |
210 |
211 | # -- Options for manual page output --------------------------------------------
212 |
213 | # One entry per manual page. List of tuples
214 | # (source start file, name, description, authors, manual section).
215 | man_pages = [
216 | ('index', 'gobook', u'gobook Documentation',
217 | [u'Big Yuuta'], 1)
218 | ]
219 |
220 | # If true, show URL addresses after external links.
221 | #man_show_urls = False
222 |
223 |
224 | # -- Options for Texinfo output ------------------------------------------------
225 |
226 | # Grouping the document tree into Texinfo files. List of tuples
227 | # (source start file, target name, title, author,
228 | # dir menu entry, description, category)
229 | texinfo_documents = [
230 | ('index', 'gobook', u'gobook Documentation', u'Big Yuuta',
231 | 'gobook', 'One line description of project.', 'Miscellaneous'),
232 | ]
233 |
234 | # Documents to append as an appendix to all manuals.
235 | #texinfo_appendices = []
236 |
237 | # If false, no module index is generated.
238 | #texinfo_domain_indices = True
239 |
240 | # How to display URL addresses: 'footnote', 'no', or 'inline'.
241 | #texinfo_show_urls = 'footnote'
242 |
--------------------------------------------------------------------------------
/more-methods.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | More meth(odes) please!
4 | ***********************
5 | We have learned how to write methods in Go, that they can be seen as functions
6 | with an implicit first parameter that is its receiver, and we saw some
7 | facilities that Go offers when working with pointers and receivers.
8 |
9 | In this chapter we will see how to implement some OOP concepts using methods.
10 | It will be fun and relatively easy.
11 |
12 | Structs with anonymous fields
13 | =============================
14 | I didn't tell you about this when we studied ``struct``\s, but we actually can
15 | declare fields without specifying names for them (just the type). It is for
16 | this reason that we call them *anonymous fields* (the lack of a name).
17 |
18 | When an anonymous field is a ``struct`` its fields are inserted (embedded)
19 | into the struct containing it.
20 |
21 | Let's see an example to help clarify this concept:
22 |
23 | .. code-block:: go
24 | :linenos:
25 |
26 | package main
27 | import "fmt"
28 |
29 | type Human struct {
30 | name string
31 | age int
32 | weight int //in lb, mind you
33 | }
34 |
35 | type Student struct {
36 | Human //an anonymous field of type Human
37 | speciality string
38 | }
39 |
40 | func main() {
41 | //Mark is a Student, notice how we declare a literal of this type:
42 | mark := Student{Human{"Mark", 25, 120}, "Computer Science"}
43 | //Now let's access the fields:
44 | fmt.Println("His name is", mark.name)
45 | fmt.Println("His age is", mark.age)
46 | fmt.Println("His weight is", mark.weight)
47 | fmt.Println("His speciality is", mark.speciality)
48 | //Change his speciality
49 | mark.speciality = "AI"
50 | fmt.Println("Mark changed his speciality")
51 | fmt.Println("His speciality is", mark.speciality)
52 | //change his age. He got older
53 | fmt.Println("Mark become old")
54 | mark.age = 46
55 | fmt.Println("His age is", mark.age)
56 | //Mark gained some weight as time goes by
57 | fmt.Println("Mark is not an athlet anymore")
58 | mark.weight += 60
59 | fmt.Println("His weight is", mark.weight)
60 | }
61 |
62 | Output:
63 |
64 | .. container:: output
65 |
66 | | His name is Mark
67 | | His age is 25
68 | | His weight is 120
69 | | His speciality is Computer Science
70 | | Mark changed his speciality
71 | | His speciality is AI
72 | | Mark become old
73 | | His age is 46
74 | | Mark is not an athlet anymore
75 | | His weight is 180
76 |
77 | On line 29 and 33 we were able to access and change the fields ``age`` and
78 | ``weight`` just as if they were *declared* as fields of the ``Student`` struct.
79 | This is because fields of ``Human`` are embedded in the struct ``Student``.
80 |
81 | Cool, isn't it? But there's more than this interpolation of fields, an anonymous
82 | field can be used with its type as its name!
83 |
84 | This means that ``Student`` has a field named ``Human`` that can be used as
85 | regular field with this name.
86 |
87 | .. code-block:: go
88 | :linenos:
89 |
90 | // We can access and modify the Human field using the embedded struct name:
91 | mark.Human = Human{"Marcus", 55, 220} // Nervous breakdown, he became a Nun.
92 | mark.Human.age -= 1 // Soon he will be back in diapers...
93 |
94 | Anonymous fields of any type
95 | ============================
96 | Accessing, and changing an anonymous field by name is quite useful for
97 | anonymous fields that are not ``struct``\s. * -- Who told you that anonymous
98 | fields must be* ``struct``\s?! * -- I didn't!*
99 |
100 | In fact, any *named type* and pointers to named types are completely acceptable.
101 |
102 | Let's see some anonymous action:
103 |
104 | .. code-block:: go
105 | :linenos:
106 |
107 | package main
108 | import "fmt"
109 |
110 | type Skills []string
111 |
112 | type Human struct {
113 | name string
114 | age int
115 | weight int //in lb, mind you
116 | }
117 |
118 | type Student struct {
119 | Human //an anonymous field of type Human
120 | Skills //anonymous field for his skills
121 | int //we will use this int as an anonymous field for his preferred number
122 | speciality string
123 | }
124 |
125 | func main() {
126 | //Jane is a Student, look how we declare a literal of this type
127 | //by specifying only some of its fields. We saw this before
128 | jane := Student{Human:Human{"Jane", 35, 100}, speciality:"Biology"}
129 | //Now let's access the fields:
130 | fmt.Println("Her name is", jane.name)
131 | fmt.Println("Her age is", jane.age)
132 | fmt.Println("Her weight is", jane.weight)
133 | fmt.Println("Her speciality is", jane.speciality)
134 | //Let's change some anonymous fields
135 | jane.Skills = []string{"anatomy"}
136 | fmt.Println("Her skills are", jane.Skills)
137 | fmt.Println("She acquired two new ones")
138 | jane.Skills = append(jane.Skills, "physics", "golang")
139 | fmt.Println("Her skills now are", jane.Skills)
140 | //her preferred number, which is an int anonymous field
141 | jane.int = 3
142 | fmt.Println("Her preferred number is", jane.int)
143 | }
144 |
145 | Output:
146 |
147 | .. container:: output
148 |
149 | | Her name is Jane
150 | | Her age is 35
151 | | Her weight is 100
152 | | Her speciality is Biology
153 | | Her skills are [anatomy]
154 | | She acquired two new ones
155 | | Her skills now are [anatomy physics golang]
156 | | Her preferred number is 3
157 |
158 | The anonymous field mechanism lets us *inherit* some (or even all)
159 | of the implementation of a given type from another type or types.
160 |
161 | Anonymous fields conflicts
162 | ==========================
163 | What happens if ``Human`` has a field ``phone`` and ``Student`` has also a field
164 | with the same name?
165 |
166 | This kind of conflicts are solved in Go simply by saying that the *outer* name
167 | *hides* the inner one. i.e. when accessing ``phone`` you are working with
168 | ``Student``'s one.
169 |
170 | This provides a way to *override* a field that is present in the "inherited"
171 | anonymous field by the one that we explicitely specify in our type.
172 |
173 | If you still need to access the anonymous one, you'll have to use the type's
174 | name syntax:
175 |
176 | .. code-block:: go
177 | :linenos:
178 |
179 | package main
180 | import "fmt"
181 |
182 | type Human struct {
183 | name string
184 | age int
185 | phone string //his own mobile number
186 | }
187 |
188 | type Employee struct {
189 | Human //an anonymous field of type Human
190 | speciality string
191 | phone string //work's phone number
192 | }
193 |
194 | func main() {
195 | Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
196 | fmt.Println("Bob's work phone is: " Bob.phone)
197 | //Now we need to specify Human to access Human's phone
198 | fmt.Println("Bob's personal phone is: " Bob.Human.phone)
199 | }
200 |
201 | Output:
202 |
203 | .. container:: output
204 |
205 | | Bob's work phone is: 333-222
206 | | Bob's personal phone is: 777-444-XXXX
207 |
208 | Great! So now you ask,
209 |
210 | "*Now, what does all this have to do with methods?*"
211 |
212 | Attaboy, you didn't forget the main subject of the chapter. Kudos.
213 |
214 | Methods on anonymous fields
215 | ===========================
216 | The good surprise is that methods behave exactly like anonymous fields. If an
217 | anonymous field implements a given method, this method will be available for the
218 | type that is using this anonymous field.
219 |
220 | If the ``Human`` type implements a method ``SayHi()`` that prints a greeting,
221 | this same method is available for both ``Student`` and ``Employee``! You won't
222 | need to write it twice for them:
223 |
224 | .. code-block:: go
225 | :linenos:
226 |
227 | package main
228 | import "fmt"
229 |
230 | type Human struct {
231 | name string
232 | age int
233 | phone string //his own mobile number
234 | }
235 |
236 | type Student struct {
237 | Human //an anonymous field of type Human
238 | school string
239 | }
240 |
241 | type Employee struct {
242 | Human //an anonymous field of type Human
243 | company string
244 | }
245 |
246 | //A human method to say hi
247 | func (h *Human) SayHi() {
248 | fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
249 | }
250 |
251 | func main() {
252 | mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
253 | sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
254 |
255 | mark.SayHi()
256 | sam.SayHi()
257 | }
258 |
259 | Output:
260 |
261 | .. container:: output
262 |
263 | | Hi, I am Mark you can call me on 222-222-YYYY
264 | | Hi, I am Sam you can call me on 111-888-XXXX
265 |
266 | .. admonition:: Philosophy
267 |
268 | Think about it: you often need to represent *things* that share some
269 | *attributes* or *characteristics*, this is solved with the anonymous field
270 | mechanism. And when you need to represent a shared *behavior* or
271 | *functionality*, you can use a method on an anonymous field.
272 |
273 | Overriding a method
274 | ===================
275 | What if you want the ``Employee`` to tell you where he works as well?
276 | Easy, the same rule for overriding fields on conflicts applies for methods,
277 | and we happily exploit this fact:
278 |
279 | .. code-block:: go
280 | :linenos:
281 |
282 | package main
283 | import "fmt"
284 |
285 | type Human struct {
286 | name string
287 | age int
288 | phone string
289 | }
290 |
291 | type Student struct {
292 | Human //an anonymous field of type Human
293 | school string
294 | }
295 |
296 | type Employee struct {
297 | Human //an anonymous field of type Human
298 | company string
299 | }
300 |
301 | //A human method to say hi
302 | func (h *Human) SayHi() {
303 | fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
304 | }
305 |
306 | //Employee's method overrides Human's one
307 | func (e *Employee) SayHi() {
308 | fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
309 | e.company, e.phone) //Yes you can split into 2 lines here.
310 | }
311 |
312 | func main() {
313 | mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
314 | sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
315 |
316 | mark.SayHi()
317 | sam.SayHi()
318 | }
319 |
320 | Output:
321 |
322 | .. container:: output
323 |
324 | | Hi, I am Mark you can call me on 222-222-YYYY
325 | | Hi, I am Sam, I work at Golang Inc. Call me on 111-888-XXXX
326 |
327 | And... It worked like a charm!
328 |
329 | With these simple concepts, you can now design shorter, nicer and expressive
330 | programs. In the next chapter we will learn how to enhance this experience even
331 | more with a new notion: Interfaces.
332 |
333 |
--------------------------------------------------------------------------------
/basic.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | The basic things
4 | ****************
5 | In the previous chapter, we saw that Go programs are organized using *packages*
6 | and that Go natively supports UTF-8 for strings and identifiers. In this chapter
7 | we will see how to declare and use variables and constants and the different Go
8 | built-in types.
9 |
10 |
11 | How to declare a variable?
12 | ==========================
13 | There are several ways to declare a variable in Go.
14 |
15 | The basic form is:
16 |
17 | .. code-block:: go
18 |
19 | // declare a variable named "variable_name" of type "type"
20 | var variable_name type
21 |
22 | You can declare several variables of the same type in a single line, by
23 | separating them with commas.
24 |
25 | .. code-block:: go
26 |
27 | // declare variables var1, var2, and var3 all of type type
28 | var var1, var2, var3 type
29 |
30 | And you can initialize a variable when declaring it too
31 |
32 | .. code-block:: go
33 |
34 | /* declare a variable named "variable_name" of type "type" and initialize it
35 | to value*/
36 | var variable_name type = value
37 |
38 | You can even initialize many variables that are declared in the same statement
39 |
40 | .. code-block:: go
41 |
42 | /* declare a var1, var2, var3 of type "type" and initialize them to value1,
43 | value2, and value3 respectively*/
44 | var var1, var2, var3 type = value1, value2, value3
45 |
46 | Guess what? You can omit the type and it will be inferred from the initializers
47 |
48 | .. code-block:: go
49 |
50 | /* declare and initialize var1, var2 and var3 and initialize them
51 | respectively to value1, value2, and value3. /
52 | var var1, var2, var3 = value1, value2, value3
53 |
54 | Even shorter, inside a function body (let me repeat that: only inside a function
55 | body) you can even drop the keyword ``var`` and use the ``:=`` instead of ``=``
56 |
57 | .. code-block:: go
58 |
59 | // omit var and type, and use ':=' instead of '=' inside the function body
60 | func test(){
61 | var1, var2, var3 := value1, value2, value3
62 | }
63 |
64 | Don't worry. It's actually easy. The examples with the builtin types, below,
65 | will illustrate both of these forms. Just remember that, unlike the C way, in Go
66 | the type is put at the end of the declaration and -should I repeat it?- **that
67 | the := operator can only be used inside a function body**.
68 |
69 | .. _primitive-types:
70 |
71 | The builtin types
72 | =================
73 |
74 | Boolean
75 | -------
76 | For boolean truth values, Go has the type ``bool`` (like the C++ one) that takes
77 | one of the values: ``true`` or ``false``.
78 |
79 | .. code-block:: go
80 | :linenos:
81 |
82 | //Example snippet
83 | var active bool //basic form
84 | var enabled, disabled = true, false //type omitted, variables initialized
85 | func test(){
86 | var available bool //general form
87 | valid := false //type and var omitted, and variable initialized
88 | available = true //normal assignation
89 | }
90 |
91 |
92 | Numeric types
93 | -------------
94 | For integer values, signed and unsigned, Go has ``int`` and ``uint`` both having
95 | the appropriate length for your machine (32 or 64 bits) But there's also
96 | explicit sized ints: ``int8``, ``int16``, ``int32``, ``int64`` and ``byte``,
97 | ``uint8``, ``uint16``, ``uint32``, ``uint64``. With ``byte`` being an alias for
98 | ``uint8``.
99 |
100 | For floating point values, we have ``float32`` and ``float64``.
101 |
102 | Wait that's not all, Go has native support for complex numbers too! In fact, you
103 | can use ``complex64`` for numbers with 32 bits for the real part and 32 bits
104 | for the imaginary part, and there is ``complex128`` for numbers with 64 bits for
105 | the real part and 64 bits for the imaginary part.
106 |
107 | Table of numeric types
108 | ^^^^^^^^^^^^^^^^^^^^^^
109 |
110 | From the `Go Programming Language Specification`_
111 |
112 | +----------+----------------------------------------------------------------------------------------+
113 | |Type | Values |
114 | +==========+========================================================================================+
115 | |uint8 | the set of all unsigned 8-bit integers (0 to 255) |
116 | +----------+----------------------------------------------------------------------------------------+
117 | |uint16 | the set of all unsigned 16-bit integers (0 to 65535) |
118 | +----------+----------------------------------------------------------------------------------------+
119 | |uint32 | the set of all unsigned 32-bit integers (0 to 4294967295) |
120 | +----------+----------------------------------------------------------------------------------------+
121 | |uint64 | the set of all unsigned 64-bit integers (0 to 18446744073709551615) |
122 | +----------+----------------------------------------------------------------------------------------+
123 | | |
124 | +----------+----------------------------------------------------------------------------------------+
125 | |int8 | the set of all signed 8-bit integers (-128 to 127) |
126 | +----------+----------------------------------------------------------------------------------------+
127 | |int16 | the set of all signed 16-bit integers (-32768 to 32767) |
128 | +----------+----------------------------------------------------------------------------------------+
129 | |int32 | the set of all signed 32-bit integers (-2147483648 to 2147483647) |
130 | +----------+----------------------------------------------------------------------------------------+
131 | |int64 | the set of all signed 64-bit integers (-9223372036854775808 to 9223372036854775807) |
132 | +----------+----------------------------------------------------------------------------------------+
133 | | |
134 | +----------+----------------------------------------------------------------------------------------+
135 | |float32 | the set of all IEEE-754 32-bit floating-point numbers |
136 | +----------+----------------------------------------------------------------------------------------+
137 | |float64 | the set of all IEEE-754 64-bit floating-point numbers |
138 | +----------+----------------------------------------------------------------------------------------+
139 | | |
140 | +----------+----------------------------------------------------------------------------------------+
141 | |complex64 | the set of all complex numbers with float32 real and imaginary parts |
142 | +----------+----------------------------------------------------------------------------------------+
143 | |complex128| the set of all complex numbers with float64 real and imaginary parts |
144 | +----------+----------------------------------------------------------------------------------------+
145 | | |
146 | +----------+----------------------------------------------------------------------------------------+
147 | | byte familiar alias for uint8 |
148 | +----------+----------------------------------------------------------------------------------------+
149 |
150 |
151 | .. code-block:: go
152 | :linenos:
153 |
154 | //Example snippet
155 | var i int32 //basic form with a int32
156 | var x, y, z = 1, 2, 3 //type omitted, variables initialized
157 | func test(){
158 | var pi float32 //basic form
159 | one, two, three := 1, 2, 3 //type and var omitted, variables initialized
160 | c := 10+3i // a complex number, type infered and keyword 'var' omitted.
161 | pi = 3.14 // normal assignation
162 | }
163 |
164 | Strings
165 | -------
166 | As seen in the previous chapter, strings are in UTF-8 and they are enclosed
167 | between two double quotes (") and their type is -you bet!- ``string``.
168 |
169 | .. code-block:: go
170 | :linenos:
171 |
172 | //Example snippet
173 | var french_hello string //basic form
174 | var empty_string string = "" // here empty_string (like french_hello) equals ""
175 | func test(){
176 | no, yes, maybe := "no", "yes", "maybe" //var and type omitted
177 | japanese_hello := "Ohaiou" //type inferred, var keyword omitted
178 | french_hello = "Bonjour" //normal assignation
179 | }
180 |
181 | Constants
182 | =========
183 | In Go, constants are -uh- constant values created at compile time, and they
184 | can be: numbers, boolean or strings.
185 |
186 | The syntax to declare a constant is:
187 |
188 | .. code-block:: go
189 |
190 | const constant_name = value
191 |
192 | Some examples:
193 |
194 | .. code-block:: go
195 | :linenos:
196 |
197 | //example snippet
198 | const i = 100
199 | const pi = 3.14
200 | const prefix = "go_"
201 |
202 | Facilities
203 | ==========
204 |
205 | Grouping declarations
206 | ---------------------
207 | Multiple ``var``, ``const`` and ``import`` declarations can be grouped using
208 | parenthesis.
209 |
210 | So instead of writing:
211 |
212 | .. code-block:: go
213 | :linenos:
214 |
215 | //example snippet
216 | import "fmt"
217 | import "os"
218 |
219 | const i = 100
220 | const pi = 3.14
221 | const prefix = "go_"
222 |
223 | var i int
224 | var pi = float32
225 | var prefix string
226 |
227 | You can write:
228 |
229 | .. code-block:: go
230 | :linenos:
231 |
232 | //example snippet with grouping
233 | import(
234 | "fmt"
235 | "os"
236 | )
237 |
238 | const(
239 | i = 100
240 | pi = 3.14
241 | prefix = "go_"
242 | )
243 |
244 | var(
245 | i int
246 | pi = float32
247 | prefix string
248 | )
249 |
250 |
251 | *Of course*, you group consts with consts, vars with vars and imports with imports
252 | but you can not mix them in the same group!
253 |
254 | iota and enumerations
255 | ---------------------
256 | Go provides the keyword ``iota`` that can be used when declaring enumerated
257 | constants, This keyword yelds an incremented value by 1, starting from 0, each
258 | time it is used.
259 |
260 | Example:
261 |
262 | .. code-block:: go
263 | :linenos:
264 |
265 | //example snippet
266 | const(
267 | x = iota //x == 0
268 | y = iota //y == 1
269 | z = iota //z == 2
270 | w // implicitely w == iota, therefore: w == 3
271 | )
272 |
273 |
274 | Well, that's it for this chapter. I told you, it won't be hard. In fact, Go
275 | eases variable declarations a lot. You'd almost feel like coding with a
276 | scripting language like python --and it's even better.
277 |
278 | .. external links and footnotes:
279 |
280 | .. _Go Programming Language Specification: http://golang.com/doc/go_spec.html#Numeric_types
281 |
--------------------------------------------------------------------------------
/control.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | Basic Control flow
4 | ******************
5 | In the previous chapter, we learned how to declare variables and constants.
6 | We also saw the different basic, builtin types that come with Go. In this
7 | chapter, we will see the basic control constructions, or how to *reason about*
8 | this data. But before that, let's talk about comments and semicolons.
9 |
10 | Comments
11 | ========
12 | You probably noticed in the example snippets given in previous chapters, some
13 | comments. Didn't you?
14 | Go has the same commenting conventions as in C++. That is:
15 |
16 | * Single line comments: Everything from ``//`` until the end of the line is a
17 | comment.
18 | * bloc comments: Everything betwwen ``/*`` and ``*/`` is a comment.
19 |
20 | .. code-block:: go
21 | :linenos:
22 |
23 | //Single line comment, this is ignored by the compiler.
24 | /* Everything from the beginning of this line until the keyword 'var' on
25 | line 4 is a comment and ignored by the compiler. */
26 | var(
27 | integer int
28 | pi = float32
29 | prefix string
30 | )
31 |
32 | Semicolons
33 | ==========
34 | If you've programmed with C, or C++, or Pascal, you might wonder why, in the
35 | previous examples, there weren't any semicolons.
36 | In fact, you don't need them in Go. Go automatically inserts semicolons on every
37 | line end that looks like the end of a statement.
38 |
39 | And this makes the code a lot cleaner, and easy on the eyes.
40 |
41 | The only place you will typically see semicolons is separating the clauses of
42 | for loops and the like; they are not necessary after every statement.
43 |
44 | Note that you can use semicolons to separate several statements written on a
45 | single line.
46 |
47 | The one surprise is that it's important to put the opening brace of a construct
48 | such as an if statement on the same line as the if; if you don't, there are
49 | situations that may not compile or may give the wrong result [#f1]_
50 |
51 | Ok let's begin, now.
52 |
53 | The if statement
54 | ================
55 | Perhaps the most well-known statement type in imperative programming. And it can
56 | be summarized like this: if condition met, do this, else do that.
57 |
58 | In Go, you don't need parenthesis for the condition.
59 |
60 | .. code-block:: go
61 | :linenos:
62 |
63 | if x > 10 {
64 | fmt.Println("x is greater than 10")
65 | } else {
66 | fmt.Println("x is less than 10")
67 | }
68 |
69 | You can also have a leading initial short statement before the condition too.
70 |
71 | .. code-block:: go
72 | :linenos:
73 |
74 | // Compute the value of x, and then compare it to 10.
75 | if x := computed_value(); x > 10 {
76 | fmt.Println("x is greater than 10")
77 | } else {
78 | fmt.Println("x is less than 10")
79 | }
80 |
81 | You can combine multiple if/else statements.
82 |
83 | .. code-block:: go
84 | :linenos:
85 |
86 | if integer == 3 {
87 | fmt.Println("The integer is equal to 3")
88 | } else if integer < 3 {
89 | fmt.Println("The integer is less than 3")
90 | } else {
91 | fmt.Println("The integer is greater than 3")
92 | }
93 |
94 | The for statement
95 | =================
96 | The ``for`` statement is used to iterate and loop.
97 | Its general syntax is:
98 |
99 | .. code-block:: go
100 | :linenos:
101 |
102 | for expression1; expression2; expression3{
103 | ...
104 | }
105 |
106 | Gramatically, ``expression1``, ``expression2``, and ``expression3`` are
107 | expressions, where ``expression1``, and ``expression3`` are used for
108 | assignements or function calls (``expression1`` before starting the loop, and
109 | ``expression3`` at the end of every iteration) and ``expression2`` is used to
110 | determine whether to continue or stop the iterations.
111 |
112 | An example would be better than the previous paragraph, right? Here we go!
113 |
114 | .. code-block:: go
115 | :linenos:
116 |
117 | package main
118 | import "fmt"
119 |
120 | func main(){
121 | sum := 0;
122 | for index:=0; index < 10 ; index++ {
123 | sum += index
124 | }
125 | fmt.Println("sum is equal to ", sum)
126 | }
127 |
128 | In the code above we initalize our variable ``sum`` to 0. The ``for`` loop by
129 | is begun by initializing the variable ``index`` to 0 (``index:=0``).
130 |
131 | Next the ``for`` loop's body is executed (``sum += i``) *while* the condition
132 | ``index < 10`` is true.
133 |
134 | At the end of each iteration the ``for`` loop will execute the ``index++``
135 | expression (eg. increments ``index``).
136 |
137 | You might guess that the output from the previous program would be:
138 |
139 | .. container:: output
140 |
141 | | sum is equal to 45
142 |
143 | And you would be correct!
144 | Because the sum is 0+1+2+3+4+5+6+7+8+9 which equals 45.
145 |
146 | **Question:**
147 |
148 | Is it possible to combine lines 5 and 6 into a single one, in the previous
149 | program? How?
150 |
151 | Actually ``expression1``, ``expression2``, and ``expression3`` are all optional.
152 | This means you can omit, one, two or all of them in a ``for`` loop. If you omit
153 | ``expression1`` or ``expression3`` it means they simply won't be executed. If
154 | you omit ``expression2`` that'd mean that it is always true and that the loop
155 | will iterate forever -- unless a ``break`` statement is encountered.
156 |
157 | Since these expressions may be omitted, you can have something like:
158 |
159 | .. code-block:: go
160 | :linenos:
161 |
162 | //expression1 and expression3 are omitted here
163 | sum := 1
164 | for ; sum < 1000; {
165 | sum += sum
166 | }
167 |
168 | Which can be simplified by removing the semicolons:
169 |
170 | .. code-block:: go
171 | :linenos:
172 |
173 | //expression1 and expression3 are omitted here, and semicolons gone.
174 | sum := 1
175 | for sum < 1000 {
176 | sum += sum
177 | }
178 |
179 | Or when even expression2 is omitted also, we can have something like:
180 |
181 | .. code-block:: go
182 | :linenos:
183 |
184 | //infinite loop, no semicolons at all.
185 | for {
186 | fmt.Println("I loop for ever!")
187 | }
188 |
189 | break and continue
190 | ==================
191 |
192 | With ``break`` you can stop loops early. i.e. finish the loop even if the
193 | condition expressed by ``expression2`` is still true.
194 |
195 | .. code-block:: go
196 | :linenos:
197 |
198 | for index := 10; index>0; index-- {
199 | if index < 5{
200 | break
201 | }
202 | fmt.Println(index)
203 | }
204 |
205 | The previous snippet says: loop from 10 to 0 printing the numbers (line 6); but
206 | if i<5 then break (stop) the loop!
207 | Hence, the program will print the numbers: 10, 9, 8, 7, 6, 5.
208 |
209 | ``continue``, on the other hand will just break the current iteration and
210 | *skips* to the next one.
211 |
212 | .. code-block:: go
213 | :linenos:
214 |
215 | for index := 10; index > 0; index-- {
216 | if index == 5 {
217 | continue
218 | }
219 | fmt.Println(index)
220 | }
221 |
222 | Here the program will print all the numbers from 10 down to 1, except 5! Because
223 | on line 3, the condition ``if index == 5`` will be ``true`` so ``continue``
224 | will be executed and the ``fmt.Println(index) (for index == 5)`` won't be run.
225 |
226 | The switch statement
227 | ====================
228 | Sometimes, you'll need to write a complicated chain of ``if``/``else`` tests.
229 | And the code becomes ugly and hard to read and maintain. The ``switch``
230 | statement, makes it look nicer and easier to read.
231 |
232 | Go's switch is more flexible than its C equivalent, because the case expression
233 | need not to be constants or even integers.
234 |
235 | The general form of a switch statement is
236 |
237 | .. code-block:: go
238 | :linenos:
239 |
240 | // General form of a switch statement:
241 | switch sExpr {
242 | case expr1:
243 | some instructions
244 | case expr2:
245 | some other instructions
246 | case expr3:
247 | some other instructions
248 | default:
249 | other code
250 | }
251 |
252 | The type of ``sExpr`` and the expressions ``expr1``, ``expr2``, ``expr3``...
253 | type should match. i.e. if ``var`` is of type ``int`` the cases expressions should
254 | be of type ``int`` also!
255 |
256 | Of course, you can have as many cases you want.
257 |
258 | Multiple match expressions can be used, each separated by commas in the case
259 | statement.
260 |
261 | If there is no ``sExpr`` at all, then by default it's *bool* and so should be
262 | the cases expressions.
263 |
264 | If more than one case statements match, then the first in lexical order is
265 | executed.
266 |
267 | The *default* case is optional and can be anywhere within the switch block,
268 | not necessarily the last one.
269 |
270 | Unlike certain other languages, each case block is independent and code does not
271 | "fall through" (each of the case code blocks are like independent if-else-if
272 | code blocks. There is a fallthrough statement that you can explicitly use to
273 | obtain fall through behavior if desired.)
274 |
275 | Some switch examples:
276 | ---------------------
277 |
278 | .. code-block:: go
279 | :linenos:
280 |
281 | // Simple switch statement example:
282 | i := 10
283 | switch i {
284 | case 1:
285 | fmt.Println("i is equal to 1")
286 | case 2, 3, 4:
287 | fmt.Println("i is equal to 2, 3 or 4")
288 | case 10:
289 | fmt.Println("i is equal to 10")
290 | default:
291 | fmt.Println("All I know is that i is an integer")
292 | }
293 |
294 | In this snippet, we initialized ``index`` to 10, but in practice, you should
295 | think of ``index`` as a computed value (result of a function or some other
296 | calculus before the switch statement)
297 |
298 | Notice that in line 6, we grouped some expressions (2, 3, and 4) in a single
299 | case statement.
300 |
301 | .. code-block:: go
302 | :linenos:
303 |
304 | // Switch example without sExpr
305 | index := 10
306 | switch {
307 | case index < 10:
308 | fmt.Println("The index is less than 10")
309 | case index > 10, index < 0:
310 | fmt.Println("The index is either bigger than 10 or less than 0")
311 | case index == 10:
312 | fmt.Println("The index is equal to 10")
313 | default:
314 | fmt.Println("This won't be printed anyway")
315 | }
316 |
317 | Now, in this example, we omitted ``sExpr`` of the general form. So the cases
318 | expressions should be of type *bool*. And so they are! (They're comparisons that
319 | return either ``true`` or ``false``)
320 |
321 | **Question**:
322 |
323 | Can you tell why the ``default`` case on line 10 will never be reached?
324 |
325 |
326 | .. code-block:: go
327 | :linenos:
328 |
329 | //switch example with fallthrough
330 | integer := 6
331 | switch integer {
332 | case 4:
333 | fmt.Println("The integer was <= 4")
334 | fallthrough
335 | case 5:
336 | fmt.Println("The integer was <= 5")
337 | fallthrough
338 | case 6:
339 | fmt.Println("The integer was <= 6")
340 | fallthrough
341 | case 7:
342 | fmt.Println("The integer was <= 7")
343 | fallthrough
344 | case 8:
345 | fmt.Println("The integer was <= 8")
346 | fallthrough
347 | default:
348 | fmt.Println("default case")
349 | }
350 |
351 | In this example, the case on line 10 matches, but since there is
352 | ``fallthrough``, the code for ``case 7:`` and so on will also be executed
353 | (just like a C switch that doesn't use the ``break`` keyword).
354 |
355 |
356 | .. [#f1] http://golang.org/doc/go_tutorial.html#tmp_33
357 |
--------------------------------------------------------------------------------
/more-interfaces.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | More on interfaces
4 | ******************
5 | We discovered the magic of interfaces in the previous chapter, how a simple
6 | concept as defining a type's behavior can offer tremendous opportunities.
7 |
8 | If you haven't read the previous chapter, you shouldn't read this one, simply
9 | because most of what we're about to study depends on a good understanding of the
10 | previous chapter.
11 |
12 | Shall we begin?
13 |
14 | Knowing what is stored in a interface variable
15 | ==============================================
16 | We know that a variable of a given interface can store any value of any type
17 | that implements this interface. That's the good part, but what if we wanted to
18 | retrieve a value stored in an interface variable and put it in a regular type
19 | variable, how do we know what exact type was "wrapped" in that interface
20 | variable?
21 |
22 | Let's see an example to clarify the actual question:
23 |
24 | .. code-block:: go
25 | :linenos:
26 |
27 | type Element interface{}
28 | type List [] Element
29 |
30 | //...
31 |
32 | func main() {
33 | //...
34 | var number int
35 | element := list[index]
36 | // The question is how do I convert 'element' to int, in order to assign
37 | // it to number and is the value boxed in 'element' actually an int?
38 | //...
39 | }
40 |
41 | So, the question confronting us is:
42 |
43 | How do we test the type that is stored in an interface variable?
44 |
45 | Comma-ok type assertions
46 | ------------------------
47 | Go comes with a handy syntax to know whether it is possible to convert an
48 | interface value to a given type value, it's as easy as this: ``value, ok =
49 | element.(T)``, where ``value`` is a variable of type ``T``, ``ok`` is a boolean,
50 | and ``element`` is the interface variable.
51 |
52 | If it is possible to convert ``element`` to type ``T``, then ``ok`` is set to
53 | ``true``, and ``value`` is set to the result of this conversion.
54 | Otherwise, ``ok`` is set to ``false`` and ``value`` is set to the *zero value*
55 | of ``T``.
56 |
57 | Let's use this comma-ok type assertion in an example:
58 |
59 | .. code-block:: go
60 | :linenos:
61 |
62 | package main
63 |
64 | import (
65 | "fmt"
66 | "strconv" //for conversions to and from string
67 | )
68 |
69 | type Element interface{}
70 | type List [] Element
71 |
72 | type Person struct {
73 | name string
74 | age int
75 | }
76 |
77 | //For printng. See previous chapter.
78 | func (p Person) String() string {
79 | return "(name: " + p.name + " - age: "+strconv.Itoa(p.age)+ " years)"
80 | }
81 |
82 | func main() {
83 | list := make(List, 3)
84 | list[0] = 1 // an int
85 | list[1] = "Hello" // a string
86 | list[2] = Person{"Dennis", 70}
87 |
88 | for index, element := range list {
89 | if value, ok := element.(int); ok {
90 | fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
91 | } else if value, ok := element.(string); ok {
92 | fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
93 | } else if value, ok := element.(Person); ok {
94 | fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)
95 | } else {
96 | fmt.Printf("list[%d] is of a different type\n", index)
97 | }
98 | }
99 | }
100 |
101 | Output:
102 |
103 | .. container:: output
104 |
105 | | list[0] is an int and its value is 1
106 | | list[1] is a string and its value is Hello
107 | | list[2] is a Person and its value is (name: Dennis - age: 70 years)
108 |
109 | It's that simple!
110 |
111 | Notice the syntax we used with our ``if``\s? I hope that you still remember that
112 | you can initialize inside an ``if``! Do you??
113 |
114 | Yes, I know, the more we test for other types, the more the ``if``/``else``
115 | chain gets harder to read. And this is why they invented the *type switch*!
116 |
117 | The type switch test
118 | --------------------
119 | Better to show it off with an example, right? Ok, let's rewrite the previous
120 | example. Here we Go!
121 |
122 | .. code-block:: go
123 | :linenos:
124 |
125 | package main
126 |
127 | import (
128 | "fmt"
129 | "strconv" //for conversions to and from string
130 | )
131 |
132 | type Element interface{}
133 | type List [] Element
134 |
135 | type Person struct {
136 | name string
137 | age int
138 | }
139 |
140 | //For printng. See previous chapter.
141 | func (p Person) String() string {
142 | return "(name: " + p.name + " - age: "+strconv.Itoa(p.age)+ " years)"
143 | }
144 |
145 | func main() {
146 | list := make(List, 3)
147 | list[0] = 1 //an int
148 | list[1] = "Hello" //a string
149 | list[2] = Person{"Dennis", 70}
150 |
151 | for index, element := range list{
152 | switch value := element.(type) {
153 | case int:
154 | fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
155 | case string:
156 | fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
157 | case Person:
158 | fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)
159 | default:
160 | fmt.Println("list[%d] is of a different type", index)
161 | }
162 | }
163 | }
164 |
165 | Output:
166 |
167 | .. container:: output
168 |
169 | | list[0] is an int and its value is 1
170 | | list[1] is a string and its value is Hello
171 | | list[2] is a Person and its value is (name: Dennis - age: 70 years)
172 |
173 | Now repeat after me:
174 |
175 | "The ``element.(type)`` construct SHOULD NOT be used outside of a switch
176 | statement! -- Can you use it elsewhere? -- **NO, YOU CAN NOT!**"
177 |
178 | If you need to make a single test, use the comma-ok test.
179 | Just DON'T use ``element.(type)`` outside of a switch statement.
180 |
181 | Embedding interfaces
182 | ====================
183 | What's really nice with Go is the *logic* side of its syntax. When we learnt
184 | about anonymous fields in ``struct``\s we found it quite natural, didn't we?
185 | Now, by applying the same logic, wouldn't it be nice to be able to embed an
186 | interface ``interface1`` within another interface ``interface2`` so that
187 | ``interface2`` "inherits" the methods in ``interface1``?
188 |
189 | I say "logic", because after all: interfaces are sets of methods,
190 | just like structs are sets of fields. And so it is!
191 | In Go you can put an interface type into another.
192 |
193 | **Example**: Suppose that you have an indexed collections of elements, and that
194 | you want to get the minimum, and the maximum value of this collection without
195 | changing the elements order in this collection.
196 |
197 | One silly but illustrative way to do this is by using the ``sort.Interface`` we
198 | saw in the previous chapter. But then again, the function ``sort.Sort`` provided
199 | by the sort package actually changes the input collection!
200 |
201 | We add two methods: ``Get`` and ``Copy``:
202 |
203 | .. code-block:: go
204 | :linenos:
205 |
206 | package main
207 |
208 | import (
209 | "fmt"
210 | "strconv"
211 | "sort"
212 | )
213 |
214 | type Person struct {
215 | name string
216 | age int
217 | phone string
218 | }
219 |
220 | type MinMax interface {
221 | sort.Interface
222 | Copy() MinMax
223 | Get(i int) interface{}
224 | }
225 |
226 | func (h Person) String() string {
227 | return "(name: " + h.name + " - age: "+strconv.Itoa(h.age)+ " years)"
228 | }
229 |
230 | type People []Person // People is a type of slices that contain Persons
231 |
232 | func (g People) Len() int {
233 | return len(g)
234 | }
235 |
236 | func (g People) Less(i, j int) bool {
237 | if g[i].age < g[j].age {
238 | return true
239 | }
240 | return false
241 | }
242 |
243 | func (g People) Swap(i, j int) {
244 | g[i], g[j] = g[j], g[i]
245 | }
246 |
247 | func (g People) Get(i int) interface{} {return g[i]}
248 |
249 | func (g People) Copy() MinMax {
250 | c := make(People, len(g))
251 | copy(c, g)
252 | return c
253 | }
254 |
255 | func GetMinMax(C MinMax) (min, max interface{}) {
256 | K := C.Copy()
257 | sort.Sort(K)
258 | min, max = K.Get(0), K.Get(K.Len()-1)
259 | return
260 | }
261 |
262 | func main() {
263 | group := People {
264 | Person{name:"Bart", age:24},
265 | Person{name:"Bob", age:23},
266 | Person{name:"Gertrude", age:104},
267 | Person{name:"Paul", age:44},
268 | Person{name:"Sam", age:34},
269 | Person{name:"Jack", age:54},
270 | Person{name:"Martha", age:74},
271 | Person{name:"Leo", age:4},
272 | }
273 |
274 | //Let's print this group as it is
275 | fmt.Println("The unsorted group is:")
276 | for _, value := range group {
277 | fmt.Println(value)
278 | }
279 |
280 | //Now let's get the older and the younger
281 | younger, older := GetMinMax(group)
282 | fmt.Println("\n➞ Younger is", younger)
283 | fmt.Println("➞ Older is ", older)
284 |
285 | //Let's print this group again
286 | fmt.Println("\nThe original group is still:")
287 | for _, value := range group {
288 | fmt.Println(value)
289 | }
290 | }
291 |
292 | Output:
293 |
294 | .. container:: output
295 |
296 | | The unsorted group is:
297 | | (name: Bart - age: 24 years)
298 | | (name: Bob - age: 23 years)
299 | | (name: Gertrude - age: 104 years)
300 | | (name: Paul - age: 44 years)
301 | | (name: Sam - age: 34 years)
302 | | (name: Jack - age: 54 years)
303 | | (name: Martha - age: 74 years)
304 | | (name: Leo - age: 4 years)
305 | |
306 | | ➞ Younger is (name: Leo - age: 4 years)
307 | | ➞ Older is (name: Gertrude - age: 104 years)
308 | |
309 | | The original group is still:
310 | | (name: Bart - age: 24 years)
311 | | (name: Bob - age: 23 years)
312 | | (name: Gertrude - age: 104 years)
313 | | (name: Paul - age: 44 years)
314 | | (name: Sam - age: 34 years)
315 | | (name: Jack - age: 54 years)
316 | | (name: Martha - age: 74 years)
317 | | (name: Leo - age: 4 years)
318 |
319 | The example is idiotic (the opposite of idiomatic!) but it *did* work as desired.
320 | Mind you, interface embedding can be very useful, you can find some interface
321 | embedding in some Go packages as well.
322 | For example, the `container/heap`_ package that provides heap operations
323 | of data collections that implement this interface:
324 |
325 | .. code-block:: go
326 | :linenos:
327 |
328 | //heap.Interface
329 | type Interface interface {
330 | sort.Interface //embeds sort.Interface
331 | Push(x interface{}) //a Push method to push elements into the heap
332 | Pop() interface{} //a Pop elements that pops elements from the heap
333 | }
334 |
335 | Another example is the `io.ReadWriter`_ interface that is a combination of two
336 | interfaces: `io.Reader`_ and `io.Writer`_ both also defined in the ``io``
337 | package:
338 |
339 | .. code-block:: go
340 | :linenos:
341 |
342 | // io.ReadWriter
343 | type ReadWriter interface {
344 | Reader
345 | Writer
346 | }
347 |
348 | Types that implement io.ReadWriter can read and write since they implement both
349 | Reader and Writer interfaces.
350 |
351 | Did I mention yet to make sure you *never* use ``element.(type)`` outside of a
352 | switch statement?
353 |
354 | .. external links and footnotes:
355 |
356 | .. _container/heap: http://golang.org/pkg/container/heap
357 | .. _io.ReadWriter: http://golang.org/pkg/io/index.html#ReadWriter
358 | .. _io.Reader: http://golang.org/pkg/io/index.html#Reader
359 | .. _io.Writer: http://golang.org/pkg/io/index.html#Writer
360 |
--------------------------------------------------------------------------------
/_theme/gobook/static/default.css:
--------------------------------------------------------------------------------
1 | /*
2 | @font-face {
3 | font-family:Rancho;
4 | src:url('fonts/Rancho/Rancho-Regular.ttf');
5 | }
6 | */
7 | @import url(http://fonts.googleapis.com/css?family=Rancho);
8 |
9 | * {
10 | margin:0;
11 | padding:0;
12 | border:0;
13 | }
14 |
15 | body {
16 | margin:0;
17 | background:#503e2a;
18 | background:#4b0000;
19 | background: -moz-linear-gradient(top, #100000 0%, #4b0000 40%); /* FF3.6+ */
20 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#100000), color-stop(40%,#4b0000)); /* Chrome,Safari4+ */
21 | background: -webkit-linear-gradient(top, #100000 0%,#4b0000 40%); /* Chrome10+,Safari5.1+ */
22 | background: -o-linear-gradient(top, #100000 0%,#4b0000 40%); /* Opera 11.10+ */
23 | background: -ms-linear-gradient(top, #100000 0%,#4b0000 40%); /* IE10+ */
24 | background: linear-gradient(top, #100000 0%,#4b0000 40%); /* W3C */
25 | font:12px/1.5 Verdana,sans-serif;
26 | color:white;
27 | text-align:left;
28 | }
29 |
30 | figure, footer, header, nav, section, figcaption {
31 | display:block;
32 | }
33 |
34 | #wrapper {
35 | width:960px;
36 | margin:0px auto;
37 | }
38 |
39 | #main {
40 | float:left;
41 | margin:0;
42 | width:640px;
43 | font-size:1em;
44 | color:#000;
45 | }
46 |
47 | #main > section {
48 | padding:20px;
49 | background-color:#fff;
50 | min-height:600px;
51 | -moz-box-shadow:#100000 0 0 10px;
52 | -webkit-box-shadow:#100000 0 0 10px;
53 | }
54 |
55 | #sidebar {
56 | float:right;
57 | margin:0;
58 | width:280px;
59 | font-size:1em;
60 | background-color:transparent;
61 | color:#fff;
62 | padding:30px 10px 0px 20px;
63 | text-align:left;
64 | text-shadow:#000000 1px 1px 1px;
65 | }
66 |
67 | header {
68 | padding:4px 0 12px 0;
69 | }
70 |
71 | footer {
72 | color:#f9f0bf;
73 | font-size:90%;
74 | padding-bottom:2em;
75 | text-align:right
76 | }
77 |
78 | /*** links ***/
79 | a {
80 | text-decoration:none;
81 | }
82 |
83 | a:link, a:visited {
84 | color:#ffffbf;
85 | }
86 |
87 | img {
88 | margin:10px;
89 | }
90 |
91 | a img {
92 | border:none;
93 | }
94 |
95 | #main a:link, #main a:visited {
96 | color:#08519c;
97 | }
98 |
99 | #sidebar a:link, #sidebar a:visited {
100 | color:#f9f05a;
101 | }
102 |
103 | #main a:hover {
104 | text-decoration:underline;
105 | }
106 |
107 | #sidebar a:hover {
108 | color:#f9f0bf;
109 | text-decoration:underline;
110 | }
111 |
112 | h2 a, h3 a, h4 a {
113 | text-decoration:none !important;
114 | }
115 |
116 | a.reference em {
117 | font-style:normal;
118 | }
119 |
120 | a:hover {
121 | text-decoration:underline;
122 | }
123 |
124 | header h1 a {
125 | font-family:Rancho;
126 | color:white;
127 | }
128 |
129 | header nav a:hover{
130 | text-decoration:none;
131 | }
132 |
133 |
134 | #main footer a, #main footer a:link, #main footer a:visited,
135 | #main footer a:hover {
136 | color:#f9f0bf;
137 | }
138 |
139 | /*** sidebar ***/
140 | #sidebar div.sphinxsidebarwrapper {
141 | font-size:92%;
142 | margin-right:14px;
143 | }
144 |
145 | #sidebar h3, #sidebar h4 {
146 | color:white;
147 | font-size:175%;
148 | }
149 |
150 | #sidebar a {
151 | color:white;
152 | }
153 |
154 | #sidebar ul ul {
155 | margin-top:0;
156 | margin-bottom:0;
157 | }
158 |
159 | #sidebar li {
160 | margin-top:0.2em;
161 | margin-bottom:0.2em;
162 | }
163 |
164 | /*** nav ***/
165 | #main nav {
166 | margin:0;
167 | padding:10px;
168 | background-color:#200000;
169 | font-size:11px;
170 | text-align:right;
171 | color:#fff;
172 | -moz-box-shadow:#100000 0 0 10px;
173 | -webkit-box-shadow:#100000 0 0 10px;
174 | }
175 |
176 | #main nav a, #main nav a:link, #main nav a:visited {
177 | color:#f9f0bf;
178 | }
179 |
180 | #main nav a:hover {
181 | text-decoration:underline;
182 | }
183 |
184 | section#main h2{
185 | clear:left;
186 | }
187 |
188 | header h1 {
189 | font-family:Rancho;
190 | color:white;
191 | font-size:48px;
192 | text-shadow:#100000 1px 1px 4px;
193 | }
194 |
195 | header nav {
196 | position:absolute;
197 | top:5px;
198 | margin-left:-5px;
199 | padding:7px 0;
200 | color:#263E2B;
201 | }
202 |
203 | header nav a, header nav a:visited {
204 | color:#fff;
205 | }
206 |
207 | header nav a {
208 | padding:0 4px;
209 | }
210 |
211 | header nav:hover {
212 | color:#fff;
213 | }
214 |
215 | footer {
216 | margin:10px 0;
217 | color:#fff;
218 | text-align:center;
219 | text-shadow:#100000 1px 1px 4px;
220 | }
221 |
222 | /*** content ***/
223 | /*** basic styles ***/
224 | dd {
225 | margin-left:15px;
226 | }
227 |
228 | h1,h2,h3,h4 {
229 | margin-top:1em;
230 | font-family:"Trebuchet MS",sans-serif;
231 | font-family:Rancho;
232 | font-weight:normal;
233 | }
234 |
235 | h1 {
236 | font-size:300%;
237 | margin-top:0.6em;
238 | margin-bottom:.4em;
239 | line-height:1.1em;
240 | color:#67001f;
241 | }
242 |
243 | h2 {
244 | font-size:250%;
245 | margin-bottom:.6em;
246 | line-height:1.2em;
247 | color:#7f2704;
248 | }
249 |
250 | h3 {
251 | font-size:175%;
252 | margin-bottom:.2em;
253 | color:#a63603;
254 | }
255 |
256 | h4 {
257 | font-size:150%;
258 | margin-top:1.5em;
259 | margin-bottom:3px;
260 | color:#f46d43;
261 | }
262 |
263 | div.figure {
264 | text-align:center;
265 | }
266 |
267 | div.figure p.caption {
268 | font-size:1em;
269 | margin-top:0;
270 | margin-bottom:1.5em;
271 | color:#555;
272 | }
273 |
274 | hr {
275 | color:#ccc;
276 | background-color:#ccc;
277 | height:1px;
278 | border:0;
279 | }
280 |
281 | p, ul, dl {
282 | margin-top:.6em;
283 | margin-bottom:1em;
284 | padding-bottom:0.1em;
285 | }
286 |
287 | caption {
288 | font-size:1em;
289 | font-weight:bold;
290 | margin-top:0.5em;
291 | margin-bottom:0.5em;
292 | margin-left:2px;
293 | text-align:center;
294 | }
295 |
296 | blockquote {
297 | padding:0 1em;
298 | margin:1em 0;
299 | border-left:2px solid #94da3a;
300 | }
301 |
302 | strong {
303 | font-weight:bold;
304 | }
305 |
306 | em {
307 | font-style:italic;
308 | }
309 |
310 | ins {
311 | font-weight:bold;
312 | text-decoration:none;
313 | }
314 |
315 | /*** lists ***/
316 | ul {
317 | padding-left:30px;
318 | }
319 |
320 | ol {
321 | padding-left:30px;
322 | }
323 |
324 | ol.arabic li {
325 | list-style-type:decimal;
326 | }
327 |
328 | ul li {
329 | list-style-type:square;
330 | margin-bottom:.4em;
331 | }
332 |
333 | ol li {
334 | margin-bottom:.4em;
335 | }
336 |
337 | ul ul {
338 | padding-left:1.2em;
339 | }
340 |
341 | ul ul ul {
342 | padding-left:1em;
343 | }
344 |
345 | ul.linklist, ul.toc {
346 | padding-left:0;
347 | }
348 |
349 | ul.toc ul {
350 | margin-left:.6em;
351 | }
352 |
353 | ul.toc ul li {
354 | list-style-type:square;
355 | }
356 |
357 | ul.toc ul ul li {
358 | list-style-type:disc;
359 | }
360 |
361 | ul.linklist li, ul.toc li {
362 | list-style-type:none;
363 | }
364 |
365 | dt {
366 | font-weight:bold;
367 | margin-top:.5em;
368 | font-size:1.1em;
369 | }
370 |
371 | dd {
372 | margin-bottom:.8em;
373 | }
374 |
375 | ol.toc {
376 | margin-bottom:2em;
377 | }
378 |
379 | ol.toc li {
380 | font-size:125%;
381 | padding:.5em;
382 | line-height:1.2em;
383 | clear:right;
384 | }
385 |
386 | ol.toc li.b {
387 | background-color:#E0FFB8;
388 | }
389 |
390 | ol.toc li a:hover {
391 | background-color:transparent !important;
392 | text-decoration:underline !important;
393 | }
394 |
395 | ol.toc span.release-date {
396 | float:right;
397 | font-size:85%;
398 | padding-right:.5em;
399 | }
400 |
401 | ol.toc span.comment-count {
402 | font-size:75%;
403 | color:#999;
404 | }
405 |
406 | /*** tables ***/
407 | table {
408 | color:#000;
409 | margin-bottom:1em;
410 | width:100%;
411 | }
412 |
413 | table.docutils td p {
414 | margin-top:0;
415 | margin-bottom:.5em;
416 | }
417 |
418 | table.docutils td, table.docutils th {
419 | border-bottom:1px solid #dfdfdf;
420 | padding:4px 2px;
421 | }
422 |
423 | table.docutils thead th {
424 | border-bottom:2px solid #dfdfdf;
425 | text-align:left;
426 | font-weight:bold;
427 | white-space:nowrap;
428 | }
429 |
430 | table.docutils thead th p {
431 | margin:0;
432 | padding:0;
433 | }
434 |
435 | table.docutils {
436 | border-collapse:collapse;
437 | }
438 |
439 | /*** code blocks ***/
440 | .literal {
441 | white-space:nowrap;
442 | }
443 |
444 | .literal {
445 | color:#aa0000;
446 | }
447 |
448 | #sidebar .literal {
449 | color:white;
450 | background:transparent;
451 | font-size:11px;
452 | }
453 |
454 | h4 .literal {
455 | color:#234f32;
456 | font-size:13px;
457 | }
458 |
459 | pre {
460 | font-size:small;
461 | background:#222;
462 | border:1px solid #111;
463 | border-width:1px 0;
464 | margin:1em 0;
465 | padding:.3em .4em;
466 | overflow:hidden;
467 | line-height:1.3em;
468 | }
469 |
470 | dt .literal, table .literal {
471 | background:none;
472 | }
473 |
474 | #main a.reference tt.literal {
475 | border-bottom:1px #234f32 dotted;
476 | }
477 |
478 | /* Restore colors of pygments hyperlinked code */
479 | #main .highlight .k a:link, #main .highlight .k a:visited {
480 | color:#000000;
481 | text-decoration:none;
482 | border-bottom:1px dotted #000000;
483 | }
484 |
485 | #main .highlight .nf a:link, #main .highlight .nf a:visited {
486 | color:#990000;
487 | text-decoration:none;
488 | border-bottom:1px dotted #990000;
489 | }
490 |
491 | /*** notes & admonitions ***/
492 | .note, .admonition {
493 | padding:.8em 1em .8em;
494 | margin:1em 0;
495 | border:1px solid #fee391;
496 | background:url(note.png) .8em .8em no-repeat;
497 | background-color:#fff7bc;
498 | }
499 |
500 | .admonition-title {
501 | font-weight:bold;
502 | margin-top:0 !important;
503 | margin-bottom:0 !important;
504 | }
505 |
506 | .admonition .last {
507 | margin-bottom:0 !important;
508 | }
509 |
510 | .note, .admonition {
511 | padding-left:65px;
512 | background-image:url(note.png);
513 | }
514 |
515 | div.admonition-philosophy {
516 | padding-left:65px;
517 | background-color:#fff7f3;
518 | border-color:#f4cae4;
519 | background-image:url(philosophy.png);
520 | }
521 |
522 | div.admonition-remember {
523 | padding-left:65px;
524 | background-image::url(remember.png);
525 | }
526 |
527 | /*** versoinadded/changes ***/
528 | div.versionadded, div.versionchanged {
529 | }
530 |
531 | div.versionadded span.title, div.versionchanged span.title {
532 | font-weight:bold;
533 | }
534 |
535 | /*** p-links ***/
536 | a.headerlink {
537 | color:#c60f0f;
538 | font-size:0.8em;
539 | padding:0 4px 0 4px;
540 | text-decoration:none;
541 | visibility:hidden;
542 | }
543 |
544 | h1:hover > a.headerlink, h2:hover > a.headerlink, h3:hover > a.headerlink,
545 | h4:hover > a.headerlink, h5:hover > a.headerlink, h6:hover > a.headerlink,
546 | dt:hover > a.headerlink {
547 | visibility:visible;
548 | }
549 |
550 | /*** index ***/
551 | table.indextable td {
552 | text-align:left;
553 | vertical-align:top;
554 | }
555 |
556 | table.indextable dl, table.indextable dd {
557 | margin-top:0;
558 | margin-bottom:0;
559 | }
560 |
561 | table.indextable tr.pcap {
562 | height:10px;
563 | }
564 |
565 | table.indextable tr.cap {
566 | margin-top:10px;
567 | background-color:#f2f2f2;
568 | }
569 |
570 | /*** page-specific overrides ***/
571 | div#contents ul {
572 | margin-bottom:0;
573 | }
574 |
575 | div#contents ul li {
576 | margin-bottom:0;
577 | }
578 |
579 | div#contents ul ul li {
580 | margin-top:0.3em;
581 | }
582 |
583 | /*** IE hacks ***/
584 | * pre {
585 | width:100%;
586 | }
587 |
588 | .clearboth {
589 | clear:both;
590 | }
591 |
592 | .linenos {
593 | color:#eee;
594 | }
595 |
596 | .centerit, .graphviz {
597 | text-align:center;
598 | display:block;
599 | margin:20px auto;
600 | }
601 |
602 | .output {
603 | border:1px solid #d9d6ad;
604 | background-color:#efeedb;
605 | padding:20px;
606 | margin:10px 0;
607 | }
608 |
609 | .rightfloat {
610 | float:right;
611 | }
612 |
613 | .side {
614 | float:right;
615 | padding:0 0 0 20px;
616 | border-left:3px solid #d9d6ad;
617 | color:#555;
618 | width:250px;
619 | clear:both;
620 | }
621 |
622 | .a{
623 | margin:20px 0;
624 | border:1px solid #eee;
625 | }
626 |
--------------------------------------------------------------------------------
/maps.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | Advanced composite types: Maps
4 | ******************************
5 | This chapter will be lighter than the :doc:`previous one`, so don't
6 | worry, and smile for the perspective of adding a new tool to your box.
7 |
8 | Arrays and slices are wonderful tools for collecting elements of the same type
9 | in a *sequential* fashion.
10 | We simply say: the first element, the second element, ... the **n** :sup:`th`
11 | element of the array or the slice. We can access and modifiy elements using
12 | their numerical integer indices in the ``array`` or the *slice*.
13 |
14 | This is nice and quite useful. Now suppose that we'd like to access and modify
15 | elements given a name of some type (a non-integer name or 'index').
16 | For example: Say we wish to access the definition of the word "Hello" in a
17 | dictionary or to find out the capital of "Japan".
18 |
19 | These category of problems call for a new kind of type.
20 | A type where we can specify a *key* from which a *value* will be stored and
21 | retrieved. It's not about the n\ :sup:`th` element of a sequence, it's about an
22 | *association* of things (keys) with other things (values).
23 |
24 | This kind of types is called a *dict* in Python and *map* in Go and a *hash* in
25 | Ruby.
26 |
27 | How to declare a map?
28 | =====================
29 | The syntax of a map type is: ``map[keyType] valueType``.
30 |
31 | For example:
32 |
33 | .. code-block:: go
34 | :linenos:
35 |
36 | // A map that associates strings to int
37 | // eg. "one" --> 1, "two" --> 2...
38 | var numbers map[string] int //declare a map of strings to ints
39 |
40 | You can access and assign a value to an *entry* of this map using the square
41 | bracket syntax as in arrays or slices, but instead of an ``int`` index you use a
42 | key of type ``keyType``.
43 |
44 | As with slices, since maps are reference types, we can make them using the
45 | ``make`` function: ``make(map[string]float32)``.
46 |
47 | When used with maps, ``make`` takes an optional capacity parameter.
48 |
49 | .. code-block:: go
50 | :linenos:
51 |
52 | // A map that associates strings to int
53 | // eg. "one" --> 1, "two" --> 2...
54 | var numbers map[string] int //declare a map of strings to ints
55 | numbers = make(map[string]int)
56 | numbers["one"] = 1
57 | numbers["ten"] = 10
58 | numbers["trois"] = 3 //trois is "three" in french. I know that you know.
59 | //...
60 | fmt.Println("Trois is the french word for the number: ", numbers[trois])
61 | // Trois is the french word for the number: 3. Also a good time.
62 |
63 | We now have the idea: it's like a table with two columns: in the left column we
64 | have the key, and on the right column we have its *associated* value.
65 |
66 | .. graphviz::
67 |
68 | digraph numbers_map {
69 |
70 | //rankdir=LR;
71 | graph [bgcolor=transparent, resolution=96, fontsize="10" ];
72 | edge [arrowsize=.5, arrowhead="dot", arrowtail="dot", color="#555555"];
73 | node [fontsize=8, height=.1, penwidth=.4]
74 | numbers [shape="plaintext", label=<
75 |
76 |
77 |
Key
78 |
Value
79 |
80 |
81 |
"one"
1
82 |
83 |
84 |
"ten"
10
85 |
86 |
87 |
"trois"
3
88 |
89 |
90 |
numbers
91 |
92 |
>]
93 | }
94 |
95 | Some things to notice:
96 |
97 | - There is no defined notion of *order*. We do not access a value by an index,
98 | but rather by a *key* instead.
99 | - The size of a map is not fixed like in arrays. In fact, just like a *slice*,
100 | a map is a *reference* type.
101 | - Doing for example ``numbers["coffees_I_had"] = 7`` will actually add an entry
102 | to this table, and the size of the map will be incremented by 1.
103 | - As in slices and arrays, the built-in function ``len`` will return the number
104 | of keys in a map (thus the number of entries).
105 | - Values can be changed, of course. ``numbers["coffees_I_had"] = 12`` will
106 | change the ``int`` value associated with the string "coffes_I_had".
107 |
108 | Literal values of maps can be expressed using a list of colon-separated
109 | ``key:value`` pairs. Let's see an example of this:
110 |
111 | .. code-block:: go
112 | :linenos:
113 |
114 | // A map representing the rating given to some programming languages.
115 | rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
116 | // This is equivalent to writing more verbosely
117 | var rating = map[string]float32
118 | rating = make(map[string]float)
119 | rating["C"] = 5
120 | rating["Go"] = 4.5
121 | rating["Python"] = 4.5
122 | rating["C++"] = 2 //Linus would put 1 at most. Go ask him
123 |
124 | Maps are references
125 | -------------------
126 | If you assign a map ``m`` to another map ``m1``, they will both refer to the
127 | same underlying structure that holds the key/value pairs.
128 | Thus, changing the value associated with a given key in ``m1`` will also change
129 | the value of that key in ``m`` as they both reference the same underlying data:
130 |
131 | .. code-block:: go
132 | :linenos:
133 |
134 | //let'ss ay a translation dictionary
135 | m = make(map[string][string])
136 | m["Hello"] = "Bonjour"
137 | m1 = m
138 | m1["Hello"] = "Salut"
139 | // Now: m["Hello"] == "Salut"
140 |
141 | Checking existence of a key
142 | ---------------------------
143 | **Question** What would the expression ``rating["C#"]`` return as a value, in our previous
144 | example?
145 |
146 | Good question! The answer is simple: the expression will return the zero value
147 | of the value type.
148 |
149 | The value type in our example is ``float32``, so it will return '0.00'.
150 |
151 | .. code-block:: go
152 | :linenos:
153 |
154 | //A map representing the rating given to some programming languages.
155 | rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
156 | csharp_rating := rating["C#"]
157 | //csharp_rating == 0.00
158 |
159 | But then, if the value associated with an inexistent key is the zero of the type
160 | value, how can we be sure that C#'s rating is actually 0.00? In other words: is
161 | C#'s rating actually 0.00 so we can say that as a language it *stinks* or was it
162 | that it was not rated at all?
163 |
164 | Here comes the "comma-ok" form of accessing a key's associated value in a map.
165 | It has this syntax: ``value, present = m[key]``.
166 | Where ``present`` is a boolean that indicates whether the key is present in the
167 | map.
168 |
169 | .. code-block:: go
170 | :linenos:
171 |
172 | //A map representing the rating given to some programming languages.
173 | rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
174 | csharp_rating, ok := rating["C#"]
175 | //would print: We have no rating associated with C# in the map
176 | if ok {
177 | fmt.Println("C# is in the map and its rating is ", csharp_rating)
178 | } else {
179 | fmt.Println("We have no rating associated with C# in the map")
180 | }
181 |
182 | We often use ``ok`` as a variable name for boolean presence, hence the name
183 | "comma-ok" form. But, hey! You're free to use any name as long as it's a
184 | ``bool`` type.
185 |
186 | Deleting an entry
187 | -----------------
188 | To delete an entry from the map, think of an *inversed* "comma-ok" form.
189 | In fact, you just have to assign any given value followed by comma ``false``.
190 |
191 | .. code-block:: go
192 | :linenos:
193 |
194 | // A map representing the rating given to some programming languages.
195 | rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
196 | map["C++"] = 1, false // We delete the entry with key "C++"
197 | cpp_rating, ok := rating["C++"]
198 | // Would print: We have no rating associated with C++ in the map
199 | if ok {
200 | fmt.Println("C++ is in the map and its rating is ", cpp_rating)
201 | } else {
202 | fmt.Println("We have no rating associated with C++ in the map")
203 | }
204 |
205 | If in line 2, we had ``map["C++"] = 1, true`` the output of the if-else
206 | statement would be: *C++ is in the map and its rating is 1*. i.e. the entry
207 | associated with key "C++" would be kept in the map, and its value changed to 1.
208 |
209 | Cool! We now have a sexy new type which allows us to easily add key/value pairs,
210 | check if a given key is present, and delete any given key. Simply.
211 |
212 | The question now is: "How do I retrieve all the elements in my map?"
213 | More specifically, "How do I print a list of all the languages in the ``rating``
214 | map with their respective ratings?"
215 |
216 | The range clause
217 | ================
218 | For maps (and arrays, and slices, and other stuff which we'll see later), Go
219 | comes with a facinating alteration of the syntax for the "for statement".
220 |
221 | This syntax is as follow:
222 |
223 | .. code-block:: go
224 | :linenos:
225 |
226 | for key, value := range m {
227 | // In each iteration of this loop, the variables key and value are set
228 | // to the current key/value in the map
229 | ...
230 | }
231 |
232 | Let's see a complete example to understand this better.
233 |
234 | .. code-block:: go
235 | :linenos:
236 |
237 | package main
238 | import "fmt"
239 |
240 | func main(){
241 | // Declare a map literal
242 | ratings := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
243 |
244 | // Iterate over the ratings map
245 | for key, value := range ratings {
246 | fmt.Printf("%s language is rated at %g\n", key, value)
247 | }
248 | }
249 |
250 | Output:
251 |
252 | .. container:: output
253 |
254 | | C++ language is rated at 2
255 | | C language is rated at 5
256 | | Go language is rated at 4.5
257 | | Python language is rated at 4.5
258 |
259 |
260 | If we don't need the value in our for statement, we can omit it like this:
261 |
262 | .. code-block:: go
263 | :linenos:
264 |
265 | package main
266 | import "fmt"
267 |
268 | func main(){
269 | // Declare a map literal.
270 | ratings := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
271 |
272 | fmt.Print("We rated these languages: ")
273 |
274 | // Iterate over the ratings map, and print the languages names.
275 | for key := range ratings {
276 | fmt.Print(key, ",")
277 | }
278 | }
279 |
280 | Output:
281 |
282 | .. container:: output
283 |
284 | | We rated these languages: C++,C,Go,Python,
285 |
286 | **Exercise**: Modify the program above to replace the last comma in the list by
287 | a period. That is, output:
288 | "We rated these languages: C++,C,Go,Python."
289 |
290 | This "for statement" form is also available for arrays and slices where instead
291 | of a key we have an index.
292 |
293 | Let's rewrite a previous example using this new tool:
294 |
295 | .. code-block:: go
296 | :linenos:
297 |
298 | package main
299 | import "fmt"
300 |
301 | // Return the biggest value in a slice of ints.
302 | func Max(slice []int) int { // The input parameter is a slice of ints.
303 | max := slice[0] //the first element is the max for now.
304 | for index, value := range slice { // Notice how we iterate!
305 | if value > max { // We found a bigger value in our slice.
306 | max = value
307 | }
308 | }
309 | return max
310 | }
311 |
312 | func main() {
313 | // Declare three arrays of different sizes, to test the function Max.
314 | A1 := [10]int {1,2,3,4,5,6,7,8,9}
315 | A2 := [4]int {1,2,3,4}
316 | A3 := [1]int {1}
317 |
318 | //declare a slice of ints
319 | var slice []int
320 |
321 | slice = A1[:] // Take all A1 elements.
322 | fmt.Println("The biggest value of A1 is", Max(slice))
323 | slice = A2[:] // Ttake all A2 elements.
324 | fmt.Println("The biggest value of A2 is", Max(slice))
325 | slice = A3[:] // Ttake all A3 elements.
326 | fmt.Println("The biggest value of A3 is", Max(slice))
327 | }
328 |
329 | Output:
330 |
331 | .. container:: output
332 |
333 | | The biggest value of A1 is 9
334 | | The biggest value of A2 is 4
335 | | The biggest value of A3 is 1
336 |
337 | Look carefully at line 6. We used a ``range`` over a slice of ints. ``i`` is an
338 | index and it goes from 0 to ``len(s)-1`` and ``value`` is an int that goes from
339 | ``s[0]`` to ``s[len(s)-1]``.
340 |
341 | Notice also how we didn't use the index ``i`` in this loop. We didn't need it.
342 |
343 | The blank identifier
344 | ====================
345 | Whenever a function returns a value you don't care about, or a range returns an
346 | index that you don't care about, you can use the *blank identifier* _
347 | (underscore) This predeclared identifier can be assigned any value of any type,
348 | and it will be discarded.
349 |
350 | We could have written the ``Max(s []int)int`` function like this:
351 |
352 | .. code-block:: go
353 | :linenos:
354 |
355 | // Return the biggest value in a slice of ints.
356 | func Max(slice []int) int { // The input parameter is a slice of ints.
357 | max := slice[0]
358 | for _, value := range slice { // Notice how we use _ to "ignore" the index.
359 | if value > max {
360 | max = value
361 | }
362 | }
363 | return max
364 | }
365 |
366 | Also, say, we have a function that returns two or more values of which some are
367 | unimportant for us. We can "ignore" these output results using the *blank
368 | identifier*.
369 |
370 | .. code-block:: go
371 | :linenos:
372 |
373 | // A function that returns a bool that is set to true of Sqrt is possible
374 | // and false when not. And the actual square root of a float64
375 | func MySqrt(floater float64) (squareroot float64, ok bool) {
376 | if floater > 0 {
377 | squareroot, ok = math.Sqrt(f), true
378 | } else {
379 | squareroot, ok = 0, false
380 | }
381 | return squareroot, ok
382 | }
383 | //...
384 | r,_ = MySqrt(v) //retrieve the square root of v, and ignore its faisability
385 |
386 | That's it for this chapter. We learned about *maps* ; how to make them, how to
387 | add, change, and delete key/value pairs from them. How to check if a given key
388 | exists in a given map. And we also learned about the *blank identifier* '``_``'
389 | and the ``range`` clause.
390 |
391 | Yes, the ``range`` clause, especially, is a control flow construct that should
392 | belong in the chapter about :doc:`control flow`, but we didn't yet
393 | know about arrays, slices or maps, at that time. This is why we deferred it
394 | until this chapter.
395 |
396 | The next chapter will be about things that we didn't mention about functions in
397 | the chapter about :doc:`functions ` for the same reason: lack of
398 | prior exposure, or simply because I wanted the chapter to be light so we
399 | can make progress with advanced data structures.
400 |
401 | Anyways, you'll see, it will be fun! See you in the next chapter! :)
402 |
403 |
--------------------------------------------------------------------------------
/composite.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | .. _composite-types:
4 |
5 | Basic composite types
6 | *********************
7 | In the :doc:`previous chapter`, we saw how to combine the traditional
8 | control flow idioms seen in :doc:`chapter 3` to create blocks of
9 | reusable code, called *functions*. In this chapter, we'll see how to combine
10 | the basic data types seen in :ref:`chapter 2`, in order to
11 | create complex data types.
12 |
13 | The problem
14 | ===========
15 | Go comes with some *primitive* types: ints, floats, complex numbers, booleans,
16 | and strings. Fair enough, but you'll notice as you start to write complex
17 | programs that you'll need more advanced forms of data.
18 |
19 | Let's begin with an example.
20 |
21 | In the previous chapter, we wrote the ``MAX(A, B int)`` function to find out
22 | the bigger value between two integers A, and B. Now, suppose that A, and B are
23 | actually the ages of persons whose names are respectively Tom and Bob. We need
24 | our program to output the name of the older person, and by how many years he is
25 | older.
26 |
27 | Sure, we still can use the ``MAX(A, B int)`` function by giving it as input
28 | parameters, the ages of Tom and Bob. But it'd be nicer to write a function
29 | ``Older`` for **people**. And not for integers.
30 |
31 | *People*! I said people! Thus the need to *create* a custom type to *represent*
32 | people, and this type will be used for the input parameters of the ``Older``
33 | function we'd like to write.
34 |
35 | Structs
36 | =======
37 | In Go, as in C and other languages, we can declare new types that act as
38 | *containers* for attributes or fields of some other types. For example, we can
39 | create a custom type called ``person`` to represent the attributes of a
40 | person. In our example these attributes will be the person's
41 | *name* **and** *age*.
42 |
43 | .. graphviz::
44 |
45 | digraph person {
46 | rankdir=LR;
47 | graph [bgcolor=transparent, resolution=96, fontsize="10" ];
48 | edge [arrowsize=.5, arrowtail="dot", color="#FF6600"];
49 | node [shape=record, fontsize=8, height=.1, penwidth=.4]
50 | person[label="Tom|25"];
51 | node[shape=plaintext];
52 | pName [label="P.name"];
53 | pAge [label="P.age"];
54 | pName->person:f0;
55 | pAge->person:f1;
56 | }
57 |
58 |
59 | A type like this is called a ``struct``, which is short for *structure*.
60 |
61 | How to declare a struct in Go?
62 | ------------------------------
63 | .. code-block:: go
64 | :linenos:
65 |
66 | type person struct {
67 | name string // Field name of type string.
68 | age int // Field age of type int.
69 | }
70 |
71 | See? It's easy. A person ``struct`` is a container of two fields:
72 |
73 | - The person's name: a field of type ``string``.
74 | - The person's age: a field of type ``int``.
75 |
76 | To declare a ``person`` variable we do exactly as we learned in
77 | :doc:`chapter 2` for basic variable types.
78 |
79 | Thus, writing things like:
80 |
81 | .. code-block:: go
82 | :linenos:
83 |
84 | type person struct {
85 | name string
86 | age int
87 | }
88 |
89 | var P person // P will be a variable of type person. How quaint!
90 |
91 | We access and assign a struct's fields (attributes) with the *dot nottation*.
92 | That is, if ``P`` is a variable of type ``person``, then we access its fields like
93 | this:
94 |
95 | .. code-block:: go
96 | :linenos:
97 |
98 | P.name = "Tom" // Assign "Tom" to P's name field.
99 | P.age = 25 // Set P's age to 25 (an int).
100 | fmt.Println("The person's name is %s", P.name) // Access P's name field.
101 |
102 | There's even two short-form assignment statement syntaxes:
103 |
104 | 1. By providing the values for each (and every) field in order:
105 |
106 | .. code-block:: go
107 | :linenos:
108 |
109 | //declare a variable P of type person and initialize its fields
110 | //name to "Tom" and age to 25.
111 | P := person{"Tom", 25}
112 |
113 | 2. By using field:value initializers for any number of fields in any order:
114 |
115 | .. code-block:: go
116 | :linenos:
117 |
118 | //declare a variable P of type person and initialize its fields
119 | //name to "Tom" and age to 25.
120 | //Order, here, doesn't count since we specify the fields.
121 | P := person{age:24, name:"Tom"}
122 |
123 |
124 | Good. Let's write our ``Older`` function that takes two input parameters of type
125 | ``person``, and returns the older one *and* the difference in their ages.
126 |
127 | .. code-block:: go
128 | :linenos:
129 |
130 | package main
131 | import "fmt"
132 |
133 | // We declare our new type
134 | type person struct {
135 | name string
136 | age int
137 | }
138 |
139 | // Return the older person of p1 and p2
140 | // and the difference in their ages.
141 | func Older(p1, p2 person) (person, int) {
142 | if p1.age>p2.age { // Compare p1 and p2's ages
143 | return p1, p1.age-p2.age
144 | }
145 | return p2, p2.age-p1.age
146 | }
147 |
148 | func main() {
149 | var tom person
150 |
151 | tom.name, tom.age = "Tom", 18
152 |
153 | // Look how to declare and initialize easily.
154 | bob := person{age:25, name:"Bob"} //specify the fields and their values
155 | paul := person{"Paul", 43} //specify values of fields in their order
156 |
157 | tb_Older, tb_diff := Older(tom, bob)
158 | tp_Older, tp_diff := Older(tom, paul)
159 | bp_Older, bp_diff := Older(bob, paul)
160 |
161 | fmt.Printf("Of %s and %s, %s is older by %d years\n",
162 | tom.name, bob.name, tb_Older.name, tb_diff)
163 |
164 | fmt.Printf("Of %s and %s, %s is older by %d years\n",
165 | tom.name, paul.name, tp_Older.name, tp_diff)
166 |
167 | fmt.Printf("Of %s and %s, %s is older by %d years\n",
168 | bob.name, paul.name, bp_Older.name, bp_diff)
169 | }
170 |
171 | Output:
172 |
173 | .. container:: output
174 |
175 | | Of Tom and Bob, Bob is older by 7 years
176 | | Of Tom and Paul, Paul is older by 25 years
177 | | Of Bob and Paul, Paul is older by 18 years
178 |
179 | And that's about it! ``struct`` types are handy, easy to declare and to use!
180 |
181 | Ready for another problem?
182 |
183 | .. _Older100:
184 |
185 | Now, suppose that we'd like to retrieve the older of, not 2, but 10 persons!
186 | Would you write a ``Older10`` function that would take 10 input ``person``\s?
187 | Sure you can! But, seriously, that would be one ugly, very ugly function! Don't
188 | write it, just picture it in your brain. Still not convinced? Ok, imagine a
189 | ``Older100`` function with **100** input parameters! Convinced, now?
190 |
191 | Ok, let's see how to solve these kinds of problems using arrays.
192 |
193 | .. _arrays:
194 |
195 | Arrays
196 | ======
197 | An array of size **n** is a *block* of **n** *consecutive* objects of the same
198 | **type**. That is a finite *set* of indexed objects, where you can enumerate
199 | them: *object number 1*, *object number 2*, etc...
200 |
201 | In fact, in Go as in C and other languages, the indexing starts from 0, so you
202 | actually say: *object number 0*, *object number 1*... *object number n-1*
203 |
204 | .. graphviz::
205 |
206 | digraph array_s {
207 | rankdir=LR;
208 | graph [bgcolor=transparent, resolution=96, fontsize="10" ];
209 | edge [arrowsize=.5, arrowtail="dot", color="#555555"];
210 | node [shape=record, fontsize=8, height=.1, penwidth=.4]
211 | array[label="{A[0]|[A]1|A[2]|A[3]|...|A[n-1]}"];
212 | }
213 |
214 |
215 | Here's how to declare an array of 10 ``int``\s, for example:
216 |
217 | .. code-block:: go
218 | :linenos:
219 |
220 | //declare an array A of 10 ints
221 | var A [10]int
222 |
223 | And here's how to declare an array of 10 ``person``\s:
224 |
225 | .. code-block:: go
226 | :linenos:
227 |
228 | //declare an array A of 10 persons
229 | var people [10]person
230 |
231 |
232 | We can access the x :sup:`th` element of an array ``A``, with the syntax:
233 | **A[x]**.
234 | Specifically we say: ``A[0]``, ``A[1]``, ..., ``A[n]``.
235 |
236 | For example, the name of the 3 :sup:`rd` person is:
237 |
238 | .. code-block:: go
239 | :linenos:
240 |
241 | // Declare an array A of 10 persons:
242 | var people [10]person
243 |
244 | // Remember indices start from 0!
245 | third_name := people[2].name //use the dot to access the third 'name'.
246 |
247 | // Or more verbosely:
248 | third_person := people[2]
249 | thirdname := third_person.name
250 |
251 | .. graphviz::
252 |
253 | digraph array_s {
254 | //rankdir=LR;
255 | graph [bgcolor=transparent, resolution=96, fontsize="10" ];
256 | edge [arrowsize=.5, arrowhead="dot", color="#555555"];
257 | node [shape=record, fontsize=8, height=.1, penwidth=.4]
258 | people[label="people[0]|[people1]|people[2]|people[3]|...|people[n-1]"];
259 | p2[shape=circle, penwidth=1, color=crimson, fontcolor=black, label=<
260 |
261 |
262 |
Tom
263 |
25
264 |
265 |
>]
266 | p2->people:f2 [label=" Zoom on people[2]", fontsize=6, color=crimson, fontcolor=crimson]
267 | }
268 |
269 | The idea now is to write a function ``Older10`` that takes an array of 10
270 | ``person``\s as its input, and returns the older ``person`` in this array.
271 |
272 | .. code-block:: go
273 | :linenos:
274 |
275 | package main
276 | import "fmt"
277 |
278 | //Our struct
279 | type person struct {
280 | name string
281 | age int
282 | }
283 |
284 | //return the older person in a group of 10 persons
285 | func Older10(people [10]person) person {
286 | older := people[0] // The first one is the older for now.
287 | // Loop through the array and check if we could find an older person.
288 | for index := 1; index < 10; index++ { // We skipped the first element here.
289 | if people[index].age > older.age { // Current's persons age vs olderest so far.
290 | older = people[index] // If people[index] is older, replace the value of older.
291 | }
292 | }
293 | return older
294 | }
295 |
296 | func main() {
297 | // Declare an example array variable of 10 person called 'array'.
298 | var array [10]person
299 |
300 | // Initialize some of the elements of the array, the others are by
301 | // default set to person{"", 0}
302 | array[1] = person{"Paul", 23};
303 | array[2] = person{"Jim", 24};
304 | array[3] = person{"Sam", 84};
305 | array[4] = person{"Rob", 54};
306 | array[8] = person{"Karl", 19};
307 |
308 | older := Older10(array) // Call the function by passing it our array.
309 |
310 | fmt.Println("The older of the group is: ", older.name)
311 | }
312 |
313 | Output:
314 |
315 | .. container:: output
316 |
317 | | The older of the group is: Sam
318 |
319 |
320 | We could have declared and initialized the variable ``array`` of the ``main()``
321 | function above in a single shot like this:
322 |
323 | .. code-block:: go
324 | :linenos:
325 |
326 | // Declare and initialize an array A of 10 person.
327 | array := [10]person {
328 | person{"", 0},
329 | person{"Paul", 23},
330 | person{"Jim", 24},
331 | person{"Sam", 84},
332 | person{"Rob", 54},
333 | person{"", 0},
334 | person{"", 0},
335 | person{"", 0},
336 | person{"Karl", 10},
337 | person{"", 0}}
338 |
339 | This means that to initialize an array, you put its elements between two braces,
340 | and you separate them with commas.
341 |
342 | We can even omit the size of the array, and Go will count the number of elements
343 | given in the initialization for us. So we could have written the above code as:
344 |
345 | .. code-block:: go
346 | :linenos:
347 |
348 | // Declare and initialize an array of 10 persons, but let the compiler guess the size.
349 | array := [...]person { // Substitute '...' instead of an integer size.
350 | person{"", 0},
351 | person{"Paul", 23},
352 | person{"Jim", 24},
353 | person{"Sam", 84},
354 | person{"Rob", 54},
355 | person{"", 0},
356 | person{"", 0},
357 | person{"", 0},
358 | person{"Karl", 10},
359 | person{"", 0}}
360 |
361 | Specifically note the ellipsis ``[...]``.
362 |
363 | .. _arrays-note:
364 |
365 | .. note::
366 | **However**, the **size of an array is an important part of its
367 | definition**. They don't *grow* and they don't *shrink*. You can't, for
368 | example, have an array of 9 elements, and use it with a function that
369 | expects an array of 10 elements as an input. Simply because they are of
370 | *different* types. **Remember this.**
371 |
372 | Some things to keep in mind:
373 |
374 | - Arrays are values. Assigning one array to another, copies all of the elements
375 | of the right hand array to the left hand array.
376 | That is: if ``A``, and ``B`` are arrays of the same type, and we write: ``B =
377 | A``, then ``B[0] == A[0]``, ``B[1] == A[1]``... ``B[n-1] == A[n-1]``.
378 |
379 | - When passing an array to a function, it is copied. i.e. The function recieves
380 | a *copy* of that array, and **not** a reference (pointer) to it.
381 |
382 | - Go comes with a built-in function ``len`` that returns variables sizes. In the
383 | previous example: ``len(array) == 10``.
384 |
385 | Multi-dimensional arrays
386 | ========================
387 | You can think to yourself: *"Hey! I want an array of arrays!"*.
388 | Yes, that's possible, and often used in practice.
389 |
390 | We can declare a 2-dimensional array like this:
391 |
392 | .. code-block:: go
393 | :linenos:
394 |
395 | //declare and initialize an array of 2 arrays of 4 ints
396 | double_array := [2][4]int {[4]int{1,2,3,4}, [4]int{5,6,7,8}}
397 |
398 | This is an array of (2 arrays (of 4 ``int``)). We can think of it as a matrix,
399 | or a table of two lines each made of 4 columns.
400 |
401 | .. graphviz::
402 |
403 | digraph array_2 {
404 | rankdir=LR;
405 | graph [bgcolor=transparent, resolution=96, fontsize="10" ];
406 | edge [arrowsize=.5, arrowtail="dot", color="#ff6600"];
407 | node [shape=record, fontsize=8, height=.1, penwidth=.4]
408 | array[label="{1|2|3|4}|{5|6|7|8}"];
409 | node[shape="plaintext", fixedsize="true"]
410 | exnode00 [label="A[0,0]"];
411 | exnode01 [label="A[0,1]"];
412 | exnode11 [label="A[1,1]"];
413 | exnode13 [label="A[1,3]"];
414 | exnode00->array:f00;
415 | exnode01->array:f01;
416 | exnode11->array:f11;
417 | exnode13->array:f13;
418 | }
419 |
420 | The previous declaration may be simplified, using the fact that the compiler can
421 | count arrays' elements for us, like this:
422 |
423 | .. code-block:: go
424 | :linenos:
425 |
426 | //simplify the previous declaration, with the '...' syntax
427 | double_array := [2][4]int {[...]int{1,2,3,4}, [...]int{5,6,7,8}}
428 |
429 | Guess what?
430 | Since Go is about cleaner code, we can simplify this code even further:
431 |
432 | .. code-block:: go
433 | :linenos:
434 |
435 | //über simpifikation!
436 | double_array := [2][4]int {{1,2,3,4}, {5,6,7,8}}
437 |
438 | Cool, eh? Now, we can combine multiple fields of different types to create a
439 | ``struct`` and we can have ``array``\s of, as many as we want, of objects of the
440 | same type, and pass it as a *single block* to our functions. But this is just
441 | the begining! In the next chapter, we will see how to create and use some
442 | advanced composite data types with pointers.
443 |
444 |
--------------------------------------------------------------------------------
/functions.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | Functions, why and how
4 | **********************
5 | In the previous two chapters, we saw the basic data types, and the basic
6 | control structures. They're basic in the sense that they are useful for some
7 | very basic needs. And as the needs, or the problem to solve with a program
8 | become complex, you'll feel the the need for complex data, and control
9 | structures.
10 |
11 | The problem
12 | ===========
13 | Let's say that we have to write a program to retrieve the maximum value of
14 | two integers A and B. That's easy to do with a simple *if* statement, right?
15 |
16 | .. code-block:: go
17 | :linenos:
18 |
19 | //compare A and B and say wich is bigger
20 | if A > B {
21 | fmt.Print("The max is A")
22 | } else {
23 | fmt.Print("The max is B")
24 | }
25 |
26 | Now, imagine that we have to make such a comparison many times in our program.
27 | Writing the previous snippet every time becomes a real chore, and error-prone.
28 | This is why we need to *encapsulate* this snippet in a code block, give it a
29 | name and then call this code block every time we need to know the max of two
30 | numbers. This code block is what we call a function.
31 |
32 | .. graphviz::
33 |
34 | digraph function {
35 | rankdir=LR;
36 | graph [bgcolor=transparent, resolution=96, fontsize="10"];
37 | node [shape=circle, fontsize=8, fixedsize=true, penwidth=.4];
38 | edge [arrowsize=.5, arrowtail="dot", color="#555555", penwidth=.4];
39 | block[label = "Function", shape="box", color=antiquewhite3, style=filled, peripheries=2];
40 | input1->block [color="#ff6600"];
41 | input2->block [color="#ff6600"];
42 | input3->block [color="#ff6600"];
43 | block->output1;
44 | block->output2;
45 | { rank=same; input1 input2 input3}
46 | }
47 |
48 |
49 | A *function* is a code block that takes some items and returns some results.
50 |
51 | If you've ever done some electronics, you'd see that functions really look like
52 | electronic circuits or chips. Need to amplify a signal? Take an amplifier
53 | chipset. Need to filter? Use a filter chipset and so on...
54 |
55 | Your job as a software developer will be much easier, and far more fun once you
56 | start to think of a complex project as a set of modules for which the input is
57 | from the output of another module. The complexity of the solution will be
58 | reduced, and the debugging will be made easier also.
59 |
60 | Let's see how to apply this sort of design to the following problem:
61 | suppose we have a function MAX(A, B) which takes two integers {A, B} and returns
62 | a single integer output M which is the larger value of both A and B:
63 |
64 | .. graphviz::
65 |
66 | digraph MAX {
67 | rankdir=LR;
68 | graph [bgcolor=transparent, resolution=96, fontsize="10" ];
69 | node [shape=circle, fontsize=8, fixedsize=true, penwidth=.4];
70 | edge [arrowsize=.5, arrowtail="dot", color="#555555", penwidth=.4];
71 | block[label = "MAX", shape="box", color=antiquewhite3, style=filled, peripheries=2];
72 | A->block [color="#ff6600"];
73 | B->block [color="#ff6600"];
74 | block->M;
75 | }
76 |
77 | By reusing the function ``MAX`` we can compute the maximum value of three
78 | values: A, B and C as follows:
79 |
80 | .. graphviz::
81 |
82 | digraph MAX {
83 | rankdir=LR;
84 | graph [bgcolor=transparent, resolution=96, fontsize="10" ];
85 | node [shape=circle, fontsize=8, fixedsize=true, penwidth=.4];
86 | edge [arrowsize=.5, arrowtail="dot", color="#555555", penwidth=.4];
87 | max1[label = "MAX", shape="box", color=antiquewhite3, style=filled, peripheries=2];
88 | max2[label = "MAX", shape="box", color=antiquewhite3, style=filled, peripheries=2];
89 | A->max1 [color="#ff6600"];
90 | B->max1 [color="#ff6600"];
91 | max1->max2;
92 | C->max2 [color="#ff6600"];
93 | max2->X;
94 | { rank=same; A B C}
95 | }
96 |
97 |
98 | This is a very simple example actually. In practice you probably should write a
99 | ``MAX3`` function that takes 3 input integers and returns a single integer,
100 | instead of reusing the function ``MAX``.
101 |
102 | Of course, you can *inject* the output of a function into another if and only if
103 | the types match.
104 |
105 | How to do this in Go?
106 | =====================
107 | The general syntax of a function is:
108 |
109 | .. code-block:: go
110 | :linenos:
111 |
112 | func funcname(input1 type1, input2 type2) (output1 type1, output2 type2) {
113 | //some code and processing here
114 | ...
115 | //return the results of the function
116 | return value1, value2
117 | }
118 |
119 | The details:
120 |
121 | * The keyword ``func`` is used to declare a function of name *funcname*.
122 | * A function may take as many input parameters as required. Each one followed
123 | by its type and all separated by commas.
124 | * A function may return many result values.
125 | * In the previous snippet, ``result1`` and ``result2`` are called
126 | *named result parameters*, if you don't want to name the return parameters,
127 | you can instead specify only the types, separated with commas.
128 | * If your function returns only one output value, you may omit the parenthesis
129 | arround the output declaration portion.
130 | * If your function doesn't return any value, you may omit it entirely.
131 |
132 | Some examples to better understand these rules:
133 |
134 | A simple Max function
135 | ---------------------
136 | .. code-block:: go
137 | :linenos:
138 |
139 | package main
140 | import "fmt"
141 |
142 | //return the maximum between two int a, and b.
143 | func max(a, b int) int {
144 | if a > b {
145 | return a
146 | }
147 | return b
148 | }
149 |
150 | func main() {
151 | x := 3
152 | y := 4
153 | z := 5
154 |
155 | max_xy := max(x, y) //calling max(x, y)
156 | max_xz := max(x, z) //calling max(x, z)
157 |
158 | fmt.Printf("max(%d, %d) = %d\n", x, y, max_xy)
159 | fmt.Printf("max(%d, %d) = %d\n", x, z, max_xz)
160 | fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) //just call it here
161 | }
162 |
163 | Output:
164 |
165 | .. container:: output
166 |
167 | | max(3, 4) = 4
168 | | max(3, 5) = 5
169 | | max(4, 5) = 5
170 |
171 |
172 | Our function *MAX* takes two input parameters A and B, and returns a single
173 | ``int``.
174 | Notice how we grouped A and B's types. We could have written: MAX(A int, B int),
175 | however, it is shorter this way.
176 |
177 | Notice also that we prefered not to name our output value. We instead specified
178 | the output type (``int``).
179 |
180 | A function with two ouput values
181 | --------------------------------
182 |
183 | .. code-block:: go
184 | :linenos:
185 |
186 | package main
187 | import "fmt"
188 |
189 | //return A+B and A*B in a single shot
190 | func SumAndProduct(A, B int) (int, int) {
191 | return A+B, A*B
192 | }
193 |
194 | func main() {
195 | x := 3
196 | y := 4
197 |
198 | xPLUSy, xTIMESy := SumAndProduct(x, y)
199 |
200 | fmt.Printf("%d + %d = %d\n", x, y, xPLUSy)
201 | fmt.Printf("%d * %d = %d\n", x, y, xTIMESy)
202 | }
203 |
204 | Output:
205 |
206 | .. container:: output
207 |
208 | | 3 + 4 = 7
209 | | 3 * 4 = 12
210 |
211 |
212 | A function with a result variable
213 | ---------------------------------
214 | .. code-block:: go
215 | :linenos:
216 |
217 | package main
218 |
219 | //look how we grouped the import of packages fmt and math
220 | import(
221 | "fmt"
222 | "math"
223 | )
224 |
225 | //A function that returns a bool that is set to true of Sqrt is possible
226 | //and false when not. And the actual square root of a float64
227 | func MySqrt(f float64) (squareroot float64, ok bool){
228 | if f > 0 {
229 | squareroot, ok = math.Sqrt(f), true
230 | } else {
231 | squareroot, ok = 0, false
232 | }
233 | return squareroot, ok
234 | }
235 |
236 | func main() {
237 | for index := -2.0; index <= 10; index++ {
238 | squareroot, possible := MySqrt(index)
239 | if possible {
240 | fmt.Printf("The square root of %f is %f\n", index, squareroot)
241 | } else {
242 | fmt.Printf("Sorry, no square root for %f\n", index)
243 | }
244 | }
245 | }
246 |
247 | Outputs:
248 |
249 | .. container:: output
250 |
251 | | Sorry, no square root for -2.000000
252 | | Sorry, no square root for -1.000000
253 | | Sorry, no square root for 0.000000
254 | | The square root of 1.000000 is 1.000000
255 | | The square root of 2.000000 is 1.414214
256 | | The square root of 3.000000 is 1.732051
257 | | The square root of 4.000000 is 2.000000
258 | | The square root of 5.000000 is 2.236068
259 | | The square root of 6.000000 is 2.449490
260 | | The square root of 7.000000 is 2.645751
261 | | The square root of 8.000000 is 2.828427
262 | | The square root of 9.000000 is 3.000000
263 | | The square root of 10.000000 is 3.162278
264 |
265 |
266 | Here, we *import* the package "``math``" in order to use the ``Sqrt`` (Square
267 | root) function it provides. We, then, write our own function ``MySqrt`` which
268 | returns two values: the first one is the actual sqaure root of the input
269 | parameter ``f`` and the second one is a boolean (indicates whether a square root
270 | is possible or not)
271 |
272 | Notice how we use the parameters ``s`` and ``ok`` as actual variables in the
273 | function's body.
274 |
275 | Since result variables are initialized to "zero" (0, 0.00, false...) according
276 | to its type, we can rewrite the previous example as follows:
277 |
278 | .. code-block:: go
279 | :linenos:
280 |
281 | import "math"
282 |
283 | //return A+B and A*B in a single shot
284 | func MySqrt(floater float64) (squareroot float64, ok bool){
285 | if floater > 0 {
286 | squareroot, ok = math.Sqrt(f), true
287 | }
288 | return squareroot, ok
289 | }
290 |
291 | The empty return
292 | ----------------
293 | When using named output variables, if the function executes a return statement
294 | with no arguments, the current values of the result parameters are used as the
295 | returned values.
296 |
297 | Thus, we can rewrite the previous example as follow:
298 |
299 | .. code-block:: go
300 | :linenos:
301 |
302 | import "math"
303 |
304 | //return A+B and A*B in a single shot
305 | func MySqrt(floater float64) (squareroot float64, ok bool) {
306 | if floater > 0 {
307 | squareroot, ok = math.Sqrt(f), true
308 | }
309 | return // Omitting the output named variables, but keeping the "return".
310 | }
311 |
312 | .. _value-reference:
313 |
314 | Parameters by value, and by reference
315 | =====================================
316 | When passing an input parameter to a function, it actually recieves a *copy* of
317 | this parameter. So, if the function changes the value of this parameter, the
318 | original variable's value won't be changed, because the function works on a
319 | *copy* of the original variable's value.
320 |
321 | An example to verify the previous paragraph:
322 |
323 | .. code-block:: go
324 | :linenos:
325 |
326 | package main
327 | import "fmt"
328 |
329 | //simple function that returns 1 + its input parameter
330 | func add1(a int) int {
331 | a = a+1 // we change the value of a, by adding 1 to it
332 | return a //return the new value
333 | }
334 |
335 | func main() {
336 | x := 3
337 |
338 | fmt.Println("x = ", x) // Should print "x = 3"
339 |
340 | x1 := add1(x) //calling add1(x)
341 |
342 | fmt.Println("x+1 = ", x1) // Should print "x+1 = 4"
343 | fmt.Println("x = ", x) // Will print "x = 3"
344 | }
345 |
346 | .. container:: output
347 |
348 | | x = 3
349 | | x+1 = 4
350 | | x = 3
351 |
352 | You see? The value of ``x`` wasn't changed by the call of the function ``add1``
353 | even though we had an explicit ``a = a+1`` instruction on line 6.
354 |
355 | The reason is simple: when we called the function ``add1``, it recieved a *copy*
356 | of the variable ``x`` and not ``x`` itself, hence it changed the copy's value,
357 | not the value of ``x`` itself.
358 |
359 | I know the question you have in mind:
360 | *"What if I wanted the value of x to be changed by calling the function?"*
361 |
362 | And here comes the utility of pointers: Instead of writing a function that has
363 | an ``int`` input parameter, we should give it a pointer to the variable we want
364 | to change! This way, the function has *access* to the original variable and it
365 | can change it.
366 |
367 | Let's try this.
368 |
369 | .. code-block:: go
370 | :linenos:
371 |
372 | package main
373 | import "fmt"
374 |
375 | //simple function that returns 1 + its input parameter
376 | func add1(a *int) int { // Notice that we give it a pointer to an int!
377 | *a = *a+1 // We dereference and change the value pointed by a
378 | return *a // Return the new value
379 | }
380 |
381 | func main() {
382 | x := 3
383 |
384 | fmt.Println("x = ", x) // Will print "x = 3"
385 |
386 | x1 := add1(&x) // Calling add1(&x) by passing the address of x to it
387 |
388 | fmt.Println("x+1 = ", x1) // Will print "x+1 = 4"
389 | fmt.Println("x = ", x) // Will print "x = 4"
390 | }
391 |
392 | .. container:: output
393 |
394 | | x = 3
395 | | x+1 = 4
396 | | x = 4
397 |
398 | Now, we have changed the value of ``x``!
399 |
400 | How is passing a reference to functions is useful? You may ask.
401 |
402 | * The first reason is that passing a reference makes function *cooperation* on
403 | a single variable possible. In other words, if we want to apply several
404 | functions on a given variable, they will all be able to change it.
405 |
406 | * A pointer is cheap. Cheap in terms of memory usage. We can have functions that
407 | operate on a big data value for example. Copying this data will, of course,
408 | require memory on each call as it is copied for use by the function.
409 | In this way, a pointer takes much less memory.
410 | Yo! Remember, it's just an address! :)
411 |
412 | .. _functions-signatures:
413 |
414 | Function's signatures
415 | =====================
416 | Like with people, names don't matter that much. Do they? Well, yes, let's face
417 | it, they do matter, but what matters most is what they do, what they need, what
418 | they produce (Yeah you! Get back to work!).
419 |
420 | In our previous example, we could have called our function **add_one** instead of
421 | **add1**, and that would still work as long as we call it by its name.
422 | What really matters in our function is:
423 |
424 | 1. Its input parameters: how much? which types?
425 | 2. Its output parameters: how much, which type?
426 | 3. Its body code: What does the function do?
427 |
428 | We can rewrite the function's body to work differently, and the main program
429 | would continue to compile and run without problems. But we can't change the
430 | input and output parameters in the function's declaration and still use its old
431 | parameters in the main program.
432 |
433 | In other words, of the 3 elements we listed above, what matters even more is:
434 | what input parameters does the function expect, and what output parameters does
435 | it return.
436 |
437 | These two elements are what we call a *function signature*, for which we use
438 | this formalism:
439 |
440 | ``func (input1 type1 [, input2 type2 [, ...]]) (output1 OutputType1 [, output2 OutputType2 [,...]])``
441 |
442 | Or optionally with the function's name:
443 |
444 | ``func function_name (input1 type1 [, input2 type2 [, ...]]) (output1 OutputType1 [, output2 OutputType2 [,...]])``
445 |
446 | Examples of signatures
447 | ----------------------
448 |
449 | .. code-block:: go
450 | :linenos:
451 |
452 | //The signature of a function that takes an int and returns and int
453 | func (int x) x int
454 |
455 | //takes two float and returns a bool
456 | func (float32, float32) bool
457 |
458 | // Takes a string returns nothing
459 | func (string)
460 |
461 | // Takes nothing returns nothing
462 | func()
463 |
464 |
--------------------------------------------------------------------------------
/methods.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | Methods: a taste of OOP
4 | ***********************
5 | In the previous chapter, we saw some nice things to do with functions as values
6 | that can be assigned to variables, passed to and returned from other functions.
7 | We finished with the fact that we actually can use functions as ``struct``
8 | fields.
9 |
10 |
11 | Today, we'll see a kind of an *extrapolation* of functions, that is functions
12 | with a *receiver*, which are called **methods**.
13 |
14 | What is a method?
15 | =================
16 | Suppose that you have a ``struct`` representing a rectangle. And you want *this*
17 | rectangle to *tell* you *its own* area.
18 |
19 | The way we'd do this with functions would be something like this:
20 |
21 | .. code-block:: go
22 | :linenos:
23 |
24 | package main
25 | import "fmt"
26 |
27 | type Rectangle struct {
28 | width, height float64
29 | }
30 |
31 | func area(r Rectangle) float64 {
32 | return r.width*r.height
33 | }
34 |
35 | func main() {
36 | r1 := Rectangle{12, 2}
37 | r2 := Rectangle{9, 4}
38 | fmt.Println("Area of r1 is: ", area(r1))
39 | fmt.Println("Area of r2 is: ", area(r2))
40 | }
41 |
42 | Output:
43 |
44 | .. container:: output
45 |
46 | | Area of r1 is: 24
47 | | Area of r2 is: 36
48 |
49 | This works as expected, but in the example above, the function ``area`` is not
50 | *part* of the ``Rectangle`` type. It *expects* a ``Rectangle`` parameter as
51 | its input.
52 |
53 | *Yes, so what?* You'd say. No problem, it's just if you decide to add circles
54 | and triangles and other polygons to your program, and you want to compute their
55 | areas, you'd have to write different functions *with different names* for a
56 | *functionality* or a *characteristic* that is, after all, the *same*.
57 |
58 | You'd have to write: ``area_rectangle``, ``area_circle``, ``area_triangle``...
59 |
60 | And this is not elegant. Because the *area* of a *shape* is a *characteristic*
61 | of this shape. It should be a part of it, *belong* to it, just like its other
62 | fields.
63 |
64 | And this leads us to methods: A method is function that is bound or attached to
65 | a given type. Its syntax is the same as a traditional function except that we
66 | specify a *receiver* of this type just after the keyword ``func``.
67 |
68 | In the words of `Rob Pike`_:
69 |
70 | "*A method is a function with an implicit first argument, called a receiver.*"
71 |
72 | ``func (ReceiverType r) func_name (parameters) (results)``
73 |
74 | Let's illustrate this with an example:
75 |
76 | .. code-block:: go
77 | :linenos:
78 |
79 | package main
80 | import ("fmt"; "math") //Hey! Look how we used a semi-colon! Neat technique!
81 |
82 | type Rectangle struct {
83 | width, height float64
84 | }
85 |
86 | type Circle struct {
87 | radius float64
88 | }
89 |
90 | /*
91 | Notice how we specified a receiver of type Rectangle to this method.
92 | Notice also how this methods -in this case- doesn't need input parameters
93 | because the data it need is part of its receiver r
94 | */
95 | func (r Rectangle) area() float64 {
96 | return r.width * r.height //using fields of the receiver
97 | }
98 |
99 | // Another method with the SAME name but with a different receiver.
100 | func (c Circle) area() float64 {
101 | return c.radius * c.radius * math.Pi
102 | }
103 |
104 | func main() {
105 | r1 := Rectangle{12, 2}
106 | r2 := Rectangle{9, 4}
107 | c1 := Circle{10}
108 | c2 := Circle{25}
109 | //Now look how we call our methods.
110 | fmt.Println("Area of r1 is: ", r1.area())
111 | fmt.Println("Area of r2 is: ", r2.area())
112 | fmt.Println("Area of c1 is: ", c1.area())
113 | fmt.Println("Area of c2 is: ", c2.area())
114 | }
115 |
116 | Output:
117 |
118 | .. container:: output
119 |
120 | | Area of r1 is: 24
121 | | Area of r2 is: 36
122 | | Area of c1 is: 314.1592653589793
123 | | Area of c2 is: 1963.4954084936207
124 |
125 | A few things to note about methods:
126 |
127 | - Methods of different receivers are different methods even if they share the
128 | name.
129 | - A method has access to its receiver's fields (data).
130 | - A method is called with the dot notation like ``struct`` fields.
131 |
132 | So? Are methods applicable only for ``struct`` types? The anwser is No. In fact,
133 | you can write methods for any *named* type that you define, that is not a
134 | pointer:
135 |
136 | .. code-block:: go
137 | :linenos:
138 |
139 | package main
140 | import "fmt"
141 |
142 | //We define two new types
143 | type SliceOfints []int
144 | type AgesByNames map[string]int
145 |
146 | func (s SliceOfints) sum() int {
147 | sum := 0
148 | for _, value := range s {
149 | sum += value
150 | }
151 | return sum
152 | }
153 |
154 | func (people AgesByNames) older() string {
155 | a := 0
156 | n := ""
157 | for key, value := range people {
158 | if value > a {
159 | a = value
160 | n = key
161 | }
162 | }
163 | return n
164 | }
165 |
166 | func main() {
167 | s := SliceOfints {1, 2, 3, 4, 5}
168 | folks := AgesByNames {
169 | "Bob": 36,
170 | "Mike": 44,
171 | "Jane": 30,
172 | "Popey": 100, //look at this comma. when it's the last and
173 | } //the brace is here, the comma above is obligatory.
174 |
175 | fmt.Println("The sum of ints in the slice s is: ", s.sum())
176 | fmt.Println("The older in the map folks is:", folks.older())
177 | }
178 |
179 | If you missed the comma remark, go back and re-read the code carefully.
180 |
181 | Output:
182 |
183 | .. container:: output
184 |
185 | | The sum of ints in the slice s is: 15
186 | | The older in the map folks is: Popey
187 |
188 | *Now, wait a minute!* (You say this with your best Bill Cosby's impression)
189 | *What is this "named types" thing that you're telling me now?*
190 | Sorry, my bad. I didn't need to tell you before.
191 | And I didn't want to distract you with this *detail* back then.
192 |
193 | It's in fact easy. You can define new types as much as you want.
194 | ``struct`` is in fact a specific case of this syntax.
195 | Look back, we actually used this in the previous chapter!
196 |
197 | You can create aliases for built-in and composite types with the following
198 | syntax:
199 |
200 | ``type type_name type_literal``
201 |
202 | Examples:
203 |
204 | .. code-block:: go
205 | :linenos:
206 |
207 | //ages is an alias for int
208 | type ages int
209 | //money is an alias for float32
210 | type money float32
211 | //we define months as a map of strings and their associated number of days
212 | type months map[string]int
213 | //m is a variable of type months
214 | m := months {
215 | "January":31,
216 | "February":28,
217 | ...
218 | "December":31,
219 | }
220 |
221 | See? It's actually easy, and it can be handy to give more meaning to your
222 | code, by giving names to complicated composite -- or even simple -- types.
223 |
224 | Back to our methods.
225 |
226 | So, yes, you can define methods for any named type, even if it's an alias to a
227 | pre-declared type. Needless to say that you can define as many methods, for any
228 | given named type, as you want.
229 |
230 | Let's see a more advanced example, and we will discuss some details of it just
231 | after.
232 |
233 | Tis the story of a set of colored boxes. They have widths, heights, depths
234 | and colors of course! We want to find out the color of the biggest box, and
235 | eventually paint them all black (Because you know... I see a red box, and I want
236 | it painted black...)
237 |
238 | Here we *Go*!
239 |
240 | .. Very punny... :p
241 |
242 | .. _colored-boxes-example:
243 |
244 | .. code-block:: go
245 | :linenos:
246 | :emphasize-lines: 25, 43
247 |
248 | package main
249 | import "fmt"
250 |
251 | const(
252 | WHITE = iota
253 | BLACK
254 | BLUE
255 | RED
256 | YELLOW
257 | )
258 |
259 | type Color byte
260 |
261 | type Box struct {
262 | width, height, depth float64
263 | color Color
264 | }
265 |
266 | type BoxList []Box //a slice of boxes
267 |
268 | func (b Box) Volume() float64 {
269 | return b.width * b.height * b.depth
270 | }
271 |
272 | func (b *Box) SetColor(c Color) {
273 | b.color = c
274 | }
275 |
276 | func (bl BoxList) BiggestsColor() Color {
277 | v := 0.00
278 | k := Color(WHITE) //initialize it to something
279 | for _, b := range bl {
280 | if b.Volume() > v {
281 | v = b.Volume()
282 | k = b.color
283 | }
284 | }
285 | return k
286 | }
287 |
288 | func (bl BoxList) PaintItBlack() {
289 | for i, _ := range bl {
290 | bl[i].SetColor(BLACK)
291 | }
292 | }
293 |
294 | func (c Color) String() string {
295 | strings := []string {"WHITE", "BLACK", "BLUE", "RED", "YELLOW"}
296 | return strings[c]
297 | }
298 |
299 | func main() {
300 | boxes := BoxList {
301 | Box{4, 4, 4, RED},
302 | Box{10, 10, 1, YELLOW},
303 | Box{1, 1, 20, BLACK},
304 | Box{10, 10, 1, BLUE},
305 | Box{10, 30, 1, WHITE},
306 | Box{20, 20, 20, YELLOW},
307 | }
308 |
309 | fmt.Printf("We have %d boxes in our set\n", len(boxes))
310 | fmt.Println("The volume of the first one is", boxes[0].Volume(), "cm³")
311 | fmt.Println("The color of the last one is", boxes[len(boxes)-1].color.String())
312 | fmt.Println("The biggest one is", boxes.BiggestsColor().String())
313 | //I want it painted black
314 | fmt.Println("Let's paint them all black")
315 | boxes.PaintItBlack()
316 | fmt.Println("The color of the second one is", boxes[1].color.String())
317 | //obviously, it will be... BLACK!
318 | fmt.Println("Obviously, now, the biggest one is", boxes.BiggestsColor().String())
319 | }
320 |
321 | Output:
322 |
323 | .. container:: output
324 |
325 | | We have 6 boxes in our set
326 | | The volume of the first one is 64 cm³
327 | | The color of the last one is YELLOW
328 | | The biggest one is WHITE
329 | | Let's paint them all black
330 | | The color of the second one is BLACK
331 | | Obviously, now, the biggest one is BLACK
332 |
333 | So we defined some ``const``\s with consecutive values using the ``iota`` idiom
334 | to represent some colors.
335 |
336 | And then we declared some types:
337 |
338 | 1. ``Color`` which is an alias to ``byte``.
339 | 2. ``Box`` struct to represent a box, it has three dimensions and a color.
340 | 3. ``BoxList`` which is a slice of ``Box``.
341 |
342 | Simple and straightforward.
343 |
344 | Then we wrote some methods for these types:
345 |
346 | - ``Volume()`` with a receiver of type ``Box`` that returns the volume of the
347 | received box.
348 | - ``SetColor(c Color)`` sets its receiver's color to ``c``.
349 | - ``BiggestsColor()`` with a receiver of type ``BoxList`` returns the color of
350 | the ``Box`` with the biggest volume that exists within the slice.
351 | - ``PaintItBlack()`` with a receiver of type ``BoxList`` sets the colors of all
352 | ``Box``\es in the slice to BLACK.
353 | - ``String()`` a method with a receiver of type ``Color`` returns a string
354 | representation of this color.
355 |
356 | All this is simple. For real. We *translated* our vision of the problem into
357 | *things* that have methods that describe and implement a *behavior*.
358 |
359 | Pointer receivers
360 | =================
361 | Now, look at line 25 that I highlighted on purpose. The receiver is a pointer to
362 | Box! Yes, you can use ``*Box`` too. The restriction with methods is that the
363 | type ``Box`` itself (or any receiver's type) shouldn't be a pointer.
364 |
365 | Why did we use a pointer? You have 10 seconds to think about it, and then read
366 | on the next paragraph. I'll start counting:
367 |
368 | 10, 9, 8...
369 |
370 | Ready?
371 |
372 | Ok! Let's find out if you were correct.
373 | We used a pointer because we needed the ``SetColor`` method to be able to
374 | change the value of the field 'color' of its receiver. If we did not use a
375 | pointer, then the method would recieve a *copy* of the receiver ``b``
376 | (passed by value) and hence the changes that it will make will affect the copy
377 | only, not the original.
378 |
379 | Think of the receiver as a parameter that the method has in input, and
380 | ensure that you understand and remember the difference between
381 | :ref:`passing by value and reference`.
382 |
383 | Structs and pointers simplification
384 | -----------------------------------
385 | Again with the method ``SetColor``, intelligent readers
386 | (You are one of them, this I know!)
387 | would say that we should have written ``(*b).color = c`` instead of ``b.color =
388 | c``, since we need to dereference the pointer ``b`` to access the field color.
389 |
390 | This is true! In fact, both forms are accepted because Go knows that you want
391 | to access the fields of the value pointed to by the pointer (since a pointer has
392 | no notion of fields) so it assumes that you wanted ``(*b)`` and it simplifies
393 | this for you. Look Ma, Magic!
394 |
395 | Even more simplification
396 | ------------------------
397 | Experienced readers will also say:
398 |
399 | "On line 43 where we call ``SetColor`` on ``bl[i]``,
400 | shouldn't it be ``(&bl[i]).SetColor(BLACK)`` instead?
401 | Since ``SetColor`` expects a pointer of type ``*Box`` and not a value of
402 | type ``Box``?"
403 |
404 | This is also quite true! Both forms are accepted. Go automatically does
405 | the conversion for you because it *knows* what type the method expects as a
406 | receiver.
407 |
408 | In other words:
409 |
410 | If a method ``M`` expects a receiver of type ``*T``, you can call the method
411 | on a variable ``V`` of type ``T`` without passing it as ``&V`` to ``M``.
412 |
413 | Similarly:
414 |
415 | If a method ``M`` expects a receiver of type ``T``, you can call the method
416 | on a variable ``P`` of type ``*T`` without passing it as ``*P`` to ``M``.
417 |
418 | Example:
419 |
420 | .. code-block:: go
421 | :linenos:
422 |
423 | package main
424 | import "fmt"
425 |
426 | type Number int
427 |
428 | //method inc has a receiver of type pointer to Number
429 | func (n *Number) inc() {
430 | *n++
431 | }
432 |
433 | //method print has a receiver of type Number
434 | func (n Number) print() {
435 | fmt.Println("The number is equal to", n)
436 | }
437 |
438 | func main() {
439 |
440 | i := Number(10) //say that i is of type Number and is equal to 10
441 | fmt.Println("i is equal to", i)
442 |
443 | fmt.Println("Let's increment it twice")
444 | i.inc() //same as (&i).inc() method expects a pointer, but that's okay
445 | fmt.Println("i is equal to", i)
446 | (&i).inc() //this also works as expected
447 | fmt.Println("i is equal to", i)
448 |
449 | p := &i //p is a pointer to i
450 |
451 | fmt.Println("Let's print it twice")
452 | p.print() //same as (*p).print() method expects a value, but that's okay
453 | i.print() //this also works as expected
454 | }
455 |
456 | Output:
457 |
458 | .. container:: output
459 |
460 | | i is equal to 10
461 | | Let's increment it twice
462 | | i is equal to 11
463 | | i is equal to 12
464 | | Let's print it twice
465 | | The number is equal to 12
466 | | The number is equal to 12
467 |
468 | So don't worry, Go knows the type of a receiver, and knowing this it simplifies
469 | by accepting ``V.M()`` as a shorthand of ``(&V).M()`` and ``P.M()`` as a
470 | shorthand for ``(*P).M()``.
471 |
472 | Anyone who has done much C/C++ programming will have realized at this point the
473 | world of pain that Go saves us from by simply using sane assumptions.
474 |
475 | Well, well, well... I know these pointers/values matters hurt heads, take a
476 | break, go out, have a good coffee, and in the next chapter we will see some cool
477 | things to do with methods.
478 |
479 | .. external links and footnotes:
480 |
481 | .. _Rob Pike: http://groups.google.com/group/golang-nuts/msg/d05976004eb9f72b
482 |
--------------------------------------------------------------------------------
/even-more-functions.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | Even more on functions
4 | **********************
5 | In the previous chapter, we learned how to write variadic, and recursive
6 | functions and how to use the ``defer`` statement to defer functions calls to
7 | just before the currently executing function returns.
8 |
9 | In this chapter, we will learn something that might seem surprising a little
10 | bit, which will end up being *awesome*.
11 |
12 | Function types
13 | ==============
14 | Do you remember when we talked about
15 | :ref:`functions signatures `? That what matters most in a
16 | function, beside what it actually does, is the parameters and results numbers
17 | and types.
18 |
19 | Well, a function type denotes the set of all functions with the same parameter
20 | and result types.
21 |
22 | For example: the functions with signatures: func ``SUM(int, int) int`` and
23 | ``MAX(int, int) int`` are of the same type, because their parameter count,
24 | results count and types are the same.
25 |
26 | Does this sound strange? One computes a sum, and the other the max, yet they are
27 | both of the same type?
28 |
29 | Yes, they are. Picture this with me: The numbers 1, and 23 are both of the same
30 | type (``int``) yet their *values* are different. Paul and Sam are both of the
31 | same "human" type, yet their "values" (beliefs, jobs, weight...) are different.
32 |
33 | The function's body, what it actually does, is what makes the difference between
34 | two functions of the same type. Just like how many coffees you can by with 1
35 | dollar or 23 dollars.
36 |
37 | Same thing for functions: What they do, their bodies, is what differentiate two
38 | functions of the same type.
39 |
40 | Convinced? Let's see how to declare functions types.
41 |
42 | How to declare a function type?
43 | -------------------------------
44 | The syntax is simple:
45 |
46 | ``type type_name func(input1 inputType1 [, input2 inputType2 [, ...]) (result1 resultType1 [, ...])``
47 |
48 | Some examples to illustrate this:
49 |
50 | .. code-block:: go
51 | :linenos:
52 |
53 | // twoOne is the type of functions with two int parameters and an int result.
54 | // max(int, int) int and sum(int, int) int, for eg. are of this type.
55 | type twoOne func(int, int) int
56 |
57 | // slice_transform is the type of functions that takes a slice and outputs a
58 | // slice.
59 | // invert(s []int) []int and sort(s []int) []int are of this type.
60 | type slice_transform func(s []int) []int
61 |
62 | // varbytes is the type of variadic functions that takes bytes and outputs a
63 | // boolean.
64 | // redundant(...byte) bool, and contains_zero(...byte) bool are of this type
65 | type varbytes func(...byte) bool
66 |
67 | Is it clear now?
68 |
69 | *Yes, by why is this even useful or worth the hassle?* You might find yourself
70 | asking. Well, I'm glad you asked this question! Read on, you will see the
71 | beautiful madness to this method!
72 |
73 | Functions are values
74 | ====================
75 | Functions of the same type are values of this type! This means: You can declare
76 | a variable of a given function-type and assign any function of the same type to
77 | it. You can pass functions as parameters to other functions, you can also have
78 | functions that return other functions as results... And this, my friend, offers
79 | a lot of beautiful, intellignt and powerful opportunities! Let me show you some
80 | examples (don't worry, this doesn't result in Skynet... quite...).
81 |
82 | **Example 1**: Write a program which when given a slice of integers will return
83 | another slice which contains only the odd elements of the first slice (yes...
84 | of course... by 'odd' I meant the 'weird' ones... what is wrong with you people?!?).
85 |
86 | .. code-block:: go
87 | :linenos:
88 |
89 | package main
90 | import "fmt"
91 |
92 | type test_int func(int) bool
93 |
94 | // isOdd takes an ints and returns a bool set to true if the
95 | // int parameter is odd, or false if not.
96 | // isOdd is of type func(int) bool which is what test_int is declared to be.
97 |
98 | func isOdd(integer int) bool {
99 | if integer%2 == 0 {
100 | return false
101 | }
102 | return true
103 | }
104 |
105 | // Same comment for isEven
106 | func isEven(integer int) bool {
107 | if integer%2 == 0 {
108 | return true
109 | }
110 | return false
111 | }
112 |
113 | // We could've written:
114 | // func filter(slice []int, f func(int) bool) []int
115 | func filter(slice []int, f test_int) []int {
116 | var result []int
117 | for _, value := range slice {
118 | if f(value) {
119 | result = append(result, value)
120 | }
121 | }
122 | return result
123 | }
124 |
125 | func main(){
126 | slice := []int {1, 2, 3, 4, 5, 7}
127 | fmt.Println("slice = ", slice)
128 | odd := filter(slice, isOdd)
129 | fmt.Println("Odd elements of slice are: ", odd)
130 | even := filter(slice, isEven)
131 | fmt.Println("Even elements of slice are: ", even)
132 | }
133 |
134 | Output:
135 |
136 | .. container:: output
137 |
138 | | s = [1 2 3 4 5 7]
139 | | Odd elements of s are: [1 3 5 7]
140 | | Even elements of s are: [2 4]
141 |
142 | The functions ``isOdd`` and ``isEven`` are very simple.
143 | They both take an ``int``, and return a ``bool``.
144 | Of course, they're just little examples of functions of type ``test_int``.
145 | One can imagine more advanced and complex functions that are of this type.
146 |
147 | The interesting part is the ``filter`` function, which takes a slice of type
148 | ``[]int`` *and* a function of type ``test_int`` and returns a slice of type
149 | ``[]int``.
150 |
151 | Look at how we made a call ``f(value)`` on line 30. In fact, the function
152 | ``filter`` doesn't *care* how ``f`` works, what matters for it is that ``f``
153 | needs an ``int`` parameter, and that it returns a ``bool`` result.
154 |
155 | And we used this fact, in our ``main`` function. We called ``filter`` using
156 | different functions of type ``test_int``.
157 |
158 | If we're asked to extend the program to filter all the elements of the slice
159 | that, for example, are multiple of 3. All we would have to do is write a new
160 | function ``is3Multiple(i int) bool`` and use it with ``filter``.
161 |
162 | Now, if we want to filter the odd integers that are multiple of 3, we call
163 | filter twice likes this:
164 |
165 | ``slice := filter(filter(s, isOdd), is3Multiple)``
166 |
167 | The function ``filter`` is good at what it does. It filters a slice given a
168 | criteria, and this criteria is expressed in the form of functions.
169 |
170 | Cool, isn't it?
171 |
172 | Anonymous functions
173 | ===================
174 | In the previous example, we wrote the functions ``isOdd`` and ``isEven`` outside
175 | of the main function. It is possible to declare *anonymous* functions in Go,
176 | that is functions without a name, and assign them to variables.
177 |
178 | Let's see what this means with an example:
179 |
180 | .. code-block:: go
181 | :linenos:
182 |
183 | package main
184 | import "fmt"
185 |
186 | func main(){
187 | //add1 is a variable of type func(int) int
188 | //we don't declare the type since Go can guess it
189 | //by looking at the function being assigned to it.
190 | add1 := func(x int) int{
191 | return x+1
192 | }
193 |
194 | n := 6
195 | fmt.Println("n = ", n)
196 | n = add1(n)
197 | fmt.Println("add1(n) = ", n)
198 | }
199 |
200 | Output:
201 |
202 | .. container:: output
203 |
204 | | n = 6
205 | | add1(n) = 7
206 |
207 | Our variable ``add1`` is assigned a *complete* function definition, minus the
208 | name. This function is said to be "anonymous" for this reason (lack of a name).
209 |
210 | Let's see an example using anonymous functions, and that returns functions.
211 |
212 | Functions that return functions
213 | ===============================
214 | Back to the filtering problem, but now, we'd like to design it differently. We
215 | want to write a function ``filter_factory`` that given a single function ``f``
216 | like ``isOdd``, will produce a new function that takes a slice ``s`` of ints,
217 | and produces two slices:
218 |
219 | * ``yes``: a slice of the elements of ``s`` for which ``f`` returns ``true``.
220 | * ``no``: a slice of the elements of ``s`` for which ``f`` returns ``false``.
221 |
222 | .. code-block:: go
223 | :linenos:
224 |
225 | package main
226 | import "fmt"
227 |
228 | func isOdd(integer int) bool{
229 | if integer%2 == 0 {
230 | return false
231 | }
232 | return true
233 | }
234 |
235 | func isBiggerThan4(integer int) bool{
236 | if integer > 4 {
237 | return true
238 | }
239 | return false
240 | }
241 |
242 | /*
243 | filter_factory
244 | input: a criteria function of type: func(int) bool
245 | output: a "spliting" function of type: func(s []int) (yes, no []int)
246 | --
247 | To wrap your head around the declaration below, consider it this way:
248 | //declare parameter and result types
249 | type test_int func (int) bool
250 | type slice_split func([]int) ([]int, []int)
251 | and then declare it like this:
252 | func filter_factory(f test_int) slice_split
253 | --
254 | In summary: filter_factory takes a function, and creates another one
255 | of a completly different type.
256 | */
257 | func filter_factory(f func(int) bool) (func (s []int) (yes, no []int)){
258 | return func(s []int) (yes, no []int){
259 | for _, value := range s{
260 | if f(value){
261 | yes = append(yes, value)
262 | } else {
263 | no = append(no, value)
264 | }
265 | }
266 | return //look, we don't have to add yes, no. They're named results.
267 | }
268 | }
269 |
270 | func main(){
271 | s := []int {1, 2, 3, 4, 5, 7}
272 | fmt.Println("s = ", s)
273 | odd_even_function := filter_factory(isOdd)
274 | odd, even := odd_even_function(s)
275 | fmt.Println("odd = ", odd)
276 | fmt.Println("even = ", even)
277 |
278 | //separate those that are bigger than 4 and those that are not.
279 | //this time in a more compact style.
280 | bigger, smaller := filter_factory(isBiggerThan4)(s)
281 | fmt.Println("Bigger than 4: ", bigger)
282 | fmt.Println("Smaller than or equal to 4: ", smaller)
283 | }
284 |
285 | Output:
286 |
287 | .. container:: output
288 |
289 | | s = [1 2 3 4 5 7]
290 | | odd = [1 3 5 7]
291 | | even = [2 4]
292 | | Bigger than 4: [5 7]
293 | | Smaller than or equal to 4: [1 2 3 4]
294 |
295 | How does this work? First, we won't discuss ``isOdd`` and ``isBiggerThan4``
296 | they're simple and both of the same type: ``func(int) bool``. That's all that
297 | matters for us, now.
298 |
299 | Now the heart of the program: the ``filter_factory`` function. Like stated in
300 | the comments, this function takes as a parameter a function ``f`` of type
301 | ``fun(int) bool`` (i.e. the same as ``isOdd`` and ``isBiggerThan4``)
302 |
303 | filter_factory returns an anonymous function that is of type:
304 | ``func([]int)([]int, []int)`` --or in plain english: a function that takes a
305 | slice of ints as its parameters and outputs two slices of ints.
306 |
307 | This anonymous function, justly, uses ``f`` to decide where to *copy* each
308 | element of its input slice. if ``f(value)`` returns ``true`` then append it to
309 | the ``yes`` slice, else append it to the ``no`` slice.
310 |
311 | Like the ``filter`` function in the first example, the anonymous function
312 | doesn't *care* how ``f`` works. All it knows is that if it gives it an ``int``
313 | it will return a ``bool``. And that's enough to decide where to append the
314 | value; in the ``yes`` or the ``no`` slices.
315 |
316 | Now, back to the ``main`` function and how we use ``filter_factory`` in it.
317 |
318 | Two ways:
319 |
320 | The detailed one: we declare a variable ``odd_even_function`` and we assign to
321 | it the result of calling ``filter_factory`` with ``isOdd`` as its parameter. So
322 | odd_even_function is of type ``func([]int) ([]int, []int)``.
323 |
324 | We call ``odd_even_function`` with ``s`` as its parameters and we retrieve two
325 | slices: ``odd`` and ``even``.
326 |
327 | The second way is compact. The call ``filter_factory(isBiggerThan4)`` returns a
328 | function of type ``func([]int)([]int, []int)`` so we use that directly with our
329 | slice ``s`` and retrieve two slices: ``bigger`` and ``smaller``.
330 |
331 | Does it make sense, now? Re-read the code if not, it's actually simple.
332 |
333 | Functions as data
334 | =================
335 | Since functions have types, and can be assigned to variables, one might wonder
336 | whether it is possible to, for example, have an array or a slice of functions?
337 | Maybe a struct with a function field? Why not a map?
338 |
339 | All this is possible in fact and, when used intelligently, can help you write
340 | simple, readable and elegant code.
341 |
342 | Let's see a silly one:
343 |
344 | .. code-block:: go
345 | :linenos:
346 |
347 | package main
348 | import "fmt"
349 |
350 | //These consts serve as names for activities
351 | const(
352 | STUDENT = iota
353 | DOCTOR
354 | MOM
355 | GEEK
356 | )
357 |
358 | //we create an "alias" of byte and name it "activity"
359 | type activity byte
360 |
361 | //A person has activities (a slice of activity) and can speak.
362 | type person struct{
363 | activities []activity
364 | speak func()
365 | }
366 |
367 | //people is a map string:person we access persons by their names
368 | type people map[string] person
369 |
370 | //phrases is a map activity:string. Associates a phrase with an activity.
371 | type phrases map[activity] string
372 |
373 | /*
374 | The function compose takes a map of available phrases
375 | and constructs a function that prints a sentence with these
376 | phrases that are appropriate for a "list" of the activities
377 | given in the slice a
378 | */
379 | func compose(p phrases, a []activity) (func()){
380 | return func(){
381 | for key, value := range a{
382 | fmt.Print(p[value])
383 | if key == len(a)-1{
384 | fmt.Println(".")
385 | } else {
386 | fmt.Print(" and ")
387 | }
388 | }
389 | }
390 | }
391 |
392 | func main(){
393 | // ph contains some phrases per activities
394 | ph := phrases{
395 | STUDENT: "I read books",
396 | DOCTOR: "I fix your head",
397 | MOM: "Dinner is ready!",
398 | GEEK: "Look ma! My compiler works!"}
399 |
400 | // a group of persons, and their activities
401 | folks := people{
402 | "Sam": person{activities:[]activity{STUDENT}},
403 | "Jane": person{activities:[]activity{MOM, DOCTOR}},
404 | "Rob": person{activities:[]activity{GEEK, STUDENT}},
405 | "Tom": person{activities:[]activity{GEEK, STUDENT, DOCTOR}},
406 | }
407 |
408 | // Let's assign them their function "speak"
409 | // depending on their activities
410 | for name, value := range folks{
411 | f := compose(ph, value.activities)
412 | k := value.activities
413 | //update the map's entry with a different person with the
414 | //same activities and their function speak.
415 | folks[name] = person{activities:k, speak:f}
416 | }
417 |
418 | // Now that they know what to say, let's hear them.
419 | for name, value := range folks{
420 | fmt.Printf("%s says: ", name)
421 | value.speak()
422 | }
423 | }
424 |
425 | Output:
426 |
427 | .. container:: output
428 |
429 | | Sam says: I read books.
430 | | Rob says: Look ma! My compiler works! and I read books.
431 | | Jane says: Dinner is ready! and I fix your head.
432 | | Tom says: Look ma! My compiler works! and I read books and I fix your head.
433 |
434 | It may sound funny, and probably silly, but what I wanted to show you is how
435 | functions can be used as ``struct`` fields just as simply as classic data types.
436 |
437 | Yes, I know what you are thinking; It would have been more elegant if the
438 | function ``speak`` of the type ``person`` could access her ``activities`` by
439 | itself and we won't even need the ``compose`` function then.
440 |
441 | That's called "Object Oriented Programming" (OOP), and even though Go isn't
442 | really an OOP language, it supports some notions of it. This will be the subject
443 | of our next chapter. Stay tuned, you, geek! :)
444 |
445 |
--------------------------------------------------------------------------------
/more-functions.rst:
--------------------------------------------------------------------------------
1 | .. include:: common.txt
2 |
3 | Getting funky with functions
4 | ****************************
5 | In the previous chapters, we went from how to declare variables, pointers, how
6 | to write basic control structures, how to combine these control structures to
7 | write functions. Then we went back to data, and how to combine basic data types
8 | to create composite data types.
9 |
10 | And now, armed with this knowledge, we're ready to work on advanced aspects of
11 | functions.
12 |
13 | I decided to divide this task in two chapters, not because the things we're
14 | about to study are hard, but mainly because it's easier, and more fun to work on
15 | a few topics at a time.
16 |
17 | Variadic functions
18 | ==================
19 | Do you remember when I made you :ref:`cringe ` at the idea of writing
20 | a function ``Older100`` that will not accept less than 100 ``person``\s?
21 | ``struct``\s as its input?
22 |
23 | Well I lied a little bit, but it was a good lie. I duct-taped you to a chair
24 | with that blindfold on with the best of intentions, I swear!
25 | It was an excellent reason to learn about arrays, and later about slices!
26 | Relax... it's for your own safety! ;)
27 |
28 | The truth is: you can have functions that accept a *variable* number of input
29 | parameters of the *same* type. They're called *variadic functions*.
30 |
31 | These functions can be declared like this:
32 |
33 | ``func function_name(args ...inputType) (output1 OutputType1 [, output2 OutputType2 [, ...]])``
34 |
35 | There's no difference from the way we learned to declare functions, except the
36 | three dots (called an ellipses) thing:``...inputType`` which says to the function that it can
37 | recieve a variable number of parameters all of them of type ``inputType``.
38 |
39 | How does this work? Easy: In fact, the ``args`` identifier you see in the input
40 | parameter is actually a slice which contains all of the parameters passed in (
41 | which should all be of type ``inputType``).
42 |
43 | A slice! Yay! So we can, in the function's body, iterate using ``range`` to get
44 | all the parameters! Yes, that's the way you do it. You play the guitar on the
45 | mtv... er, sorry. I got a case of *Mark Knopfler* fever.
46 |
47 | Let's see an example:
48 |
49 | .. code-block:: go
50 | :linenos:
51 |
52 | package main
53 | import "fmt"
54 |
55 | // Our struct representing a person
56 | type person struct {
57 | name string
58 | age int
59 | }
60 |
61 | // Return true, and the older person in a group of persons
62 | // Or false, and nil if the group is empty.
63 | func Older(people ...person) (bool, person) { // Variadic function.
64 | if(len(people) == 0){return false, person{}} // The group is empty.
65 | older := people[0] // The first one is the older FOR NOW.
66 | // Loop through the slice people.
67 | for _, value := range people{ // We don't need the index.
68 | // Compare the current person's age with the oldest one so far
69 | if value.age > older.age {
70 | older = value //if value is older, replace older
71 | }
72 | }
73 | return true, older
74 | }
75 |
76 | func main(){
77 |
78 | // Two variables to be used by our program.
79 | var(
80 | ok bool
81 | older person
82 | )
83 |
84 | // Declare some persons.
85 | paul := person{"Paul", 23};
86 | jim := person{"Jim", 24};
87 | sam := person{"Sam", 84};
88 | rob := person{"Rob", 54};
89 | karl := person{"Karl", 19};
90 |
91 | // Who is older? Paul or Jim?
92 | _, older = Older(paul, jim) //notice how we used the blank identifier
93 | fmt.Println("The older of Paul and Jim is: ", older.name)
94 | // Who is older? Paul, Jim or Sam?
95 | _, older = Older(paul, jim, sam)
96 | fmt.Println("The older of Paul, Jim and Sam is: ", older.name)
97 | // Who is older? Paul, Jim , Sam or Rob?
98 | _, older = Older(paul, jim, sam, rob)
99 | fmt.Println("The older of Paul, Jim, Sam and Rob is: ", older.name)
100 | // Who is older in a group containing only Karl?
101 | _, older = Older(karl)
102 | fmt.Println("When Karl is alone in a group, the older is: ", older.name)
103 | // Is there an older person in an empty group?
104 | ok, older = Older() //this time we use the boolean variable ok
105 | if !ok {
106 | fmt.Println("In an empty group there is no older person")
107 | }
108 | }
109 |
110 | Output:
111 |
112 | .. container:: output
113 |
114 | | The older of Paul and Jim is: Jim
115 | | The older of Paul, Jim and Sam is: Sam
116 | | The older of Paul, Jim, Sam and Rob is: Sam
117 | | When Karl is alone in a group, the older is: Karl
118 | | In an empty group there is no older person
119 |
120 | Look how we called the function ``Older`` with 2, 3, 4, 1 and even no input
121 | parameters at all. We could have called it with 100 ``person``\s if we wanted
122 | to.
123 |
124 | Variadic functions are easy to write and can be handy in a lot of situations. By
125 | the way, I promised to tell you about the built-in function called ``append``
126 | that makes appending to slices easier! Now, I can tell you more, because, guess
127 | what? The built-in ``append`` function is a variadic function!
128 |
129 | The built-in append function
130 | ----------------------------
131 | The append function has the following signature:
132 |
133 | ``func append(slice []T, elements...T) []T``.
134 |
135 | It takes a slice of type ``[]T``, and as many other ``elements`` of the same
136 | type ``T`` and returns a new slice of type ``[]T`` which includes the given
137 | elements.
138 |
139 | Example:
140 |
141 | .. code-block:: go
142 | :linenos:
143 |
144 | package main
145 | import "fmt"
146 |
147 | func main(){
148 | slice := []int {1, 2, 3}
149 | fmt.Println("At first: ")
150 | fmt.Println("slice = ", slice)
151 | fmt.Println("len(slice) = ", len(slice))
152 | fmt.Println("Let's append 4 to it")
153 | slice = append(slice, 4)
154 | fmt.Println("slice = ", slice)
155 | fmt.Println("len(slice) = ", len(slice))
156 | fmt.Println("Let's append 5 and 6 to it")
157 | slice = append(slice, 5, 6)
158 | fmt.Println("slice = ", slice)
159 | fmt.Println("len(slice) = ", len(slice))
160 | fmt.Println("Let's append 7, 8, and 9 to it")
161 | slice = append(slice, 7, 8, 9)
162 | fmt.Println("slice = ", slice)
163 | fmt.Println("len(slice) = ", len(slice))
164 | }
165 |
166 | Output:
167 |
168 | .. container:: output
169 |
170 | | At first:
171 | | slice = [1 2 3]
172 | | len(slice) = 3
173 | | Let's append 4 to it
174 | | slice = [1 2 3 4]
175 | | len(slice) = 4
176 | | Let's append 5 and 6 to it
177 | | slice = [1 2 3 4 5 6]
178 | | len(slice) = 6
179 | | Let's append 7, 8, and 9 to it
180 | | slice = [1 2 3 4 5 6 7 8 9]
181 | | len(slice) = 9
182 |
183 | You can even give a variadic function a slice of type ``[]T`` instead of a list
184 | of comma-separated parameters of type ``T``.
185 |
186 | Example:
187 |
188 | .. code-block:: go
189 | :linenos:
190 |
191 | // Two slices of ints
192 | a_slice := []int {1, 2, 3}
193 | b_slice := []int {10, 11, 12}
194 | a_slice = append(a_slice, b_slice...) // Note the syntax: the slice followed by three dots
195 | // a_slice == {1, 2, 3, 10, 11, 12}
196 |
197 | Again, just in case you glossed over the comment, notice the ellipses '``...``'
198 | immediately following the second slice argument to the variadic function.
199 |
200 | Using the append function to delete an element
201 | ----------------------------------------------
202 | Suppose that we have a slice ``s`` and that we would like to delete an element
203 | from it. There are 3 cases to consider:
204 |
205 | * The element we'd like to delete is the first one of the slice.
206 | * The element we'd like to delete is the last one of the slice
207 | * The element we'd like to delete is the one at index ``i`` of the slice (where
208 | ``i`` is between the first and the last ones)
209 |
210 | Let's write a function that deletes the element at a given index ``i`` in a
211 | given slice of ``int``\s and see how the ``append`` function can help.
212 |
213 | .. code-block:: go
214 | :linenos:
215 |
216 | package main
217 | import "fmt"
218 |
219 | func delete(i int, slice []int) []int{
220 | switch i {
221 | case 0: slice = slice[1:]
222 | case len(slice)-1: slice = slice[:len(slice)-1]
223 | default: slice = append(slice[:i], slice[i+1:]...)
224 | }
225 | return slice
226 | }
227 |
228 | func main(){
229 | slice := []int {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
230 | fmt.Println("In the beginning...")
231 | fmt.Println("slice = ", slice)
232 | fmt.Println("Let's delete the first element")
233 | slice = delete(0, slice)
234 | fmt.Println("slice = ", slice)
235 | fmt.Println("Let's delete the last element")
236 | slice = delete(len(slice)-1, slice)
237 | fmt.Println("slice = ", slice)
238 | fmt.Println("Let's delete the 3rd element")
239 | slice = delete(2, slice)
240 | fmt.Println("slice = ", slice)
241 | }
242 |
243 | Output:
244 |
245 | .. container:: output
246 |
247 | | In the beginning...
248 | | slice = [1 2 3 4 5 6 7 8 9 10]
249 | | Let's delete the first element
250 | | slice = [2 3 4 5 6 7 8 9 10]
251 | | Let's delete the last element
252 | | slice = [2 3 4 5 6 7 8 9]
253 | | Let's delete the 3rd element
254 | | slice = [2 3 5 6 7 8 9]
255 |
256 | The lines 6 and 7 of our program are fairly easy to understand. Aren't they?
257 | We re-slice our slice omitting the first and the last elements respectively.
258 |
259 | Now, the case where the element is not the first nor the last one. We assign to
260 | our slice the result of ``append`` of the slice starting from the first up to,
261 | but not including, the ``i`` :sup:`th` element and the slice that starts from
262 | the element after the ``i`` :sup:`th` (i.e. i+1) up to the last one. That is, we
263 | made our slice contain elements from the right sub-slice and the left one to the
264 | element that we want to delete.
265 |
266 | .. graphviz::
267 |
268 | digraph delete_from_slice {
269 |
270 | //rankdir=LR;
271 | graph [bgcolor=transparent, resolution=96, fontsize="10" ];
272 | edge [arrowsize=.5, arrowtail="dot", color="#FF6600"];
273 | node [fontsize=8, height=.1, penwidth=.4]
274 | s [shape=plaintext, label=<
275 |
276 |
277 |
2
278 |
3
279 |
4
280 |
5
281 |
6
282 |
7
283 |
8
284 |
9
285 |
s
286 |
287 |
288 |
0
289 |
1
290 |
2
291 |
3
292 |
4
293 |
5
294 |
6
295 |
7
296 |
297 |
298 |
>]
299 | s1 [shape=plaintext, label=<
300 |
301 |
302 |
2
303 |
3
304 |
5
305 |
6
306 |
7
307 |
8
308 |
9
309 |
new s after deleting the 3rd element
310 |
311 |
312 |
0
313 |
1
314 |
2
315 |
3
316 |
4
317 |
5
318 |
6
319 |
320 |
321 |
>]
322 | s1:f0:n->s:f0:s
323 | s1:f1:n->s:f1:s
324 | {rank=sink; s1}
325 | }
326 |
327 | Simple, isn't it? Now, we actually complicated the ``delete`` function in vain.
328 | We could have written it like this:
329 |
330 | .. code-block:: go
331 | :linenos:
332 |
333 | //simpler delete
334 | func delete(i int, slice []int) []int{
335 | slice = append(slice[:i], slice[i+1:]...)
336 | return slice
337 | }
338 |
339 | Yes, it will work. Go and try it. Can you figure out why?
340 | (**Hint**: empty. **Hint Hint**: empty.)
341 |
342 | Recursive functions
343 | ===================
344 | Some algorithmic problems can be thought of in a beautiful way using recursion!
345 |
346 | A function is said to be *recursive* when it calls itself within it's own body.
347 | For example:
348 | the Max value in a slice is the maximum of the Max value of two sub-slices of
349 | the same slice, one starting from 0 to the middle and the other starting from
350 | the middle to the end of the slice.
351 | To find out the Max in each sub-slice we use the same function,
352 | since a sub-slice is itself a slice!
353 |
354 | Enough talk already, let's see this wonderous beast in action!
355 |
356 | .. code-block:: go
357 | :linenos:
358 |
359 | package main
360 | import "fmt"
361 |
362 | //Recursive Max
363 | func Max(slice []int) int{
364 | if len(slice) == 1 {
365 | return slice[0] //there's only one element in the slice, return it!
366 | }
367 |
368 | middle := len(slice)/2 //the middle index of the slice
369 | //find out the Max of each sub-slice
370 | m1 := Max(slice[:middle])
371 | m2 := Max(slice[middle:])
372 | //compare the Max of two sub-slices and return the bigger one.
373 | if m1 > m2 {
374 | return m1
375 | }
376 | return m2
377 | }
378 |
379 | func main(){
380 | s := []int {1, 2, 3, 4, 6, 8}
381 | fmt.Println("Max(s) = ", Max(s))
382 | }
383 |
384 | Output:
385 |
386 | .. container:: output
387 |
388 | | Max(s) = 8
389 |
390 | Another example: How to invert the data in a given slice of ints?
391 | For example, given ``s := []int {1, 2, 3, 4, 5}``, we want our program to modify
392 | ``s`` to be ``{5, 4, 3, 2, 1}``.
393 |
394 | A recursive strategy to do this involves first swapping the first and the last
395 | elements of ``s`` and then inverting the slice between these elements,
396 | i.e. the one from the 2nd element to the one just before the last one.
397 |
398 |
399 | .. graphviz::
400 |
401 | digraph slice_invert {
402 |
403 | //rankdir=LR;
404 | graph [bgcolor=transparent, resolution=96, fontsize="10" ];
405 | edge [arrowsize=.5, color="#FF6600"];
406 | node [fontsize=8, height=.1, penwidth=.4]
407 | a [shape=plaintext, label=<
408 |
>]
442 | }
443 |
444 | Let's write it:
445 |
446 | .. code-block:: go
447 | :linenos:
448 |
449 | package main
450 | import "fmt"
451 |
452 | func Invert(slice []int){
453 | length := len(slice)
454 | if length > 1 { // Only a slice of 2 or more elements can be inverted
455 | slice[0], slice[length-1] = slice[length-1], slice[0] // Swap first and last ones
456 | Invert(slice[1:length-1]) // Invert the slice in between
457 | }
458 | }
459 |
460 | func main(){
461 | slice := []int {1, 2, 3, 4, 5}
462 | fmt.Println("slice = ", slice)
463 | Invert(slice)
464 | fmt.Println("Invert(slice) = ", slice)
465 | }
466 |
467 | Output:
468 |
469 | .. container:: output
470 |
471 | | slice = [1 2 3 4 5]
472 | | Invert(slice) = [5 4 2 3 1]
473 |
474 | **Exercise** Recursive absurdity! The SUM of the ints in a given slice is equal
475 | to the first element *plus* the SUM of the subslice starting from the second
476 | element. Go and write this program.
477 |
478 | And these are but a few examples, many problems can be solved using recursion.
479 | You know, just like walking: to walk, you put one foot in front of the other and
480 | you walk :)
481 |
482 | The defer statement
483 | ===================
484 | Sometimes you'd like to do *something* just before a ``return`` statement of a
485 | function, like for example closing an opened file.
486 | Now, suppose that our function has many spots where we call ``return``, like for
487 | example in a ``if``/``else`` chain, or in a ``switch`` statement. In these cases
488 | we'd do that *something* as many times as there is a ``return``.
489 |
490 | The ``defer`` statement fixes this annoying irreverant mind-numbing repetition.
491 |
492 | The ``defer`` statement schedules a function call (the deferred function) to be
493 | run immediately before the function executing the ``defer`` returns.
494 |
495 | Let's see an example to make the idea clearer:
496 |
497 | The `os package`_ comes with functions to open, close, create... files, Go
498 | figure!.
499 | Being a good lil programmer means that we have to close every file we open in
500 | our program after we've done our nefarious business with it's contents.
501 |
502 | Now, imagine a function that opens a file, processes the data in it, but has
503 | many return spots in its body. Without ``defer`` you'll have to *manually* close
504 | any already opened file, just before the ``return``.
505 |
506 | Look at this simple program from `Effective Go`_.
507 |
508 | .. code-block:: go
509 | :linenos:
510 |
511 | package main
512 |
513 | import(
514 | "os"
515 | "fmt"
516 | )
517 |
518 | // Contents returns the file's contents as a string.
519 | func Contents(filename string) (string, os.Error) {
520 | f, err := os.Open(filename)
521 | if err != nil {
522 | return "", err
523 | }
524 | defer f.Close() // f.Close will run when we're finished.
525 |
526 | var result []byte
527 | buf := make([]byte, 100)
528 | for {
529 | n, err := f.Read(buf[0:])
530 | result = append(result, buf[0:n]...) // append is discussed later.
531 | if err != nil {
532 | if err == os.EOF {
533 | break
534 | }
535 | return "", err // f will be closed if we return here.
536 | }
537 | }
538 | return string(result), nil // f will be closed if we return here.
539 | }
540 |
541 |
542 | func main() {
543 | contents, _ := Contents("/etc/hosts")
544 | fmt.Println(contents)
545 | }
546 |
547 | Our function ``Contents`` needs a file name as its input, and it ouputs this
548 | file's content, and an eventual error (for example in case the file was not
549 | found).
550 |
551 | On line 10, we open the file. If the returned error from ``os.Open`` is not ``nil``
552 | then we were unable to open the file. So we return an empty string and the same
553 | error that ``os.Open`` returned.
554 |
555 | Then on line 14, we ``defer`` the call to ``f.Close()`` so that the file will be
556 | *automatically* closed when the function emits a return (2 spots in our function).
557 |
558 | Then we declare a ``result`` slice that will contain all the bytes read from the
559 | file. And we make a buffer ``buf`` of 100 bytes that will be used to read 100
560 | bytes at a time from our file using the call to ``f.Read``. This buffer will be
561 | appended to``result`` each time it's filled with ``f.Read``.
562 |
563 | And we loop. If we get an error while reading, we check if its ``os.EOF`` (EOF
564 | means End Of File) if so, we ``break`` from the loop, else it's another error so
565 | we return an empty string and that error.
566 |
567 | At the end, we return the slice ``result`` converted to a string, using a type
568 | casting and ``nil`` which means that there was no error while retrieving the
569 | contents of the file.
570 |
571 | I know, this example may look a little bit hard, especially since we have never used
572 | the ``os`` package before, but the main goal of it is to show you a use of the
573 | ``defer`` statement. And how it can be used to guarantee two things:
574 |
575 | - Using ``defer f.Close()`` in the beginning makes sure that you will never
576 | forget to close the file, no matter how the function might change in the
577 | future, and no matter how many ``return`` spots will be added/removed from it.
578 |
579 | - The close sits near the open, which is much clearer than placing it at the end
580 | of the function.
581 |
582 | Multiple defer calls
583 | --------------------
584 | You can defer as many function calls as you want, and they'll be executed before
585 | the containing function returns in a LIFO (Last In First Out) order. That is,
586 | the last one to be deferred will be run first, and the first one will be executed
587 | at last.
588 |
589 | Example:
590 |
591 | .. code-block:: go
592 | :linenos:
593 |
594 | package main
595 | import "fmt"
596 |
597 | func A() {
598 | fmt.Println("Running function A")
599 | }
600 |
601 | func B() {
602 | fmt.Println("Running function B")
603 | }
604 |
605 | func main(){
606 | defer A()
607 | defer B()
608 | }
609 |
610 | Output:
611 |
612 | .. container:: output
613 |
614 | | Running function B
615 | | Running function A
616 |
617 |
618 | And that's it for this chapter. We learned how to write variadic, and recursive
619 | functions, and how to defer function calls. The next chapter will be even more
620 | interesting, we will see how functions are, actually, values!
621 |
622 | .. external links and footnotes:
623 |
624 | .. _os package: http://golang.org/pkg/os/index.html
625 | .. _Effective Go: http://golang.com/doc/effective_go.html#defer
626 |
--------------------------------------------------------------------------------