├── 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 |
30 |
31 |

{{ docstitle }}

32 |
33 | 34 |
35 | 36 |
37 | {% block body %}{% endblock %} 38 |
39 | 40 | 49 |
50 | 51 | {% block sidebarwrapper %} 52 | 59 |
60 | {% endblock %} 61 |
62 | {% endblock %} 63 | 64 | {% block sidebarrel %} 65 |

Browse

66 | 74 |

You are here:

75 | 85 | {% endblock %} 86 | 87 | {# Empty some default blocks out #} 88 | {% block relbar1 %}{% endblock %} 89 | {% block relbar2 %}{% endblock %} 90 | {% block sidebar1 %}{% endblock %} 91 | {% block sidebar2 %}{% endblock %} 92 | {% block footer %}{% endblock %} 93 | {% block sidebarsourcelink %}{% endblock %} 94 | 95 | {# Search box #} 96 | {% block sidebarsearch %} 97 | {%- if pagename != "search" %} 98 | 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 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 |
KeyValue
"one"1
"ten"10
"trois"3
numbers
>] 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 | 263 | 264 | 265 |
Tom25
>] 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 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 |
23456789s
01234567
>] 299 | s1 [shape=plaintext, label=< 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 |
2356789new s after deleting
the 3rd element
0123456
>] 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 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 |
step 112345
>] 418 | a:f0:n->a:f4:n [dir=both, label="swap", fontsize=8] 419 | a:f1:s->a:f3:s [dir=both, label="sub-slice", fontsize=8, 420 | penwidth=2, color="lightblue"] 421 | 422 | b [shape=plaintext, label=< 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 |
step 2234
>] 431 | b:f0:n->b:f2:n [dir=both, label="swap", fontsize=8] 432 | b:f1:s->b:f1:s [dir=both, label="sub-slice", fontsize=8, 433 | penwidth=2, color="lightblue"] 434 | 435 | c [shape=plaintext, label=< 436 | 437 | 438 | 439 | 440 | 441 |
step 33
>] 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 | --------------------------------------------------------------------------------