Support Statistics
¥.00 ·
0times
Text Preview (First 20 pages)
Registered users can read the full content for free
Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.
Page
1
(This page has no text content)
Page
2
Table of Contents Chapter 1: Ready... Steady... Go! 1 A little bit of history 1 Installing Go 2 Linux 2 Go Linux advanced installation 3 Windows 3 Mac OS X 4 Setting the workspace- Linux and Apple OS X 4 Starting with Hello World 5 Integrated Development Environment – IDE 6 Types 7 Variables and constants 8 Operators 9 Flow control 10 The if/else statement 10 The switch statement 11 The for, range statement 11 Functions 12 What does a function looks like? 12 What is an anonymous function? 13 Function with undetermined number of parameters 14 Naming returned types 15 Arrays, slices and maps 15 Arrays 15 Zero-initialization 16 Slices 16 Maps 17 Visibility 18 Zero-initialization 18 Pointers and structures 20 What is a pointer? Why are they good? 20 Structs 21 Interfaces 23 Interfaces – Signing a contract 23 Testing and TDD 25
Page
3
[ ii ] The testing package 25 What is TDD? 27 Libraries 29 Go get 31 Managing JSON data 32 The encoding package 33 Go tools 35 The golint tool 35 The gofmt tool 36 The godoc tool 37 The goimport tool 37 Contributing to Go open source projects in GitHub 38 Summary 39 Chapter 2: Creational Patterns: Singleton, Builder, Factory, Prototype, and Abstract Factory 40 Singleton design pattern – Having a unique instance of an object in the entire program 40 Description 40 Objective of the Singleton pattern 41 The example – A unique counter 41 Requirements and acceptance criteria 41 First unit test 41 Implementation 44 Summarizing the Singleton design pattern 45 Builder design pattern- Reusing an algorithm to create many implementations of an interface 45 Description 45 Objective of the Builder pattern 46 The example – vehicle manufacturing 46 Requirements and acceptance criteria 46 Unit test for the vehicle builder 46 Implementation 50 Summarizing the Builder design pattern 53 Factory method – Delegating the creation of different types of payments 53 Description 53 Objective of the Factory method 54 The example – A factory of payment methods for a shop 54 Acceptance criteria 55
Page
4
[ iii ] First unit test 55 Implementation 58 Upgrading the Debit card method to a new platform 60 Summarizing the Factory method 61 Abstract Factory – A factory of factories 62 Description 62 The objective 62 The vehicle factory example – again? 62 Acceptance criteria 63 Unit test one 63 Implementation 69 Summarizing the Abstract Factory method 70 Prototype design pattern 71 Description 71 Objective 71 The example 71 Acceptance Criteria 71 Unit test 72 Implementation 74 Summarizing the Prototype design pattern 76 Summary 76 Chapter 3: Structural patterns: Composite, Adapter, and Bridge design patterns 77 Composite design pattern 77 Description 77 Objective of the Composite pattern 78 The swimmer and the fish 78 Requirements and acceptance criteria 78 Creating compositions 79 Binary Trees compositions 83 Composite pattern versus inheritance 83 Final words on Composite pattern 84 Adapter design pattern 85 Description 85 Objective of the Adapter pattern 85 Using an incompatible interface by an Adapter object 86 Requirements and acceptance criteria 86 Unit testing our Printer Adapter 86 Implementation 88
Page
5
[ iv ] Examples of Adapter pattern in Go's source code 89 What the Go source code tells us about the Adapter pattern 93 Bridge design pattern 93 Description 93 Objective of the Bridge pattern 94 Two printers and two ways of printing for each 94 Requirements and acceptance criteria 94 Unit testing the Bridge pattern 95 Implementation 101 Reuse everything with the Bridge pattern 104 Summary 105 Chapter 4: Structural Patterns: Proxy, Facade, Decorator, and Flyweight design Patterns 106 Proxy 106 Description 106 Objective 106 The example 107 Acceptance criteria 107 Unit test 107 Implementation 112 Proxying around actions 115 Decorator design pattern 115 Description 115 Objectives of the Decorator design pattern 115 The example 116 Acceptance criteria 116 Unit test 116 Implementation 120 A real life example-server middleware 122 Starting with the common interface, http.ServeHTTP 123 Few words about Go's structural typing 128 Summarizing the Decorator design pattern – Proxy versus Decorator 129 Facade design pattern 129 Description 129 Objectives of the Facade design pattern 129 Our example 130 Acceptance criteria 130 Unit test 130 Implementation 134
Page
6
[ v ] Library created with the Facade pattern. 137 Flyweight design pattern 137 Description 138 Objectives of the Flyweight design pattern 138 Our example 138 Acceptance criteria 139 Basic structs and tests 139 Implementation 141 What's the difference between Singleton and Flyweight then? 145 Summary 145 Chapter 5: Behavioral Patterns - Strategy, Chain of Responsibility, and Command Design Patterns 147 Strategy design pattern 147 Description 147 Objectives of the Strategy pattern 148 The example – rendering images or text 148 Acceptance criteria 148 Implementation 149 Solving small issues in our library 153 Final words on the Strategy pattern 158 Chain of responsibility design pattern 159 Description 159 Objectives of the Chain of responsibility pattern 159 The example – a multi-logger chain 160 Unit tests 160 Implementation 165 What about a closure? 167 Putting it together 169 Command design pattern 169 Description 170 Objectives of the Command design pattern 170 The example – a simple queue 170 Acceptance criteria 170 Implementation 170 More examples 172 Chain of responsibility of commands 174 Rounding Command pattern up 175 Summary 176
Page
7
[ vi ] Chapter 6: Behavioral Patterns - Template, Memento and Interpreter Design Patterns 177 Template method 177 Description of Template method 177 Objective of Template method 178 The example – a simple algorithm with a deferred step 178 Requirements and acceptance criteria 178 Unit tests for the simple algorithm 179 Implementing the Template pattern 180 Anonymous function 182 I can't change the interface! 184 Looking for a Template in Go's source code. 187 A detailed journey about the Template design pattern 188 Memento design pattern 189 Description of Memento 189 Objective of Memento pattern 189 A simple example with strings 189 Requirements and acceptance criteria 190 First test 190 Implementing Memento pattern 194 Another example using Command and Facade patterns 196 Last words on Memento pattern 199 Interpreter design pattern 200 Description 200 Objectives of Interpreter design pattern 200 The example – A polish notation calculator 200 Acceptance criteria for the calculator 201 Unit tests of some operations 201 Implementation of the interpreter 202 Complexity with the interpreter design pattern 206 Interpreter again, now using interfaces: 207 The power of the interpreter pattern 209 Summary 209 Chapter 7: Behavioural patterns - Visitor, State, Mediator and Observer Design Patterns 211 Visitor design pattern 211 Description 211 Objective 212
Page
8
[ vii ] A log appender 212 Acceptance criteria 212 Unit tests 213 Implementation 217 A second example 219 Visitors to the rescue! 223 State 223 Description 224 Objective 224 A small guess the number game 224 Acceptance criteria for our game 224 Implementation 225 A state to win and a state to lose. 229 The game built using the State pattern. 230 Mediator design pattern 230 Description 230 Objective 231 A calculator 231 Acceptance criteria 231 Implementation 232 A crazy example for the mediator 235 Observer pattern 236 Description 236 Objective 236 A notifier 236 Acceptance criteria 237 Unit tests 237 Implementation 242 Summary 244
Page
9
1 Ready... Steady... Go! Design Patterns have been the foundation for hundreds of thousands of pieces of software. Since the Gang Of Four (Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides) wrote the book Design Patterns: Elements of Reusable Object-Oriented Software in 1994 with examples in C++ and Smalltalk, the twenty three classic patterns have been re-implemented in most of major languages of today and they have been used in almost every project you know about. The Gang of Four detected that many small architectures were present in many of their projects, they started to rewrite them in a more abstract way and they released the famous book. This book is a comprehensive explanation and implementation of the most common design patterns from the Gang of Four and today's patterns plus some of the most idiomatic concurrency patterns in Go. But what is Go…? A little bit of history On the last 20 years, we have lived an incredible growth in computer science. Storage spaces have been increased dramatically, RAM memories have suffered a substantial growth, and CPU's are… well… simply faster. Have they grown as much as storage and RAM memory? Not really, CPU industry has reached a limit in the speed that their CPU's can deliver, mainly because they have become so fast that they cannot get enough power to work while they dissipate enough heat. The CPU manufacturers are now shipping more cores on each computer. This situation crashes against the background of many systems programming languages that weren't designed for multi-processor CPUs or large distributed systems that act as a unique machine. In Google, they realized that this was
Page
10
Ready... Steady... Go! [ 2 ] becoming more than an issue while they were struggling to develop distributed applications in languages like Java or C++ that weren't designed with concurrency in mind. At the same time, our programs were bigger, more complex, more difficult to maintain and with lot of room for bad practices. While our computers had more cores and were faster, we were not faster when developing our code neither our distributed applications. This was Go's target. Go design started in 2007 by three Googlers in the research of a programming language that could solve common issues in large scale distributed systems like the ones you can find at Google. The creators were: Rob Pike: Plan 9 and Inferno OS. Robert Griesemer: Worked in Google's V8 JavaScript engine that powers Google Chrome. Ken Thompson: Worked at Bell labs and the Unix team. It has been involved in designing of the Plan 9 operating system as well as the definition of the UTF-8 encoding. In 2008, the compiler was done and the team got the help of Russ Cox and Ian Lance Taylor. The team started their journey to open source the project in 2009 and in March 2012 they reached a version 1.0 after more than fifty releases. Installing Go Any Go Installation needs two basic things: the binaries of the language somewhere in your disk and a GOPATH path in your system where your projects and the projects that you download from other people will be stored. Linux To install Go in Linux you have two options: Easy option: Use your distribution package manager: RHEL/Fedora/Centos users with YUM/DNF: sudo yum install -y golang Ubuntu/Debian users using APT with: sudo apt-get install - y golang
Page
11
Ready... Steady... Go! [ 3 ] Advanced: Downloading the latest distribution from h t t p s ://g o l a n g . o r g I recommend using the second and downloading a distribution. Go's updates maintains backward compatibility and you usually should not be worried about updating soon. Go Linux advanced installation The advanced installation of Go in Linux requires you to download the binaries from Golang webpage. After entering h t t p s ://g o l a n g . o r g , click the Download Go button (usually at the right) some Featured Downloads option is available for each distribution. Select Linux distribution to download the latest stable version. In https://golang.org you can also download beta versions of the language. Let's say we have saved tar.gz file in downloads so lets extract it and move it to a different path: tar -zxvf go*.*.*.linux-amd64.tar.gz sudo mv go /usr/local/go On extraction remember to replace asterisks (*) with the version you have downloaded. Now we have our Go installation in/usr/local/go path so now we have to add the bin subfolder to our PATH by opening the file $HOME/.bashrc and search for a line that looks like export PATH=[something]. So at the end of this file add the bin path to it after a colon (:$HOME/go/bin) path. It should look like the following line: export PATH=/usr/bin[something]:/usr/local/go/bin Save the file and check that our go bin is available: $ go version Go version go1.6.2 linux/amd64 Windows To install Go in Windows, you will need administrator privileges. Open your favorite browser and navigate to h t t p s ://g o l a n g . o r g . Once there click the Download Go button and select Microsoft Windows distribution. A *.msi file will start downloading.
Page
12
Ready... Steady... Go! [ 4 ] Execute the MSI installer by double clicking it. An installer will appear asking you to accept the End User License Agreement (EULA) and select a target folder for your installation. We will continue with the default path that in my case was C:\Go. Once the installation is finished you will have to add the binary Go folder, located in C:\Go\bin to your Path. For this, you must go to Control Panel and select System option. Once in System, select the Advanced tab and click the Environment variables button. Here you'll find a window with variables for your current user and system variables. In system variables, you'll find the Path variable. Click it and click the Edit button to open a text box. You can add your path by adding; C:\Go/bin at the end of the current line (note the semicolon at the beginning of the path). In recent Windows versions (Windows 10) you will have a manager to add variables easily. Mac OS X In Mac OS X the installation process is very similar to Linux. Open your favorite browser and navigate to h t t p s ://g o l a n g . o r g and click the Download Go. From the list of possible distributions that appear, select Apple OS X. This will download a *.pkg file to your download folder. A window will guide you through the installation process where you have to type your administrator password so that it can put Go binary files in /usr/local/go/bin folder with the proper permissions. Now, open Terminal to test the installation by typing this on it: $ go version Go version go1.6.2 darwin/amd64 If you see the installed version, everything was fine. If it doesn't work check that you have followed correctly every step or refer to the documentation in h t t p s ://g o l a n g . o r g webpage. Setting the workspace- Linux and Apple OS X Go will always work under the same workspace. This helps the compiler to find packages and libraries that you could be using: mkdir -p $HOME/go The $HOME/go path is going to be the destination of our $GOPATH. We have to set an environment variable with our $GOPATH pointing to this folder. To set the environment
Page
13
Ready... Steady... Go! [ 5 ] variable, open again the file $HOME/.bashrc with your favorite text editor and add the following line at the end of it: export GOPATH=${HOME}/go Save the file and open a new terminal. To check that everything is working, just write an echo to the $GOPATH variable like this: echo $GOPATH /home/mcastro/go If the output of the preceding command points to your chosen Go path, everything is correct and you can continue to write your first program. Starting with Hello World This wouldn't be a good book without a Hello World example. Our Hello World example can't be simpler, open Sublime Text and create a file called main.go within our $GOPATH/src/[your_name]/hello_world with the following content: package main func main(){ println("Hello World!") } Save the file. To run our program, open the Terminal window in your operating system: In Linux, go to programs and find a program called Terminal. In Windows, hit Windows + R, type cmd without quotes on the new window and hit Enter. In Mac OS X, hit Command + Space to open a spotlight search, type terminal without quotes. The terminal app must be highlighted so hit Enter. Once we are in our terminal, navigate to the folder where we have created our main.go file. This should be under your $GOPATH/src/[your_name]/hello_world and execute it: go run main.go Hello World! That's all. The go run [file] command will compile and execute our application but it won't generate an executable file. If you want just to build it and get an executable file, you must build the app using the following command:
Page
14
Ready... Steady... Go! [ 6 ] go build -o hello_world Nothing happens. But if you search in the current directory (ls command in Linux and Mac OSX; and dir in Windows), you'll find an executable file with the name hello_world. We have given this name to the executable file when we wrote -o hello_world command while building. You can now execute this file: /hello_world Hello World! And our message appeared! In Windows, you just need to type the name of the .exe file to get the same result. The go run [my_main_file.go] command will build and execute the app without intermediate files. The go build -o [filename] command will create an executable file that I can take anywhere and has no dependencies. Integrated Development Environment – IDE An IDE is an acronym for Integrated Development Environment and it's basically a user interface to help developers, code their programs by providing a set of tools to speed up common tasks during development process like compiling, building, or managing dependencies. The IDEs are powerful tools that take some time to master and the purpose of this book is not to explain them (an IDE like Eclipse has its own books). In Go, you have many options but there is just one that is fully oriented to Go development: LiteIDE. It is not the most powerful though. Common IDEs or text editors that have a Go plugin/integration are as following: IntelliJ Idea Sublime Text 2/3 Atom Eclipse But you can also find Go plugins for:
Page
15
Ready... Steady... Go! [ 7 ] Vim Visual Studio and Visual Code The IntelliJ Idea and Atom IDEs, for the time of this writing, has the support for debugging using a plugin called Delve. The IntelliJ Idea is bundled with the official Go plugin. In Atom you'll have to download a plugin called Go-plus and a debugger that you can find searching the word Delve. Types Types give the user the ability to store values in mnemonic names. All programming languages has types related with numbers (to store integers, negative numbers, or floating point for example) with characters (to store a single character) with strings (to store complete words) so on. Go language has the common types found in most programming languages: The bool keyword is for Boolean type which represents a True or False state. Many numeric types being the most common: The int type represents a number from 0 to 4294967295 in 32 bits machines and from 0 to 18446744073709551615 in 64 bits. The byte type represents a number from 0 to 255. The float32 and float64 types are the set of all the set of all IEEE-754 32/-bit floating-point numbers respectively. You also have signed int type like rune which is an alias of int32 type, a number that goes from -2147483648 to 2147483647 and complex64 and complex128 which are the set of all complex numbers with float32/ float64 real and imaginary parts like 2.0i. The string keyword for string type represents an array of characters enclosed in quotes like "golang" or "computer". An array that is a numbered sequence of elements of a single type and a fixed size (more about arrays later in this chapter). A list of numbers or lists of words with a fixed size are considered arrays. The slice type is a segment of an underlying array (more about this later in this chapter). This type is a bit confusing at the beginning because it seems like an array but we will see that actually they are more powerful. The structures that are the objects that are composed of another objects or types. The pointers (more about this later in this chapter)are like directions in the memory of our program (yes, like mailboxes that you don't know what's inside).
Page
16
Ready... Steady... Go! [ 8 ] The functions are interesting (more about this later in this chapter). You can also define functions as variables and pass them to other functions (yes, a function that uses a function, did you like Inception movie?). The interface is incredibly important for the language as they provide many encapsulation and abstraction functionalities that we'll need often. We'll use interfaces extensively during the book and they are presented with greater detail later. The map types are unordered key-value structures. So for a given key, you have an associated value. The channels are the communication primitive in Go for concurrency programs. We'll look on channels with more detail on Chapter 8, Dealing with Go's CSP concurrency. Variables and constants Variables are spaces in computer's memory to store values that can be modified during the execution of the program. Variables and constants have a type like the ones described in preceding text. Although, you don't need to explicitly write the type of them (although you can do it). This property to avoid explicit type declaration is what is called Inferred types. For example: //Explicitly declaring a "string" variable var explicit string = "Hello, I'm a explicitly declared variable" Here we are declaring a variable (with the keyword var) called explicit of string type. At the same time, we are defining the value to Hello World!. //Implicitly declaring a "string". Type inferred inferred := ", I'm an inferred variable " But here we are doing exactly the same thing. We have avoided the var keyword and the string type declaration. Internally, Go's compiler will infer (guess) the type of the variable to a string type. This way you have to write much less code for each variable definition. The following lines use the reflect package to gather information about a variable. We are using it to print the type of (TypeOf in the code) of both variables. fmt.Println("Variable 'explicit' is of type:", reflect.TypeOf(explicit)) fmt.Println("Variable 'inferred' is of type:", reflect.TypeOf(inferred))
Page
17
Ready... Steady... Go! [ 9 ] When we run the program, the result is the following: $ go run main.go Hello, I'm a explicitly declared variable Hello, I'm an inferred variable Variable 'explicit' is of type: string Variable 'inferred' is of type: string As we expected, the compiler has inferred the type of the implicit variable to string too. Both have written the expected output to the console. Operators The operators are used to perform arithmetic operations and make comparisons between many things. The following operators are reserved by Go language. Most commonly used operators are the arithmetic operators and comparators. Arithmetic operators are as following: The + operator for sums The - operator for subtractions The * operator for multiplications The / operator for divisions The % operator for division remainders The ++ operator to add 1 to the current variable The -- operator to subtract 1 to the current variable On the other side, comparators are used to check the differences between two statements: The == operator to check if two values are equal The != operator to check if two values are different The > operator to check if left value is higher than right value
Page
18
Ready... Steady... Go! [ 10 ] The < operator to check if left value is lower than right value The >= operator to check if left value is higher or equal to right value The <= operator to check if left value is lower or equal to right value The &&operator to check if two values are true You also have the shifters to perform a binary shift to left or right of a value, negated operator to invert some value. We´ll use them during the chapters so don´t worry too much about them now just keep in mind that you cannot name anything in your code like this operators. What's the inverted value of 10? And -10? Incorrect?. 10 in binary code is 1010 so if we invert every number we will have 0101 or 101 which is the number 5. Flow control Flow control is referred as the ability to decide which portion of code or how many times you execute some code on a condition. In Go, it is implemented using familiar imperative clauses like if, else, switch and for. The syntax is easy to grasp. Let´s review major flow control statements in Go. The if/else statement Go language, like most programming languages, has if-else conditional statement for flow control. Syntax is similar to other languages but you don't need to encapsulate the condition between parenthesis: ten := 10 if ten == 20 { println("This shouldn't be printed as 10 isn't equal to 20") } else { println("Ten is not equals to 20"); } Or else if conditions: if "a" == "b" || 10 == 10 || true == false { println("10 is equal to 10") } else if 11 == 11 &&"go" == "go" { println("This isn't print because previous condition was satisfied");
Page
19
Ready... Steady... Go! [ 11 ] } else { println("In case no condition is satisfied, print this") } } Go does not have ternary conditions like condition ? true : false. The switch statement The switch statement is also similar to most imperative languages. You take a variable and check possible values for it: number := 3 switch(number){ case 1: println("Number is 1") case 2: println("Number is 2") case 3: println("Number is 3") } The for, range statement The for loop is also similar than common programming languages but also without parenthesis: for i := 0; i<=10; i++ { println(i) } As you have probably imagined if you have computer science background, we infer an int variable defined as 0 and execute the code between the brackets while the condition (i<=10) is satisfied. Finally for each execution we added 1 to the value of i. This code will print the numbers from 0 to 10. You also have a special syntax to iterate over arrays or slices which is range: for index, value := range my_array { fmt.Printf("Index is %d and value is %d", index, value) }
Page
20
Ready... Steady... Go! [ 12 ] First, the fmt (format) is a very common Go package that we will use extensively to give shape to the message that we will print in the console. Regarding for, you can use the range keyword to retrieve every item in a collection like my_array and assign them in the value temporal variable. It will also give you an index variable to know the position of the value you're retrieving. It's equivalent to write the following: for index := 0, index < len(my_array); index++ { value := my_array[index] fmt.Printf("Index is %d and value is %d", index, value) } The len method is used to know the length of a collection. If you execute this code, you'll see that the result is the same. Functions A function is a small portion of code that surrounds some action you want to perform. They are the main tool for developer to maintain structure, encapsulation and code readability but also allow an experienced programmer to develop proper unit tests against his or her functions. Functions can be very simple or incredibly complex. Usually you'll find that simpler functions are also easier to maintain, test and debug. There is also a very good advice in computer science world that says: A function must do just one thing, but it must do it damn well. What does a function looks like? A function is a piece of code with its own variables and flow that doesn't affect anything outside of the opening and close brackets but global package or program variables. Functions in Go has the following composition:
Comments 0
Loading comments...
Reply to Comment
Edit Comment