提交 454ac1fe 编写于 作者: T Tavee Khunbida

initial thai translation

上级 55e90cb9
# 1 Go Environment Configuration
Welcome to the world of Go, let's start exploring!
Go is a fast-compiled, garbage-collected, concurrent systems programming language. It has the following advantages:
- Compiles a large project within a few seconds.
- Provides a software development model that is easy to reason about, avoiding most of the problems associated with C-style header files.
- Is a static language that does not have levels in its type system, so users do not need to spend much time dealing with relations between types. It is more like a lightweight object-oriented language.
- Performs garbage collection. It provides basic support for concurrency and communication.
- Designed for multi-core computers.
Go is a compiled language. It combines the development efficiency of interpreted or dynamic languages with the security of static languages. It is going to be the language of choice for modern, multi-core computers with networking. For these purposes, there are some problems that need to inherently be resolved at the level of the language of choice, such as a richly expressive lightweight type system, a native concurrency model, and strictly regulated garbage collection. For quite some time, no packages or tools have emerged that have aimed to solve all of these problems in a pragmatic fashion; thus was born the motivation for the Go language.
In this chapter, I will show you how to install and configure your own Go development environment.
## Links
- [Directory](preface.md)
- Next section: [Installation](01.1.md)
# 1.1 Installation
## Three ways to install Go
There are many ways to configure the Go development environment on your computer, and you can choose whichever one you like. The three most common ways are as follows.
- Official installation packages.
- The Go team provides convenient installation packages in Windows, Linux, Mac and other operating systems. This is probably the easiest way to get started. You can get the installers from the [Golang Download Page](https://golang.org/dl/).
- Install it yourself from source code.
- Popular with developers who are familiar with Unix-like systems.
- Using third-party tools.
- There are many third-party tools and package managers for installing Go, like apt-get in Ubuntu and homebrew for Mac.
In case you want to install more than one version of Go on a computer, you should take a look at a tool called [GVM](https://github.com/moovweb/gvm). It is the best tool I've seen so far for accomplishing this task, otherwise you'd have to deal with it yourself.
## Install from source code
To compile Go 1.5 and upwards, you only need the previous version of Go, as Go has achieved bootstrapping. You only need Go to compile Go.
To compile Go 1.4 downwards, you will need a C compiler as some parts of Go are still written in Plan 9 C and AT&T assembler.
On a Mac, if you have installed Xcode, you already have the compiler.
On Unix-like systems, you need to install gcc or a similar compiler. For example, using the package manager apt-get (included with Ubuntu), one can install the required compilers as follows:
```sh
sudo apt-get install gcc libc6-dev
```
On Windows, you need to install MinGW in order to install gcc. Don't forget to configure your environment variables after the installation has completed.( ***Everything that looks like this means it's commented by a translator: If you are using 64-bit Windows, you should install the 64-bit version of MinGW*** )
At this point, execute the following commands to clone the Go source code and compile it.( ***It will clone the source code to your current directory. Switch your work path before you continue. This may take some time.*** )
git clone https://go.googlesource.com/go
cd go/src
./all.bash
A successful installation will end with the message "ALL TESTS PASSED."
On Windows, you can achieve the same by running `all.bat`.
If you are using Windows, the installation package will set your environment variables automatically. In Unix-like systems, you need to set these variables manually as follows. ( ***If your Go version is greater than 1.0, you don't have to set $GOBIN, and it will automatically be related to your $GOROOT/bin, which we will talk about in the next section***)
export GOROOT=$HOME/go
export GOBIN=$GOROOT/bin
export PATH=$PATH:$GOROOT/bin
If you see the following information on your screen, you're all set.
![](images/1.1.mac.png?raw=true)
Figure 1.1 Information after installing from source code
Once you see the usage information of Go, it means you have successfully installed Go on your computer. If it says "no such command", check that your $PATH environment variable contains the installation path of Go.
## Using the standard installation packages
Go has one-click installation packages for every supported operating system. These packages will install Go in `/usr/local/go` (`c:\Go` in Windows) by default. Of course this can be modified, but you also need to change all the environment variables manually as I've shown above.
### How to check if your operating system is 32-bit or 64-bit?
Our next step depends on your operating system type, so we have to check it before we download the standard installation packages.
If you are using Windows, press `Win+R` and then run the command tool. Type the `systeminfo` command and it will show you some useful system information. Find the line that says "system type" -if you see "x64-based PC" that means your operating system is 64-bit, 32-bit otherwise.
I strongly recommend downloading the 64-bit package if you are a Mac user, as Go no longer supports pure 32-bit processors on Mac OSX.
Linux users can type `uname -a` in the terminal to see system information.
A 64-bit operating system will show the following:
<some description> x86_64 x86_64 x86_64 GNU/Linux
// some machines such as Ubuntu 10.04 will show as following
x86_64 GNU/Linux
32-bit operating systems instead show:
<some description> i686 i686 i386 GNU/Linux
### Mac
Go to the [download page](https://golang.org/dl/), choose `go1.4.2.darwin-386.pkg` (The later version has no 32-bit download.)for 32-bit systems and `go1.8.3.darwin-amd64.pkg` for 64-bit systems. Going all the way to the end by clicking "next", `~/go/bin` will be added to your system's $PATH after you finish the installation. Now open the terminal and type `go`. You should see the same output shown in figure 1.1.
### Linux
Go to the [download page](https://golang.org/dl/), choose `go1.8.3.linux-386.tar.gz` for 32-bit systems and `go1.8.3.linux-amd64.tar.gz` for 64-bit systems. Suppose you want to install Go in the `$GO_INSTALL_DIR` path. Uncompress the `tar.gz` to your chosen path using the command `tar zxvf go1.8.3.linux-amd64.tar.gz -C $GO_INSTALL_DIR`. Then set your $PATH with the following: `export PATH=$PATH:$GO_INSTALL_DIR/go/bin`. Now just open the terminal and type `go`. You should now see the same output displayed in figure 1.1.
### Windows
Go to the [download page](https://golang.org/dl/), choose `go1.8.3.windows-386.msi` for 32-bit systems and `go1.8.3.windows-amd64.msi` for 64-bit systems. Going all the way to the end by clicking "next", `c:/go/bin` will be added to `path`. Now just open a command line window and type `go`. You should now see the same output displayed in figure 1.1.
## Use third-party tools
### GVM
GVM is a Go multi-version control tool developed by a third-party, like rvm for ruby. It's quite easy to use. Install gvm by typing the following commands in your terminal:
bash < <(curl -s -S -L https://raw.github.com/moovweb/gvm/master/binscripts/gvm-installer)
Then we install Go using the following commands:
gvm install go1.8.3
gvm use go1.8.3
After the process has finished, you're all set.
### apt-get
Ubuntu is the most popular desktop release version of Linux. It uses `apt-get` to manage packages. We can install Go using the following commands.
sudo add-apt-repository ppa:gophers/go
sudo apt-get update
sudo apt-get install golang-go
### wget
```sh
wget https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz
sudo tar -xzf go1.8.3.linux-amd64.tar.gz -C /usr/local
# Go environment
export GOROOT=/usr/local/go
export GOBIN=$GOROOT/bin
export PATH=$PATH:$GOBIN
export GOPATH=$HOME/gopath
```
Starting from go 1.8, The GOPATH environment variable now has a default value if it is unset. It defaults to `$HOME/go` on Unix and `%USERPROFILE%/go` on Windows.
### Homebrew
Homebrew is a software management tool commonly used in Mac to manage packages. Just type the following commands to install Go.
1. Install Homebrew
```sh
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
2. Install Go
```sh
brew update && brew upgrade
brew install go
```
## Links
- [Directory](preface.md)
- Previous section: [Go environment configuration](01.0.md)
- Next section: [$GOPATH and workspace](01.2.md)
# 1.2 $GOPATH and workspace
## $GOPATH
Go takes a unique approach to manage the code files with the introduction of a `$GOPATH` directory which contains all the go code on the machine. Note that this is different from the `$GOROOT` environment variable which states where go is installed on the machine. We have to define the `$GOPATH` variable before using the language, in *nix systems there is a file called `.profile` we need to append the below export statement to the file. The concept behind gopath is a novel one, where we can link to any go code at any instant of time without ambiguity.
Starting from go 1.8, the GOPATH environment variable now has a default value if it not set: it defaults to `$HOME/go` on Unix and `%USERPROFILE%/go` on Windows.
On Unix-like systems, the variable should be used like this:
export GOPATH=${HOME}/mygo
In Windows, you need to create a new environment variable called GOPATH, then set its value to `c:\mygo`( ***This value depends on where your workspace is located*** )
It's OK to have more than one path (workspace) in `$GOPATH`, but remember that you have to use `:`(`;` in Windows) to separate them. At this point, `go get` will save the content to your first path in `$GOPATH`. It is highly recommended to not have multiples versions, the worst case is to create a folder by the name of your project right inside `$GOPATH`, it breaks everything that the creators were wishing to change in programming with the creation of go language because when you create a folder inside `$GOPATH` you will reference your packages as directly as <packagename>, and this breaks all the applications which will import your package because the `go get` won't find your package. Please follow conventions, there is a reason conventions are created.
In `$GOPATH`, you must have three folders as follows:
- `src` for source files whose suffix is .go, .c, .g, .s.
- `pkg` for compiled files whose suffix is .a.
- `bin` for executable files
In this book, I use `mygo` as my only path in `$GOPATH`.
## Package directory
Create package source files and folders like `$GOPATH/src/mymath/sqrt.go` (`mymath` is the package name) ( ***Author uses `mymath` as his package name, and the same name for the folder that contains the package source files***)
Every time you create a package, you should create a new folder in the `src` directory, with the notable exception of main, for which `main` folder creation is optional. Folder names are usually the same as the package that you are going to use. You can have multi-level directories if you want to. For example, if you create the directory `$GOPATH/src/github.com/astaxie/beedb`, then the package path would be `github.com/astaxie/beedb`. The package name will be the last directory in your path, which is `beedb` in this case.
Execute following commands. ( ***Now author goes back to talk examples*** )
cd $GOPATH/src
mkdir mymath
Create a new file called `sqrt.go`, type the following content to your file.
```Go
// Source code of $GOPATH/src/mymath/sqrt.go
package mymath
func Sqrt(x float64) float64 {
z := 0.0
for i := 0; i < 1000; i++ {
z -= (z*z - x) / (2 * x)
}
return z
}
```
Now my package directory has been created and its code has been written. I recommend that you use the same name for your packages as their corresponding directories, and that the directories contain all of the package source files.
## Compile packages
We've already created our package above, but how do we compile it for practical purposes? There are two ways to do this.
1. Switch your work path to the directory of your package, then execute the `go install` command.
2. Execute the above command except with a file name, like `go install mymath`.
After compiling, we can open the following folder.
cd $GOPATH/pkg/${GOOS}_${GOARCH}
// you can see the file was generated
mymath.a
The file whose suffix is `.a` is the binary file of our package. How do we use it?
Obviously, we need to create a new application to use it.
Create a new application package called `mathapp`.
cd $GOPATH/src
mkdir mathapp
cd mathapp
vim main.go
Write the following content to main.go.
```Go
//$GOPATH/src/mathapp/main.go source code.
package main
import (
"mymath"
"fmt"
)
func main() {
fmt.Printf("Hello, world. Sqrt(2) = %v\n", mymath.Sqrt(2))
}
```
To compile this application, you need to switch to the application directory, which in this case is `$GOPATH/src/mathapp`, then execute the `go install` command. Now you should see an executable file called `mathapp` was generated in the directory `$GOPATH/bin/`. To run this program, use the `./mathapp` command. You should see the following content in your terminal.
Hello world. Sqrt(2) = 1.414213562373095
## Install remote packages
Go has a tool for installing remote packages, which is a command called `go get`. It supports most open source communities, including Github, Google Code, BitBucket, and Launchpad.
go get github.com/astaxie/beedb
You can use `go get -u …` to update your remote packages and it will automatically install all the dependent packages as well.
This tool will use different version control tools for different open source platforms. For example, `git` for Github and `hg` for Google Code. Therefore, you have to install these version control tools before you use `go get`.
After executing the above commands, the directory structure should look like following.
$GOPATH
src
|-github.com
|-astaxie
|-beedb
pkg
|--${GOOS}_${GOARCH}
|-github.com
|-astaxie
|-beedb.a
Actually, `go get` clones source code to the `$GOPATH/src` of the local file system, then executes `go install`.
You can use remote packages in the same way that we use local packages.
```Go
import "github.com/astaxie/beedb"
```
## Directory complete structure
If you've followed all of the above steps, your directory structure should now look like the following.
bin/
mathapp
pkg/
${GOOS}_${GOARCH}, such as darwin_amd64, linux_amd64
mymath.a
github.com/
astaxie/
beedb.a
src/
mathapp
main.go
mymath/
sqrt.go
github.com/
astaxie/
beedb/
beedb.go
util.go
Now you are able to see the directory structure clearly: `bin` contains executable files, `pkg` contains compiled files and `src` contains package source files.
(The format of environment variables in Windows is `%GOPATH%`, however this book mainly follows the Unix-style, so Windows users need to replace these yourself.)
## Links
- [Directory](preface.md)
- Previous section: [Installation](01.1.md)
- Next section: [Go commands](01.3.md)
# 1.3 Go commands
## Go commands
The Go language comes with a complete set of command operation tools. You can execute the `go` command on the terminal to see them:
![](images/1.3.go.png?raw=true)
Figure 1.3 Go command displays detailed information
These are all useful for us. Let's see how to use some of them.
## go build
This command is for compiling tests. It will compile packages and dependencies if it's necessary.
- If the package is not the `main` package such as `mymath` in section 1.2, nothing will be generated after you execute `go build`. If you need the package file `.a` in `$GOPATH/pkg`, use `go install` instead.
- If the package is the `main` package, it will generate an executable file in the same folder. If you want the file to be generated in `$GOPATH/bin`, use `go install` or `go build -o ${PATH_HERE}/a.exe.`
- If there are many files in the folder, but you just want to compile one of them, you should append the file name after `go build`. For example, `go build a.go`. `go build` will compile all the files in the folder.
- You can also assign the name of the file that will be generated. For instance, in the `mathapp` project (in section 1.2), using `go build -o astaxie.exe` will generate `astaxie.exe` instead of `mathapp.exe`. The default name is your folder name (non-main package) or the first source file name (main package).
(According to [The Go Programming Language Specification](https://golang.org/ref/spec), package names should be the name after the word `package` in the first line of your source files. It doesn't have to be the same as the folder name, and the executable file name will be your folder name by default.)
- `go build` ignores files whose names start with `_` or `.`.
- If you want to have different source files for every operating system, you can name files with the system name as a suffix. Suppose there are some source files for loading arrays. They could be named as follows:
array_linux.go | array_darwin.go | array_windows.go | array_freebsd.go
`go build` chooses the one that's associated with your operating system. For example, it only compiles array_linux.go in Linux systems, and ignores all the others.
## go clean
This command is for cleaning files that are generated by compilers, including the following files:
_obj/ // old directory of object, left by Makefiles
_test/ // old directory of test, left by Makefiles
_testmain.go // old directory of gotest, left by Makefiles
test.out // old directory of test, left by Makefiles
build.out // old directory of test, left by Makefiles
*.[568ao] // object files, left by Makefiles
DIR(.exe) // generated by go build
DIR.test(.exe) // generated by go test -c
MAINFILE(.exe) // generated by go build MAINFILE.go
I usually use this command to clean up my files before I upload my project to Github. These are useful for local tests, but useless for version control.
## go fmt and gofmt
The people who are working with C/C++ should know that people are always arguing about which code style is better: K&R-style or ANSI-style. However in Go, there is only one code style which is enforced. For example, left braces must only be inserted at the end of lines, and they cannot be on their own lines, otherwise you will get compile errors! Fortunately, you don't have to remember these rules. `go fmt` does this job for you. Just execute the command `go fmt <File name>.go` in terminal. I don't use this command very much because IDEs usually execute this command automatically when you save source files. I will talk more about IDEs in the next section.
`go fmt` is just an alias, which runs the command 'gofmt -l -w' on the packages named by the import paths.
We usually use `gofmt -w` instead of `go fmt`. The latter will not rewrite your source files after formatting code. `gofmt -w src` formats the whole project.
## go get
This command is for getting remote packages. So far, it supports BitBucket, Github, Google Code and Launchpad. There are actually two things that happen after we execute this command. The first thing is that Go downloads the source code, then executes `go install`. Before you use this command, make sure you have installed all of the related tools.
BitBucket (Mercurial Git)
Github (git)
Google Code (Git, Mercurial, Subversion)
Launchpad (Bazaar)
In order to use this command, you have to install these tools correctly. Don't forget to update the `$PATH` variable. By the way, it also supports customized domain names. Use `go help importpath` for more details about this.
## go install
This command compiles all packages and generates files, then moves them to `$GOPATH/pkg` or `$GOPATH/bin`.
## go test
This command loads all files whose name include `*_test.go` and generates test files, then prints information that looks like the following.
ok archive/tar 0.011s
FAIL archive/zip 0.022s
ok compress/gzip 0.033s
...
It tests all your test files by default. Use command `go help testflag` for more details.
## godoc
Many people say that we don't need any third-party documentation for programming in Go (actually I've made a [CHM](https://github.com/astaxie/godoc) already). Go has a powerful tool to manage documentation natively.
So how do we look up package information in documentation? For instance, if you want to get more details about the `builtin` package, use the `godoc builtin` command. Similarly, use the `godoc net/http` command to look up the `http` package documentation. If you want to see more details about specific functions, use the `godoc fmt Printf` and `godoc -src fmt Printf` commands to view the source code.
Execute the `godoc -http=:8080` command, then open `127.0.0.1:8080` in your browser. You should see a localized golang.org. It can not only show the standard packages' information, but also packages in your `$GOPATH/pkg`. It's great for people who are suffering from the Great Firewall of China.
## Other commands
Go provides more commands than those we've just talked about.
go fix // upgrade code from an old version before go1 to a new version after go1
go version // get information about your version of Go
go env // view environment variables about Go
go list // list all installed packages
go run // compile temporary files and run the application
There are also more details about the commands that I've talked about. You can use `go help <command>` to look them up.
## Links
- [Directory](preface.md)
- Previous section: [$GOPATH and workspace](01.2.md)
- Next section: [Go development tools](01.4.md)
# Go development tools
In this section, I'm going to show you a few IDEs that can help you become a more efficient programmer, with capabilities such as intelligent code completion and auto-formatting. They are all cross-platform, so the steps I will be showing you should not be very different, even if you are not using the same operating system.
## LiteIDE
LiteIDE is an open source, lightweight IDE for developing Go projects only, developed by visualfc.
![](images/1.4.liteide.png?raw=true)
Figure 1.4 Main panel of LiteIDE
LiteIDE features.
- Cross-platform
- Windows
- Linux
- Mac OS
- Cross-compile
- Manage multiple compile environments
- Supports cross-compilation of Go
- Project management standard
- Documentation view based on $GOPATH
- Compilation system based on $GOPATH
- API documentation index based on $GOPATH
- Go source code editor
- Code outlining
- Full support of gocode
- Go documentation view and API index
- View code expression using `F1`
- Function declaration jump using `F2`
- Gdb support
- Auto-format with `gofmt`
- Others
- Multi-language
- Plugin system
- Text editor themes
- Syntax support based on Kate
- intelligent completion based on full-text
- Customized shortcuts
- Markdown support
- Real-time preview
- Customized CSS
- Export HTML and PDF
- Convert and merge to HTML and PDF
### LiteIDE installation
- Install LiteIDE
- [Download page](https://sourceforge.net/projects/liteide/files/)
- [Source code](https://github.com/visualfc/liteide)
You need to install Go first, then download the version appropriate for your operating system. Decompress the package to directly use it.
- Install gocode
You have to install gocode in order to use intelligent completion
go get -u github.com/nsf/gocode
- Compilation environment
Switch configuration in LiteIDE to suit your operating system.
In Windows and using the 64-bit version of Go, you should choose win64 as the configuration environment in the tool bar. Then, choose `Options`, find `LiteEnv` in the left list and open file `win64.env` in the right list.
GOROOT=c:\go
GOBIN=
GOARCH=amd64
GOOS=windows
CGO_ENABLED=1
PATH=%GOBIN%;%GOROOT%\bin;%PATH%
。。。
Replace `GOROOT=c:\go` to your Go installation path, save it. If you have MinGW64, add `c:\MinGW64\bin` to your path environment variable for `cgo` support.
In Linux and using the 64-bit version of Go, you should choose linux64 as the configuration environment in the tool bar. Then, choose `Options`, find `LiteEnv` in the left list and open the `linux64.env` file in the right list.
GOROOT=$HOME/go
GOBIN=
GOARCH=amd64
GOOS=linux
CGO_ENABLED=1
PATH=$GOBIN:$GOROOT/bin:$PATH
。。。
Replace `GOROOT=$HOME/go` to your Go installation path, save it.
- $GOPATH
$GOPATH is the path that contains a list of projects. Open the command tool (or press ``Ctrl+` ``in LiteIDE), then type `go help gopath` for more details.
It's very easy to view and change $GOPATH in LiteIDE. Follow `View - Setup GOPATH` to view and change these values.
## Sublime Text
Here I'm going to introduce you the Sublime Text 3 (Sublime for short) + GoSublime + gocode. Let me explain why.
- Intelligent completion
![](images/1.4.sublime1.png?raw=true)
Figure 1.5 Sublime intelligent completion
- Auto-format source files
- Project management
![](images/1.4.sublime2.png?raw=true)
Figure 1.6 Sublime project management
- Syntax highlight
- Free trial forever with no functional limitations. You may be prompted once in a while to remind you to purchase a license, but you can simply ignore it if you wish. Of course, if you do find that it enhances your productivity and you really enjoy using it, please purchase a copy of it and support its continued development!
First, download the version of [Sublime](http://www.sublimetext.com/) suitable for your operating system.
1. Press ``Ctrl+` ``, open the command tool and input the following commands.
Applicable to Sublime Text 3:
```Go
import urllib.request,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();urllib.request.install_opener(urllib.request.build_opener(urllib.request.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib.request.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read())
```
Applicable to Sublime Text 2:
```Go
import urllib2,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();os.makedirs(ipp)ifnotos.path.exists(ipp)elseNone;urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read());print('Please restart Sublime Text to finish installation')
```
Restart Sublime Text when the installation has finished. You should then find a `Package Control` option in the "Preferences" menu.
![](images/1.4.sublime3.png?raw=true)
Figure 1.7 Sublime Package Control
2. To install GoSublime, SidebarEnhancements and Go Build, press `Ctrl+Shift+p` to open Package Control, then type `pcip` (short for "Package Control: Install Package").
![](images/1.4.sublime4.png?raw=true)
Figure 1.8 Sublime Install Packages
Now type in "GoSublime", press OK to install the package, and repeat the same steps for installing SidebarEnhancements and Go Build. Once again, restart the editor when it completes the installation.
3. To verify that the installation is successful, open Sublime, then open the `main.go` file to see if it has the proper syntax highlighting. Type `import` to see if code completion prompts appear. After typing `import "fmt"`, type `fmt.` anywhere after the `import` declaration to see whether or not intelligent code completion for functions was successfully enabled.
If everything is fine, you're all set.
If not, check your $PATH again. Open a terminal, type `gocode`. If it does not run, your $PATH was not configured correctly.
## Vim
Vim is a popular text editor for programmers, which evolved from its slimmer predecessor, Vi. It has functions for intelligent completion, compilation and jumping to errors.
vim-go is vim above an open-source go language using the most extensive development environment plug-ins
The plugin address:[github.com/fatih/vim-go](https://github.com/fatih/vim-go)
Vim plugin management are the mainstream [Pathogen](https://github.com/tpope/vim-pathogen) and [Vundle](https://github.com/VundleVim/Vundle.vim)
,But the aspects thereof are different.
Pathogen is to solve each plug-in after the installation of files scattered to multiple directories and poor management of the existence. Vundle is to solve the automatic search and download plug-ins exist.
These two plug-ins can be used simultaneously.
1.Install Vundle
```sh
mkdir ~/.vim/bundle
git clone https://github.com/gmarik/Vundle.vim.git ~/.vim/bundle/Vundle.vim
```
Edit .vimrc,Vundle the relevant configuration will be placed in the beginning([Refer to the Vundle documentation for details](https://github.com/VundleVim/Vundle.vim))
```sh
set nocompatible " be iMproved, required
filetype off " required
" set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin()
" let Vundle manage Vundle, required
Plugin 'gmarik/Vundle.vim'
" All of your Plugins must be added before the following line
call vundle#end() " required
filetype plugin indent on " required
```
2.Install Vim-go
Edit ~/.vimrc,Add a line between vundle #begin and vundle #end:
```sh
Plugin 'fatih/vim-go'
```
Executed within Vim: PluginInstall
3.Install YCM(Your Complete Me) to AutoComplete
Add a line to ~ / .vimrc:
```sh
Plugin 'Valloric/YouCompleteMe'
```
Executed within Vim: PluginInstall
![](images/1.4.vim.png?raw=true)
Figure 1.8 Vim intelligent completion for Go
1. Syntax highlighting for Go
cp -r $GOROOT/misc/vim/* ~/.vim/
2. Enabling syntax highlighting
filetype plugin indent on
syntax on
3. Install [gocode](https://github.com/nsf/gocode/)
go get -u github.com/nsf/gocode
gocode will be installed in `$GOBIN` as default
4. Configure [gocode](https://github.com/nsf/gocode/)
~ cd $GOPATH/src/github.com/nsf/gocode/vim
~ ./update.sh
~ gocode set propose-builtins true
propose-builtins true
~ gocode set lib-path "/home/border/gocode/pkg/linux_amd64"
lib-path "/home/border/gocode/pkg/linux_amd64"
~ gocode set
propose-builtins true
lib-path "/home/border/gocode/pkg/linux_amd64"
Explanation of gocode configuration:
propose-builtins: specifies whether or not to open intelligent completion; false by default.
lib-path: gocode only searches for packages in `$GOPATH/pkg/$GOOS_$GOARCH` and `$GOROOT/pkg/$GOOS_$GOARCH`. This setting can be used to add additional paths.
5. Congratulations! Try `:e main.go` to experience the world of Go!
## Emacs
Emacs is the so-called Weapon of God. She is not only an editor, but also a powerful IDE.
![](images/1.4.emacs.png?raw=true)
Figure 1.10 Emacs main panel of Go editor
1. Syntax highlighting
cp $GOROOT/misc/emacs/* ~/.emacs.d/
2. Install [gocode](https://github.com/nsf/gocode/)
go get -u github.com/nsf/gocode
gocode will be installed in `$GOBIN` as default
3. Configure [gocode](https://github.com/nsf/gocode/)
~ cd $GOPATH/src/github.com/nsf/gocode/vim
~ ./update.bash
~ gocode set propose-builtins true
propose-builtins true
~ gocode set lib-path "/home/border/gocode/pkg/linux_amd64"
lib-path "/home/border/gocode/pkg/linux_amd64"
~ gocode set
propose-builtins true
lib-path "/home/border/gocode/pkg/linux_amd64"
4. Install [Auto Completion](http://www.emacswiki.org/emacs/AutoComplete)
Download and uncompress
~ make install DIR=$HOME/.emacs.d/auto-complete
Configure ~/.emacs file
;;auto-complete
(require 'auto-complete-config)
(add-to-list 'ac-dictionary-directories "~/.emacs.d/auto-complete/ac-dict")
(ac-config-default)
(local-set-key (kbd "M-/") 'semantic-complete-analyze-inline)
(local-set-key "." 'semantic-complete-self-insert)
(local-set-key ">" 'semantic-complete-self-insert)
Follow this [link](http://www.emacswiki.org/emacs/AutoComplete) for more details.
5. Configure .emacs
;; golang mode
(require 'go-mode-load)
(require 'go-autocomplete)
;; speedbar
;; (speedbar 1)
(speedbar-add-supported-extension ".go")
(add-hook
'go-mode-hook
'(lambda ()
;; gocode
(auto-complete-mode 1)
(setq ac-sources '(ac-source-go))
;; Imenu & Speedbar
(setq imenu-generic-expression
'(("type" "^type *\\([^ \t\n\r\f]*\\)" 1)
("func" "^func *\\(.*\\) {" 1)))
(imenu-add-to-menubar "Index")
;; Outline mode
(make-local-variable 'outline-regexp)
(setq outline-regexp "//\\.\\|//[^\r\n\f][^\r\n\f]\\|pack\\|func\\|impo\\|cons\\|var.\\|type\\|\t\t*....")
(outline-minor-mode 1)
(local-set-key "\M-a" 'outline-previous-visible-heading)
(local-set-key "\M-e" 'outline-next-visible-heading)
;; Menu bar
(require 'easymenu)
(defconst go-hooked-menu
'("Go tools"
["Go run buffer" go t]
["Go reformat buffer" go-fmt-buffer t]
["Go check buffer" go-fix-buffer t]))
(easy-menu-define
go-added-menu
(current-local-map)
"Go tools"
go-hooked-menu)
;; Other
(setq show-trailing-whitespace t)
))
;; helper function
(defun go ()
"run current buffer"
(interactive)
(compile (concat "go run " (buffer-file-name))))
;; helper function
(defun go-fmt-buffer ()
"run gofmt on current buffer"
(interactive)
(if buffer-read-only
(progn
(ding)
(message "Buffer is read only"))
(let ((p (line-number-at-pos))
(filename (buffer-file-name))
(old-max-mini-window-height max-mini-window-height))
(show-all)
(if (get-buffer "*Go Reformat Errors*")
(progn
(delete-windows-on "*Go Reformat Errors*")
(kill-buffer "*Go Reformat Errors*")))
(setq max-mini-window-height 1)
(if (= 0 (shell-command-on-region (point-min) (point-max) "gofmt" "*Go Reformat Output*" nil "*Go Reformat Errors*" t))
(progn
(erase-buffer)
(insert-buffer-substring "*Go Reformat Output*")
(goto-char (point-min))
(forward-line (1- p)))
(with-current-buffer "*Go Reformat Errors*"
(progn
(goto-char (point-min))
(while (re-search-forward "<standard input>" nil t)
(replace-match filename))
(goto-char (point-min))
(compilation-mode))))
(setq max-mini-window-height old-max-mini-window-height)
(delete-windows-on "*Go Reformat Output*")
(kill-buffer "*Go Reformat Output*"))))
;; helper function
(defun go-fix-buffer ()
"run gofix on current buffer"
(interactive)
(show-all)
(shell-command-on-region (point-min) (point-max) "go tool fix -diff"))
6. Congratulations, you're done! Speedbar is closed by default -remove the comment symbols in the line `;;(speedbar 1)` to enable this feature, or you can use it through `M-x speedbar`.
## Eclipse
Eclipse is also a great development tool. I'll show you how to use it to write Go programs.
![](images/1.4.eclipse1.png?raw=true)
Figure 1.1 Eclipse main panel for editing Go
1. Download and install [Eclipse](http://www.eclipse.org/)
2. Download [goclipse](https://code.google.com/p/goclipse/)
[http://code.google.com/p/goclipse/wiki/InstallationInstructions](http://code.google.com/p/goclipse/wiki/InstallationInstructions)
3. Download gocode
gocode in Github.
https://github.com/nsf/gocode
You need to install git in Windows, usually we use [msysgit](https://code.google.com/p/msysgit/)
Install gocode in the command tool
go get -u github.com/nsf/gocode
You can install from source code if you like.
4. Download and install [MinGW](http://sourceforge.net/projects/mingw/files/MinGW/)
5. Configure plugins.
Windows->Preferences->Go
(1).Configure Go compiler
![](images/1.4.eclipse2.png?raw=true)
Figure 1.12 Go Setting in Eclipse
(2).Configure gocode(optional), set gocode path to where the gocode.exe is.
![](images/1.4.eclipse3.png?raw=true)
Figure 1.13 gocode Setting
(3).Configure gdb(optional), set gdb path to where the gdb.exe is.
![](images/1.4.eclipse4.png?raw=true)
Figure 1.14 gdb Setting
6. Check the installation
Create a new Go project and hello.go file as following.
![](images/1.4.eclipse5.png?raw=true)
Figure 1.15 Create a new project and file
Test installation as follows.(you need to type command in console in Eclipse)
![](images/1.4.eclipse6.png?raw=true)
Figure 1.16 Test Go program in Eclipse
## IntelliJ IDEA
People who have worked with Java should be familiar with this IDE. It supports Go syntax highlighting and intelligent code completion, implemented by a plugin.
1. Download IDEA, there is no difference between the Ultimate and Community editions
![](images/1.4.idea1.png?raw=true)
2. Install the Go plugin. Choose `File - Setting - Plugins`, then click `Browser repo`.
![](images/1.4.idea3.png?raw=true)
3. Search `golang`, double click `download and install` and wait for the download to complete.
![](images/1.4.idea4.png?raw=true)
Click `Apply`, then restart.
4. Now you can create a Go project.
![](images/1.4.idea5.png?raw=true)
Input the position of your Go sdk in the next step -basically it's your $GOROOT.
( ***See a [blog post](http://wuwen.org/tips-about-using-intellij-idea-and-go/) for setup and use IntelliJ IDEA with Go step by step *** )
## Visual Studio VSCode
This is an awesome text editor released as open source cross platform by Microsoft which takes the development experience to a whole new level, https://code.visualstudio.com/. It has everything a modern text editor is expected to have and despite being based on the same backend that atom.io is based, it is very fast.
It works with Windows, Mac, Linux. It has go package built, it provides code linting.
## Atom
Atom is an awesome text editor released as open source cross platform, built on Electron , and based on everything we love about our favorite editors. We designed it to be deeply customizable, but still approachable using the default configuration.
Download: https://atom.io/
## GoLand
GoLand is the codename for a new commercial IDE by JetBrains aimed at providing an ergonomic environment for Go development.
The official version is not yet released。
Download: https://www.jetbrains.com/go/
## Links
- [Directory](preface.md)
- Previous section: [Go commands](01.3.md)
- Next section: [Summary](01.5.md)
# 1.5 Summary
In this chapter, we talked about how to install Go using three different methods including from source code, the standard package and via third-party tools. Then we showed you how to configure the Go development environment, mainly covering how to setup your `$GOPATH`. After that, we introduced some steps for compiling and deploying Go programs. We then covered Go commands, including the compile, install, format and test commands. Finally, there are many powerful tools to develop Go programs such as LiteIDE, Sublime Text, VSCode, Atom, Goglang, Vim, Emacs, Eclipse, IntelliJ IDEA, etc. You can choose any one you like exploring the world of Go.
## Links
- [Directory](preface.md)
- Previous section: [Go development tools](01.4.md)
- Next chapter: [Go basic knowledge](02.0.md)
# 2 Go basic knowledge
Go is a compiled system programming language, and it belongs to the C-family. However, its compilation speed is much faster than other C-family languages. It has only 25 keywords... even less than the 26 letters of the English alphabet! Let's take a look at these keywords before we get started.
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
In this chapter, I'm going to teach you some basic Go knowledge. You will find out how concise the Go programming language is, and the beautiful design of the language. Programming can be very fun in Go. After we complete this chapter, you'll be familiar with the above keywords.
## Links
- [Directory](preface.md)
- Previous chapter: [Chapter 1 Summary](01.5.md)
- Next section: ["Hello, Go"](02.1.md)
## What makes Go different from other languages?
The Go programming language was created with one goal in mind, to be able to build scalable web-applications for large scale audiences in a large team. So that is the reason they made the language as standardized as possible, hence the `gofmt` tool and the strict usage guidelines to the language was for the sake of not having two factions in the developer base, in other languages there are religious wars on where to keep the opening brace?
```java
public static void main() {
}
or
public static void main()
{
}
```
or for python should we use 4 spaces or 6 spaces or a tab or two tabs and other user preferences. If you know python then you might be aware of PEP8, which is a set of guidelines about how to write elegant code.
While this might seem to be a shallow problem, when the codebase grows and more and more people work on the same code base it is becomes increasingly difficult to maintain the code's "beauty." We live in a world where robots can drive a car, so we shouldn't just write code, we should write elegant code.
For other languages there are many variables when it comes to writing code. Every language is good for its use case, but Go is a little special because it was designed at a company which is the very synonym of the Internet (and distributed computing). Typically in order to optimize programs, developers choose to write Java over Python and C++ over Java, but almost all available languages widely in use were written decades ago when 1GB storage was much pricier. Now storage and computing is relatively cheap and computers are getting multiples cores, but the "old languages" are not harnessing concurrency in a way that go does. It's not because those languages are bad; utilizing concurrency wasn't a relevant usecase while the older languages evolved.
To mitigate all the problems that Google faced with current tools, they wrote a systems language called Go which you are about to learn! There are many advantages to using golang and there are disadvantages too, for every coin has both sides. One of the significant improvements is in code formatting. Google has designed the language to avoid debates on code formatting. Go code written by anyone in the world (assuming they know and use `gofmt`) will look exactly the same. This won't seem to matter until you work in a team! Also when the company uses automated code review or some other fancy technique, the formatted code may break in other languages which don't have strict and standard formatting rules, but not in go!
Go was designed with concurrency in mind, please note that parallelism != concurrency, there is an [amazing post](https://blog.golang.org/concurrency-is-not-parallelism) by Rob Pike on the [golang blog](https://blog.golang.org/), you will find it there, it is worth a read.
Another very important change that is the concept of `GOPATH`. Gone are the days when you had to create a folder called `code` and then create workspaces for eclipse and what not. Now you have to keep one folder tree for go code which will be updated by the package manager automatically. It is also recommended to create folders with either a custom domain or the github domain, for example I created a task manager using golang so I created a set of folders
`~/go/src/github.com/thewhitetulip/Tasks`
**Note:** In *nix systems `~` stands for home directory, which is the windows equivalent of `C:\\Users\\username`.
Now the `~/go/` is the universe for the gocode in your machine. This is a significant improvement over other languages; we can store the code efficiently without hassles. While it might seem strange at first, this approach make a lot of sense than the ridiculous package names, i.e. package names generated for other languages using reverse domains.
**Note:** Along with `src` there are two folders `pkg` which is for packages and `bin` which is for binary.
This `GOPATH` advantage isn't just restricted to storing code in particular folder. When you have created five packages for your project, you don't have to import them like `"import ./db"`. Instead you can use `import "github.com/thewhitetulip/Tasks/db"` so that when executing `go get` on my repo, the `go` tool will find the package from `github.com/...` path if it wasn't downloaded initially. This standardizes a lot of screwed up things in the programming discipline. (<-- To remove and replace with actual explanation of why this is better)
While there may be some founded complaints that go creators have ignored all language research done since the past 30yrs, you cannot create a product or a language which everyone will fall in love with. There are always some or the other use cases or constraints which the creators should consider. Considering all the advantages at least for web development I do not think any language gets close to the advantages which `go` has even if you ignore all that I said above. Go is a compiled language which means in production, you won't have to setup a `JVM` or a `virtualenv` and will instead have a single static binary! Like an icing on a cake, all the modern libraries are in the standard library, such as the `http` lib, allowing you to create webapps in golang without using a third party web framework.
# 2.1 Hello, Go
Before we start building an application in Go, we need to learn how to write a simple program. You can't expect to build a building without first knowing how to build its foundation. Therefore, we are going to learn the basic syntax to run some simple programs in this section.
## Program
According to international practice, before you learn how to program in some languages, you will want to know how to write a program to print "Hello world".
Are you ready? Let's Go!
```Go
package main
import "fmt"
func main() {
fmt.Printf("Hello, world or 你好,世界 or Καλημέρα κόσμε or こんにちは世界\n")
}
```
It prints following information.
Hello, world or 你好,世界 or Καλημέρα κόσμε or こんにちは世界
## Explanation
One thing that you should know in the first is that Go programs are composed by `package`.
`package <pkgName>` (In this case is `package main`) tells us this source file belongs to `main` package, and the keyword `main` tells us this package will be compiled to a program instead of package files whose extensions are `.a`.
Every executable program has one and only one `main` package, and you need an entry function called `main` without any arguments or return values in the `main` package.
In order to print `Hello, world…`, we called a function called `Printf`. This function is coming from `fmt` package, so we import this package in the third line of source code, which is `import "fmt"`
The way to think about packages in Go is similar to Python, and there are some advantages: Modularity (break up your program into many modules) and reusability (every module can be reused in many programs). We just talked about concepts regarding packages, and we will make our own packages later.
On the fifth line, we use the keyword `func` to define the `main` function. The body of the function is inside of `{}`, just like C, C++ and Java.
As you can see, there are no arguments. We will learn how to write functions with arguments in just a second, and you can also have functions that have no return value or have several return values.
On the sixth line, we called the function `Printf` which is from the package `fmt`. This was called by the syntax `<pkgName>.<funcName>`, which is very like Python-style.
As we mentioned in chapter 1, the package's name and the name of the folder that contains that package can be different. Here the `<pkgName>` comes from the name in `package <pkgName>`, not the folder's name.
You may notice that the example above contains many non-ASCII characters. The purpose of showing this is to tell you that Go supports UTF-8 by default. You can use any UTF-8 character in your programs.
Each go file is in some package, and that package should be a distinct folder in the GOPATH, but main is a special package which doesn't require a `main` folder. This is one aspect which they left out for standardization! But should you choose to make a main folder then you have to ensure that you run the binary properly. Also one go code can't have more than one `main` go file.
`~/go/src/github.com/thewhitetulip/Tasks/main $ go build`
`~/go/src/github.com/thewhitetulip/Tasks $ ./main/main`
the thing here is that when your code is using some static files or something else, then you ought to run the binary from the root of the application as we see in the second line above, I am running the `main` binary *outside* the main package, sometimes you might wonder why your application isn't working then this might be one of the possible problems, please keep this in mind.
One thing you will notice here is that go doesn't see to use semi colons to end a statement, well, it does, just there is a minor catch, the programmer isn't expected to put semi colons, the compiler adds semi colons to the gocode when it compiles which is the reason that this (thankfully!) is a syntax error
```Go
func main ()
{
}
```
because the compiler adds a semi colon at the end of `main()` which is a syntax error and as stated above, it helps avoid religious wars, i wish they combine `vim` and `emacs` and create a universal editor which'll help save some more wars! But for now we'll learn Go.
## Conclusion
Go uses `package` (like modules in Python) to organize programs. The function `main.main()` (this function must be in the `main` package) is the entry point of any program. Go standardizes language and most of the programming methodology, saving time of developers which they'd have wasted in religious wars. There can be only one main package and only one main function inside a go main package. Go supports UTF-8 characters because one of the creators of Go is a creator of UTF-8, so Go has supported multiple languages from the time it was born.
## Links
- [Directory](preface.md)
- Previous section: [Go basic knowledge](02.0.md)
- Next section: [Go foundation](02.2.md)
# 2.2 Go foundation
In this section, we are going to teach you how to define constants, variables with elementary types and some skills in Go programming.
## Define variables
There are many forms of syntax that can be used to define variables in Go.
The keyword `var` is the basic form to define variables, notice that Go puts the variable type `after` the variable name.
```Go
// define a variable with name “variableName” and type "type"
var variableName type
```
Define multiple variables.
```Go
// define three variables which types are "type"
var vname1, vname2, vname3 type
```
Define a variable with initial value.
```Go
// define a variable with name “variableName”, type "type" and value "value"
var variableName type = value
```
Define multiple variables with initial values.
```Go
/*
Define three variables with type "type", and initialize their values.
vname1 is v1, vname2 is v2, vname3 is v3
*/
var vname1, vname2, vname3 type = v1, v2, v3
```
Do you think that it's too tedious to define variables use the way above? Don't worry, because the Go team has also found
this to be a problem. Therefore if you want to define variables with initial values, we can just omit the variable type,
so the code will look like this instead:
```Go
/*
Define three variables without type "type", and initialize their values.
vname1 is v1,vname2 is v2,vname3 is v3
*/
var vname1, vname2, vname3 = v1, v2, v3
```
Well, I know this is still not simple enough for you. Let's see how we fix it.
```Go
/*
Define three variables without type "type" and without keyword "var", and initialize their values.
vname1 is v1,vname2 is v2,vname3 is v3
*/
vname1, vname2, vname3 := v1, v2, v3
```
Now it looks much better. Use `:=` to replace `var` and `type`, this is called a **short assignment**. It has one limitation: this form can only be used inside of a functions. You will get compile errors if you try to use it outside of function bodies. Therefore, we usually use `var` to define global variables.
`_` (blank) is a special variable name. Any value that is given to it will be ignored. For example, we give `35` to `b`, and discard `34`.( ***This example just show you how it works. It looks useless here because we often use this symbol when we get function return values.*** )
```Go
_, b := 34, 35
```
If you don't use variables that you've defined in your program, the compiler will give you compilation errors. Try to compile the following code and see what happens.
```Go
package main
func main() {
var i int
}
```
## Constants
So-called constants are the values that are determined during compile time and you cannot change them during runtime. In Go, you can use number, boolean or string as types of constants.
Define constants as follows.
```Go
const constantName = value
// you can assign type of constants if it's necessary
const Pi float32 = 3.1415926
```
More examples.
```Go
const Pi = 3.1415926
const i = 10000
const MaxThread = 10
const prefix = "astaxie_"
```
## Elementary types
### Boolean
In Go, we use `bool` to define a variable as boolean type, the value can only be `true` or `false`, and `false` will be the default value. ( ***You cannot convert variables' type between number and boolean!*** )
```Go
// sample code
var isActive bool // global variable
var enabled, disabled = true, false // omit type of variables
func test() {
var available bool // local variable
valid := false // brief statement of variable
available = true // assign value to variable
}
```
### Numerical types
Integer types include both signed and unsigned integer types. Go has `int` and `uint` at the same time, they have same length, but specific length depends on your operating system. They use 32-bit in 32-bit operating systems, and 64-bit in 64-bit operating systems. Go also has types that have specific length including `rune`, `int8`, `int16`, `int32`, `int64`, `byte`, `uint8`, `uint16`, `uint32`, `uint64`. Note that `rune` is alias of `int32` and `byte` is alias of `uint8`.
One important thing you should know that you cannot assign values between these types, this operation will cause compile errors.
```Go
var a int8
var b int32
c := a + b
```
Although int32 has a longer length than int8, and has the same type as int, you cannot assign values between them. ( ***c will be asserted as type `int` here*** )
Float types have the `float32` and `float64` types and no type called `float`. The latter one is the default type if using brief statement.
That's all? No! Go supports complex numbers as well. `complex128` (with a 64-bit real and 64-bit imaginary part) is the default type, if you need a smaller type, there is one called `complex64` (with a 32-bit real and 32-bit imaginary part). Its form is `RE+IMi`, where `RE` is real part and `IM` is imaginary part, the last `i` is the imaginary number. There is a example of complex number.
```Go
var c complex64 = 5+5i
//output: (5+5i)
fmt.Printf("Value is: %v", c)
```
### String
We just talked about how Go uses the UTF-8 character set. Strings are represented by double quotes `""` or backticks ``` `` ```.
```Go
// sample code
var frenchHello string // basic form to define string
var emptyString string = "" // define a string with empty string
func test() {
no, yes, maybe := "no", "yes", "maybe" // brief statement
japaneseHello := "Ohaiou"
frenchHello = "Bonjour" // basic form of assign values
}
```
It's impossible to change string values by index. You will get errors when you compile the following code.
```Go
var s string = "hello"
s[0] = 'c'
```
What if I really want to change just one character in a string? Try the following code.
```Go
s := "hello"
c := []byte(s) // convert string to []byte type
c[0] = 'c'
s2 := string(c) // convert back to string type
fmt.Printf("%s\n", s2)
```
You use the `+` operator to combine two strings.
```Go
s := "hello,"
m := " world"
a := s + m
fmt.Printf("%s\n", a)
```
and also.
```Go
s := "hello"
s = "c" + s[1:] // you cannot change string values by index, but you can get values instead.
fmt.Printf("%s\n", s)
```
What if I want to have a multiple-line string?
```Go
m := `hello
world`
```
``` ` ``` will not escape any characters in a string.
### Error types
Go has one `error` type for purpose of dealing with error messages. There is also a package called `errors` to handle errors.
```Go
err := errors.New("emit macho dwarf: elf header corrupted")
if err != nil {
fmt.Print(err)
}
```
### Underlying data structure
The following picture comes from an article about [Go data structure](http://research.swtch.com/godata) in [Russ Cox's Blog](http://research.swtch.com/). As you can see, Go utilizes blocks of memory to store data.
![](images/2.2.basic.png?raw=true)
Figure 2.1 Go underlying data structure
## Some skills
### Define by group
If you want to define multiple constants, variables or import packages, you can use the group form.
Basic form.
```Go
import "fmt"
import "os"
const i = 100
const pi = 3.1415
const prefix = "Go_"
var i int
var pi float32
var prefix string
```
Group form.
```Go
import(
"fmt"
"os"
)
const(
i = 100
pi = 3.1415
prefix = "Go_"
)
var(
i int
pi float32
prefix string
)
```
Unless you assign the value of constant is `iota`, the first value of constant in the group `const()` will be `0`. If following constants don't assign values explicitly, their values will be the same as the last one. If the value of last constant is `iota`, the values of following constants which are not assigned are `iota` also.
### iota enumerate
Go has one keyword called `iota`, this keyword is to make `enum`, it begins with `0`, increased by `1`.
```Go
const(
x = iota // x == 0
y = iota // y == 1
z = iota // z == 2
w // If there is no expression after the constants name, it uses the last expression,
//so it's saying w = iota implicitly. Therefore w == 3, and y and z both can omit "= iota" as well.
)
const v = iota // once iota meets keyword `const`, it resets to `0`, so v = 0.
const (
e, f, g = iota, iota, iota // e=0,f=0,g=0 values of iota are same in one line.
)
```
### Some rules
The reason that Go is concise because it has some default behaviors.
- Any variable that begins with a capital letter means it will be exported, private otherwise.
- The same rule applies for functions and constants, no `public` or `private` keyword exists in Go.
## array, slice, map
### array
`array` is an array obviously, we define one as follows.
```Go
var arr [n]type
```
in `[n]type`, `n` is the length of the array, `type` is the type of its elements. Like other languages, we use `[]` to get or set element values within arrays.
```Go
var arr [10]int // an array of type [10]int
arr[0] = 42 // array is 0-based
arr[1] = 13 // assign value to element
fmt.Printf("The first element is %d\n", arr[0])
// get element value, it returns 42
fmt.Printf("The last element is %d\n", arr[9])
//it returns default value of 10th element in this array, which is 0 in this case.
```
Because length is a part of the array type, `[3]int` and `[4]int` are different types, so we cannot change the length of arrays. When you use arrays as arguments, functions get their copies instead of references! If you want to use references, you may want to use `slice`. We'll talk about later.
It's possible to use `:=` when you define arrays.
```Go
a := [3]int{1, 2, 3} // define an int array with 3 elements
b := [10]int{1, 2, 3}
// define a int array with 10 elements, of which the first three are assigned.
//The rest of them use the default value 0.
c := [...]int{4, 5, 6} // use `…` to replace the length parameter and Go will calculate it for you.
```
You may want to use arrays as arrays' elements. Let's see how to do this.
```Go
// define a two-dimensional array with 2 elements, and each element has 4 elements.
doubleArray := [2][4]int{[4]int{1, 2, 3, 4}, [4]int{5, 6, 7, 8}}
// The declaration can be written more concisely as follows.
easyArray := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}}
```
Array underlying data structure.
![](images/2.2.array.png?raw=true)
Figure 2.2 Multidimensional array mapping relationship
### slice
In many situations, the array type is not a good choice -for instance when we don't know how long the array will be when we define it. Thus, we need a "dynamic array". This is called `slice` in Go.
`slice` is not really a `dynamic array`. It's a reference type. `slice` points to an underlying `array` whose declaration is similar to `array`, but doesn't need length.
```Go
// just like defining an array, but this time, we exclude the length.
var fslice []int
```
Then we define a `slice`, and initialize its data.
```Go
slice := []byte {'a', 'b', 'c', 'd'}
```
`slice` can redefine existing slices or arrays. `slice` uses `array[i:j]` to slice, where `i` is
the start index and `j` is end index, but notice that `array[j]` will not be sliced since the length
of the slice is `j-i`.
```Go
// define an array with 10 elements whose types are bytes
var ar = [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
// define two slices with type []byte
var a, b []byte
// 'a' points to elements from 3rd to 5th in array ar.
a = ar[2:5]
// now 'a' has elements ar[2],ar[3] and ar[4]
// 'b' is another slice of array ar
b = ar[3:5]
// now 'b' has elements ar[3] and ar[4]
```
Notice the differences between `slice` and `array` when you define them. We use `[…]` to let Go
calculate length but use `[]` to define slice only.
Their underlying data structure.
![](images/2.2.slice.png?raw=true)
Figure 2.3 Correspondence between slice and array
slice has some convenient operations.
- `slice` is 0-based, `ar[:n]` equals to `ar[0:n]`
- The second index will be the length of `slice` if omitted, `ar[n:]` equals to `ar[n:len(ar)]`.
- You can use `ar[:]` to slice whole array, reasons are explained in first two statements.
More examples pertaining to `slice`
```Go
// define an array
var array = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
// define two slices
var aSlice, bSlice []byte
// some convenient operations
aSlice = array[:3] // equals to aSlice = array[0:3] aSlice has elements a,b,c
aSlice = array[5:] // equals to aSlice = array[5:10] aSlice has elements f,g,h,i,j
aSlice = array[:] // equals to aSlice = array[0:10] aSlice has all elements
// slice from slice
aSlice = array[3:7] // aSlice has elements d,e,f,g,len=4,cap=7
bSlice = aSlice[1:3] // bSlice contains aSlice[1], aSlice[2], so it has elements e,f
bSlice = aSlice[:3] // bSlice contains aSlice[0], aSlice[1], aSlice[2], so it has d,e,f
bSlice = aSlice[0:5] // slice could be expanded in range of cap, now bSlice contains d,e,f,g,h
bSlice = aSlice[:] // bSlice has same elements as aSlice does, which are d,e,f,g
```
`slice` is a reference type, so any changes will affect other variables pointing to the same slice or array.
For instance, in the case of `aSlice` and `bSlice` above, if you change the value of an element in `aSlice`,
`bSlice` will be changed as well.
`slice` is like a struct by definition and it contains 3 parts.
- A pointer that points to where `slice` starts.
- The length of `slice`.
- Capacity, the length from start index to end index of `slice`.
```Go
Array_a := [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
Slice_a := Array_a[2:5]
```
The underlying data structure of the code above as follows.
![](images/2.2.slice2.png?raw=true)
Figure 2.4 Array information of slice
There are some built-in functions for slice.
- `len` gets the length of `slice`.
- `cap` gets the maximum length of `slice`
- `append` appends one or more elements to `slice`, and returns `slice` .
- `copy` copies elements from one slice to the other, and returns the number of elements that were copied.
Attention: `append` will change the array that `slice` points to, and affect other slices that point to the same array.
Also, if there is not enough length for the slice (`(cap-len) == 0`), `append` returns a new array for this slice. When
this happens, other slices pointing to the old array will not be affected.
### map
`map` behaves like a dictionary in Python. Use the form `map[keyType]valueType` to define it.
Let's see some code. The 'set' and 'get' values in `map` are similar to `slice`, however the index in `slice` can only be
of type 'int' while `map` can use much more than that: for example `int`, `string`, or whatever you want. Also, they are
all able to use `==` and `!=` to compare values.
```Go
// use string as the key type, int as the value type, and `make` initialize it.
var numbers map[string] int
// another way to define map
numbers := make(map[string]int)
numbers["one"] = 1 // assign value by key
numbers["ten"] = 10
numbers["three"] = 3
fmt.Println("The third number is: ", numbers["three"]) // get values
// It prints: The third number is: 3
```
Some notes when you use map.
- `map` is disorderly. Everytime you print `map` you will get different results. It's impossible to get values by `index` -you have to use `key`.
- `map` doesn't have a fixed length. It's a reference type just like `slice`.
- `len` works for `map` also. It returns how many `key`s that map has.
- It's quite easy to change the value through `map`. Simply use `numbers["one"]=11` to change the value of `key` one to `11`.
You can use form `key:val` to initialize map's values, and `map` has built-in methods to check if the `key` exists.
Use `delete` to delete an element in `map`.
```Go
// Initialize a map
rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
// map has two return values. For the second return value, if the key doesn't
//exist,'ok' returns false. It returns true otherwise.
csharpRating, ok := rating["C#"]
if ok {
fmt.Println("C# is in the map and its rating is ", csharpRating)
} else {
fmt.Println("We have no rating associated with C# in the map")
}
delete(rating, "C") // delete element with key "c"
```
As I said above, `map` is a reference type. If two `map`s point to same underlying data,
any change will affect both of them.
```Go
m := make(map[string]string)
m["Hello"] = "Bonjour"
m1 := m
m1["Hello"] = "Salut" // now the value of m["hello"] is Salut
```
### make, new
`make` does memory allocation for built-in models, such as `map`, `slice`, and `channel`, while `new` is for types'
memory allocation.
`new(T)` allocates zero-value to type `T`'s memory, returns its memory address, which is the value of type `*T`. By Go's
definition, it returns a pointer which points to type `T`'s zero-value.
`new` returns pointers.
The built-in function `make(T, args)` has different purposes than `new(T)`. `make` can be used for `slice`, `map`,
and `channel`, and returns a type `T` with an initial value. The reason for doing this is because the underlying data of
these three types must be initialized before they point to them. For example, a `slice` contains a pointer that points to
the underlying `array`, length and capacity. Before these data are initialized, `slice` is `nil`, so for `slice`, `map`
and `channel`, `make` initializes their underlying data and assigns some suitable values.
`make` returns non-zero values.
The following picture shows how `new` and `make` are different.
![](images/2.2.makenew.png?raw=true)
Figure 2.5 Underlying memory allocation of make and new
Zero-value does not mean empty value. It's the value that variables default to in most cases. Here is a list of some zero-values.
```Go
int 0
int8 0
int32 0
int64 0
uint 0x0
rune 0 // the actual type of rune is int32
byte 0x0 // the actual type of byte is uint8
float32 0 // length is 4 byte
float64 0 //length is 8 byte
bool false
string ""
```
## Links
- [Directory](preface.md)
- Previous section: ["Hello, Go"](02.1.md)
- Next section: [Control statements and functions](02.3.md)
# 2.3 Control statements and functions
In this section, we are going to talk about control statements and function operations in Go.
## Control statement
The greatest invention in programming is flow control. Because of them, you are able to use simple control statements that can be used to represent complex logic. There are three categories of flow control: conditional, cycle control and unconditional jump.
### if
`if` will most likely be the most common keyword in your programs. If it meets the conditions, then it does something and it does something else if not.
`if` doesn't need parentheses in Go.
```Go
if x > 10 {
fmt.Println("x is greater than 10")
} else {
fmt.Println("x is less than or equal to 10")
}
```
The most useful thing concerning `if` in Go is that it can have one initialization statement before the conditional statement. The scope of the variables defined in this initialization statement are only available inside the block of the defining `if`.
```Go
// initialize x, then check if x greater than
if x := computedValue(); x > 10 {
fmt.Println("x is greater than 10")
} else {
fmt.Println("x is less than 10")
}
// the following code will not compile
fmt.Println(x)
```
Use if-else for multiple conditions.
```Go
if integer == 3 {
fmt.Println("The integer is equal to 3")
} else if integer < 3 {
fmt.Println("The integer is less than 3")
} else {
fmt.Println("The integer is greater than 3")
}
```
### goto
Go has a `goto` keyword, but be careful when you use it. `goto` reroutes the control flow to a previously defined `label` within the body of same code block.
```Go
func myFunc() {
i := 0
Here: // label ends with ":"
fmt.Println(i)
i++
goto Here // jump to label "Here"
}
```
The label name is case sensitive.
### for
`for` is the most powerful control logic in Go. It can read data in loops and iterative operations, just like `while`.
```Go
for expression1; expression2; expression3 {
//...
}
```
`expression1`, `expression2` and `expression3` are all expressions, where `expression1` and `expression3` are variable definitions or return values from functions, and `expression2` is a conditional statement. `expression1` will be executed once before looping, and `expression3` will be executed after each loop.
Examples are more useful than words.
```Go
package main
import "fmt"
func main(){
sum := 0;
for index:=0; index < 10 ; index++ {
sum += index
}
fmt.Println("sum is equal to ", sum)
}
// Print:sum is equal to 45
```
Sometimes we need multiple assignments, but Go doesn't have the `,` operator, so we use parallel assignment like `i, j = i + 1, j - 1`.
We can omit `expression1` and `expression3` if they are not necessary.
```Go
sum := 1
for ; sum < 1000; {
sum += sum
}
```
Omit `;` as well. Feel familiar? Yes, it's identical to `while`.
```Go
sum := 1
for sum < 1000 {
sum += sum
}
```
There are two important operations in loops which are `break` and `continue`. `break` jumps out of the loop, and `continue` skips the current loop and starts the next one. If you have nested loops, use `break` along with labels.
```Go
for index := 10; index>0; index-- {
if index == 5{
break // or continue
}
fmt.Println(index)
}
// break prints 10、9、8、7、6
// continue prints 10、9、8、7、6、4、3、2、1
```
`for` can read data from `array`, `slice`, `map` and `string` when it is used together with `range`.
```Go
for k,v := range map {
fmt.Println("map's key:",k)
fmt.Println("map's val:",v)
}
```
Because Go supports multi-value returns and gives compile errors when you don't use values that were defined, you may want to use `_` to discard certain return values.
```Go
for _, v := range map{
fmt.Println("map's val:", v)
}
```
With go you can as well create an infinite loop, which is equivalent to `while true { ... }` in other languges.
```GO
for {
// your logic
}
```
### switch
Sometimes you may find that you are using too many `if-else` statements to implement some logic, which may make it difficult to read and maintain in the future. This is the perfect time to use the `switch` statement to solve this problem.
```Go
switch sExpr {
case expr1:
some instructions
case expr2:
some other instructions
case expr3:
some other instructions
default:
other code
}
```
The type of `sExpr`, `expr1`, `expr2`, and `expr3` must be the same. `switch` is very flexible. Conditions don't have to be constants and it executes from top to bottom until it matches conditions. If there is no statement after the keyword `switch`, then it matches `true`.
```Go
i := 10
switch i {
case 1:
fmt.Println("i is equal to 1")
case 2, 3, 4:
fmt.Println("i is equal to 2, 3 or 4")
case 10:
fmt.Println("i is equal to 10")
default:
fmt.Println("All I know is that i is an integer")
}
```
In the fifth line, we put many values in one `case`, and we don't need to add the `break` keyword at the end of `case`'s body. It will jump out of the switch body once it matched any case. If you want to continue to matching more cases, you need to use the`fallthrough` statement.
```Go
integer := 6
switch integer {
case 4:
fmt.Println("integer <= 4")
fallthrough
case 5:
fmt.Println("integer <= 5")
fallthrough
case 6:
fmt.Println("integer <= 6")
fallthrough
case 7:
fmt.Println("integer <= 7")
fallthrough
case 8:
fmt.Println("integer <= 8")
fallthrough
default:
fmt.Println("default case")
}
```
This program prints the following information.
```Go
integer <= 6
integer <= 7
integer <= 8
default case
```
## Functions
Use the `func` keyword to define a function.
```Go
func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) {
// function body
// multi-value return
return value1, value2
}
```
We can extrapolate the following information from the example above.
- Use keyword `func` to define a function `funcName`.
- Functions have zero, one or more than one arguments. The argument type comes after the argument name and arguments are separated by `,`.
- Functions can return multiple values.
- There are two return values named `output1` and `output2`, you can omit their names and use their type only.
- If there is only one return value and you omitted the name, you don't need brackets for the return values.
- If the function doesn't have return values, you can omit the return parameters altogether.
- If the function has return values, you have to use the `return` statement somewhere in the body of the function.
Let's see one practical example. (calculate maximum value)
```Go
package main
import "fmt"
// return greater value between a and b
func max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
x := 3
y := 4
z := 5
max_xy := max(x, y) // call function max(x, y)
max_xz := max(x, z) // call function max(x, z)
fmt.Printf("max(%d, %d) = %d\n", x, y, max_xy)
fmt.Printf("max(%d, %d) = %d\n", x, z, max_xz)
fmt.Printf("max(%d, %d) = %d\n", y, z, max(y, z)) // call function here
}
```
In the above example, there are two arguments in the function `max`, their types are both `int` so the first type can be omitted. For instance, `a, b int` instead of `a int, b int`. The same rules apply for additional arguments. Notice here that `max` only has one return value, so we only need to write the type of its return value -this is the short form of writing it.
### Multi-value return
One thing that Go is better at than C is that it supports multi-value returns.
We'll use the following example here.
```Go
package main
import "fmt"
// return results of A + B and A * B
func SumAndProduct(A, B int) (int, int) {
return A + B, A * B
}
func main() {
x := 3
y := 4
xPLUSy, xTIMESy := SumAndProduct(x, y)
fmt.Printf("%d + %d = %d\n", x, y, xPLUSy)
fmt.Printf("%d * %d = %d\n", x, y, xTIMESy)
}
```
The above example returns two values without names -you have the option of naming them also. If we named the return values, we would just need to use `return` to return the values since they are initialized in the function automatically. Notice that if your functions are going to be used outside of the package, which means your function names start with a capital letter, you'd better write complete statements for `return`; it makes your code more readable.
```Go
func SumAndProduct(A, B int) (add int, multiplied int) {
add = A+B
multiplied = A*B
return
}
```
### Variadic functions
Go supports functions with a variable number of arguments. These functions are called "variadic", which means the function allows an uncertain numbers of arguments.
```Go
func myfunc(arg ...int) {}
```
`arg …int` tells Go that this is a function that has variable arguments. Notice that these arguments are type `int`. In the body of function, the `arg` becomes a `slice` of `int`.
```Go
for _, n := range arg {
fmt.Printf("And the number is: %d\n", n)
}
```
### Pass by value and pointers
When we pass an argument to the function that was called, that function actually gets the copy of our variables so any change will not affect to the original variable.
Let's see one example in order to prove what i'm saying.
```Go
package main
import "fmt"
// simple function to add 1 to a
func add1(a int) int {
a = a + 1 // we change value of a
return a // return new value of a
}
func main() {
x := 3
fmt.Println("x = ", x) // should print "x = 3"
x1 := add1(x) // call add1(x)
fmt.Println("x+1 = ", x1) // should print "x+1 = 4"
fmt.Println("x = ", x) // should print "x = 3"
}
```
Can you see that? Even though we called `add1` with `x`, the origin value of `x` doesn't change.
The reason is very simple: when we called `add1`, we gave a copy of `x` to it, not the `x` itself.
Now you may ask how I can pass the real `x` to the function.
We need use pointers here. We know variables are stored in memory and they have some memory addresses. So, if we want to change the value of a variable, we must change its memory address. Therefore the function `add1` has to know the memory address of `x` in order to change its value. Here we pass `&x` to the function, and change the argument's type to the pointer type `*int`. Be aware that we pass a copy of the pointer, not copy of value.
```Go
package main
import "fmt"
// simple function to add 1 to a
func add1(a *int) int {
*a = *a + 1 // we changed value of a
return *a // return new value of a
}
func main() {
x := 3
fmt.Println("x = ", x) // should print "x = 3"
x1 := add1(&x) // call add1(&x) pass memory address of x
fmt.Println("x+1 = ", x1) // should print "x+1 = 4"
fmt.Println("x = ", x) // should print "x = 4"
}
```
Now we can change the value of `x` in the functions. Why do we use pointers? What are the advantages?
- Allows us to use more functions to operate on one variable.
- Low cost by passing memory addresses (8 bytes), copy is not an efficient way, both in terms of time and space, to pass variables.
- `channel`, `slice` and `map` are reference types, so they use pointers when passing to functions by default. (Attention: If you need to change the length of `slice`, you have to pass pointers explicitly)
### defer
Go has a well designed keyword called `defer`. You can have many `defer` statements in one function; they will execute in reverse order when the program executes to the end of functions. In the case where the program opens some resource files, these files would have to be closed before the function can return with errors. Let's see some examples.
```Go
func ReadWrite() bool {
file.Open("file")
// Do some work
if failureX {
file.Close()
return false
}
if failureY {
file.Close()
return false
}
file.Close()
return true
}
```
We saw some code being repeated several times. `defer` solves this problem very well. It doesn't only help you to write clean code but also makes your code more readable.
```Go
func ReadWrite() bool {
file.Open("file")
defer file.Close()
if failureX {
return false
}
if failureY {
return false
}
return true
}
```
If there are more than one `defer`s, they will execute by reverse order. The following example will print `4 3 2 1 0`.
```Go
for i := 0; i < 5; i++ {
defer fmt.Printf("%d ", i)
}
```
### Functions as values and types
Functions are also variables in Go, we can use `type` to define them. Functions that have the same signature can be seen as the same type.
```Go
type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...])
```
What's the advantage of this feature? The answer is that it allows us to pass functions as values.
```Go
package main
import "fmt"
type testInt func(int) bool // define a function type of variable
func isOdd(integer int) bool {
return integer%2 != 0
}
func isEven(integer int) bool {
return integer%2 == 0
}
// pass the function `f` as an argument to another function
func filter(slice []int, f testInt) []int {
var result []int
for _, value := range slice {
if f(value) {
result = append(result, value)
}
}
return result
}
var slice = []int{1, 2, 3, 4, 5, 7}
func main() {
odd := filter(slice, isOdd)
even := filter(slice, isEven)
fmt.Println("slice = ", slice)
fmt.Println("Odd elements of slice are: ", odd)
fmt.Println("Even elements of slice are: ", even)
}
```
It's very useful when we use interfaces. As you can see `testInt` is a variable that has a function as type and the returned values and arguments of `filter` are the same as those of `testInt`. Therefore, we can have complex logic in our programs, while maintaining flexibility in our code.
### Panic and Recover
Go doesn't have `try-catch` structure like Java does. Instead of throwing exceptions, Go uses `panic` and `recover` to deal with errors. However, you shouldn't use `panic` very much, although it's powerful.
`Panic` is a built-in function to break the normal flow of programs and get into panic status. When a function `F` calls `panic`, `F` will not continue executing but its `defer` functions will continue to execute. Then `F` goes back to the break point which caused the panic status. The program will not terminate until all of these functions return with panic to the first level of that `goroutine`. `panic` can be produced by calling `panic` in the program, and some errors also cause `panic` like array access out of bounds errors.
`Recover` is a built-in function to recover `goroutine`s from panic status. Calling `recover` in `defer` functions is useful because normal functions will not be executed when the program is in the panic status. It catches `panic` values if the program is in the panic status, and it gets `nil` if the program is not in panic status.
The following example shows how to use `panic`.
```Go
var user = os.Getenv("USER")
func init() {
if user == "" {
panic("no value for $USER")
}
}
```
The following example shows how to check `panic`.
```Go
func throwsPanic(f func()) (b bool) {
defer func() {
if x := recover(); x != nil {
b = true
}
}()
f() // if f causes panic, it will recover
return
}
```
### `main` function and `init` function
Go has two retentions which are called `main` and `init`, where `init` can be used in all packages and `main` can only be used in the `main` package. These two functions are not able to have arguments or return values. Even though we can write many `init` functions in one package, I strongly recommend writing only one `init` function for each package.
Go programs will call `init()` and `main()` automatically, so you don't need to call them by yourself. For every package, the `init` function is optional, but `package main` has one and only one `main` function.
Programs initialize and begin execution from the `main` package. If the `main` package imports other packages, they will be imported in the compile time. If one package is imported many times, it will be only compiled once. After importing packages, programs will initialize the constants and variables within the imported packages, then execute the `init` function if it exists, and so on. After all the other packages are initialized, programs will initialize constants and variables in the `main` package, then execute the `init` function inside the package if it exists. The following figure shows the process.
![](images/2.3.init.png?raw=true)
Figure 2.6 Flow of programs initialization in Go
### import
We use `import` very often in Go programs as follows.
```Go
import(
"fmt"
)
```
Then we use functions in that package as follows.
```Go
fmt.Println("hello world")
```
`fmt` is from Go standard library, it is located within $GOROOT/pkg. Go supports third-party packages in two ways.
1. Relative path
import "./model" // load package in the same directory, I don't recommend this way.
2. Absolute path
import "shorturl/model" // load package in path "$GOPATH/pkg/shorturl/model"
There are some special operators when we import packages, and beginners are always confused by these operators.
1. Dot operator.
Sometime we see people use following way to import packages.
```Go
import(
. "fmt"
)
```
The dot operator means you can omit the package name when you call functions inside of that package. Now `fmt.Printf("Hello world")` becomes to `Printf("Hello world")`.
2. Alias operation.
It changes the name of the package that we imported when we call functions that belong to that package.
```Go
import(
f "fmt"
)
```
Now `fmt.Printf("Hello world")` becomes to `f.Printf("Hello world")`.
3. `_` operator.
This is the operator that is difficult to understand without someone explaining it to you.
```Go
import (
"database/sql"
_ "github.com/ziutek/mymysql/godrv"
)
```
The `_` operator actually means we just want to import that package and execute its `init` function, and we are not sure if we want to use the functions belonging to that package.
## Links
- [Directory](preface.md)
- Previous section: [Go foundation](02.2.md)
- Next section: [struct](02.4.md)
# 2.4 struct
## struct
We can define new types of containers of other properties or fields in Go just like in other programming languages. For example, we can create a type called `person` to represent a person, with fields name and age. We call this kind of type a `struct`.
```Go
type person struct {
name string
age int
}
```
Look how easy it is to define a `struct`!
There are two fields.
- `name` is a `string` used to store a person's name.
- `age` is a `int` used to store a person's age.
Let's see how to use it.
```Go
type person struct {
name string
age int
}
var P person // p is person type
P.name = "Astaxie" // assign "Astaxie" to the field 'name' of p
P.age = 25 // assign 25 to field 'age' of p
fmt.Printf("The person's name is %s\n", P.name) // access field 'name' of p
```
There are three more ways to initialize a struct.
- Assign initial values by order
```Go
P := person{"Tom", 25}
```
- Use the format `field:value` to initialize the struct without order
```Go
P := person{age:24, name:"Bob"}
```
- Define an anonymous struct, then initialize it
```Go
P := struct{name string; age int}{"Amy",18}
```
Let's see a complete example.
```Go
package main
import "fmt"
// define a new type
type person struct {
name string
age int
}
// struct is passed by value
// compare the age of two people, then return the older person and differences of age
func Older(p1, p2 person) (person, int) {
if p1.age > p2.age {
return p1, p1.age - p2.age
}
return p2, p2.age - p1.age
}
func main() {
var tom person
tom.name, tom.age = "Tom", 18
bob := person{age: 25, name: "Bob"}
paul := person{"Paul", 43}
tb_Older, tb_diff := Older(tom, bob)
tp_Older, tp_diff := Older(tom, paul)
bp_Older, bp_diff := Older(bob, paul)
fmt.Printf("Of %s and %s, %s is older by %d years\n", tom.name, bob.name, tb_Older.name, tb_diff)
fmt.Printf("Of %s and %s, %s is older by %d years\n", tom.name, paul.name, tp_Older.name, tp_diff)
fmt.Printf("Of %s and %s, %s is older by %d years\n", bob.name, paul.name, bp_Older.name, bp_diff)
}
```
### embedded fields in struct
I've just introduced to you how to define a struct with field names and type. In fact, Go supports fields without names, but with types. We call these embedded fields.
When the embedded field is a struct, all the fields in that struct will implicitly be the fields in the struct in which it has been embedded.
Let's see one example.
```Go
package main
import "fmt"
type Human struct {
name string
age int
weight int
}
type Student struct {
Human // embedded field, it means Student struct includes all fields that Human has.
specialty string
}
func main() {
// instantiate and initialize a student
mark := Student{Human{"Mark", 25, 120}, "Computer Science"}
// access fields
fmt.Println("His name is ", mark.name)
fmt.Println("His age is ", mark.age)
fmt.Println("His weight is ", mark.weight)
fmt.Println("His specialty is ", mark.specialty)
// modify mark's specialty
mark.specialty = "AI"
fmt.Println("Mark changed his specialty")
fmt.Println("His specialty is ", mark.specialty)
fmt.Println("Mark become old. He is not an athlete anymore")
mark.age = 46
mark.weight += 60
fmt.Println("His age is", mark.age)
fmt.Println("His weight is", mark.weight)
}
```
![](images/2.4.student_struct.png?raw=true)
Figure 2.7 Embedding in Student and Human
We see that we can access the `age` and `name` fields in Student just like we can in Human. This is how embedded fields work. It's very cool, isn't it? Hold on, there's something cooler! You can even use Student to access Human in this embedded field!
```Go
mark.Human = Human{"Marcus", 55, 220}
mark.Human.age -= 1
```
All the types in Go can be used as embedded fields.
```Go
package main
import "fmt"
type Skills []string
type Human struct {
name string
age int
weight int
}
type Student struct {
Human // struct as embedded field
Skills // string slice as embedded field
int // built-in type as embedded field
specialty string
}
func main() {
// initialize Student Jane
jane := Student{Human: Human{"Jane", 35, 100}, specialty: "Biology"}
// access fields
fmt.Println("Her name is ", jane.name)
fmt.Println("Her age is ", jane.age)
fmt.Println("Her weight is ", jane.weight)
fmt.Println("Her specialty is ", jane.specialty)
// modify value of skill field
jane.Skills = []string{"anatomy"}
fmt.Println("Her skills are ", jane.Skills)
fmt.Println("She acquired two new ones ")
jane.Skills = append(jane.Skills, "physics", "golang")
fmt.Println("Her skills now are ", jane.Skills)
// modify embedded field
jane.int = 3
fmt.Println("Her preferred number is ", jane.int)
}
```
In the above example, we can see that all types can be embedded fields and we can use functions to operate on them.
There is one more problem however. If Human has a field called `phone` and Student has a field with same name, what should we do?
Go use a very simple way to solve it. The outer fields get upper access levels, which means when you access `student.phone`, we will get the field called phone in student, not the one in the Human struct. This feature can be simply seen as field `overload`ing.
```Go
package main
import "fmt"
type Human struct {
name string
age int
phone string // Human has phone field
}
type Employee struct {
Human
specialty string
phone string // phone in employee
}
func main() {
Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
fmt.Println("Bob's work phone is:", Bob.phone)
fmt.Println("Bob's personal phone is:", Bob.Human.phone)
}
```
## Links
- [Directory](preface.md)
- Previous section: [Control statements and functions](02.3.md)
- Next section: [Object-oriented](02.5.md)
# Object-oriented
We talked about functions and structs in the last two sections, but did you ever consider using functions as fields of a struct? In this section, I will introduce you to another form of function that has a receiver, which is called a `method`.
## method
Suppose you define a "rectangle" struct and you want to calculate its area. We'd typically use the following code to achieve this goal.
```Go
package main
import "fmt"
type Rectangle struct {
width, height float64
}
func area(r Rectangle) float64 {
return r.width * r.height
}
func main() {
r1 := Rectangle{12, 2}
r2 := Rectangle{9, 4}
fmt.Println("Area of r1 is: ", area(r1))
fmt.Println("Area of r2 is: ", area(r2))
}
```
The above example can calculate a rectangle's area. We use the function called `area`, but it's not a method of the rectangle struct (like class methods in classic object-oriented languages). The function and struct are two independent things as you may notice.
It's not a problem so far. However, if you also have to calculate the area of a circle, square, pentagon, or any other kind of shape, you are going to need to add additional functions with very similar names.
![](images/2.5.rect_func_without_receiver.png?raw=true)
Figure 2.8 Relationship between function and struct
Obviously that's not cool. Also, the area should really be the property of a circle or rectangle.
This is where a `method` comes to play. The `method` is a function affiliated with a type. It has similar syntax as function except, after the `func` keyword has a parameter called the `receiver`, which is the main body of that method.
Using the same example, `Rectangle.Area()` belongs directly to rectangle, instead of as a peripheral function. More specifically, `length`, `width` and `Area()` all belong to rectangle.
As Rob Pike said.
"A method is a function with an implicit first argument, called a receiver."
Syntax of method.
```Go
func (r ReceiverType) funcName(parameters) (results)
```
Let's change our example using `method` instead.
```Go
package main
import (
"fmt"
"math"
)
type Circle struct {
radius float64
}
type Rectangle struct {
width, height float64
}
// method
func (c Circle) Area() float64 {
return c.radius * c.radius * math.Pi
}
// method
func (r Rectangle) Area() float64 {
return r.width * r.height
}
func main() {
c1 := Circle{10}
c2 := Circle{25}
r1 := Rectangle{9, 4}
r2 := Rectangle{12, 2}
fmt.Println("Area of c1 is: ", c1.Area())
fmt.Println("Area of c2 is: ", c2.Area())
fmt.Println("Area of r1 is: ", r1.Area())
fmt.Println("Area of r2 is: ", r2.Area())
}
```
Notes for using methods.
- If the name of methods are the same but they don't share the same receivers, they are not the same.
- Methods are able to access fields within receivers.
- Use `.` to call a method in the struct, the same way fields are called.
![](images/2.5.shapes_func_with_receiver_cp.png?raw=true)
Figure 2.9 Methods are different in different structs
In the example above, the Area() methods belong to both Rectangle and Circle respectively, so the receivers are Rectangle and Circle.
One thing that's worth noting is that the method with a dotted line means the receiver is passed by value, not by reference. The difference between them is that a method can change its receiver's values when the receiver is passed by reference, and it gets a copy of the receiver when the receiver is passed by value.
Can the receiver only be a struct? Of course not. Any type can be the receiver of a method. You may be confused about customized types. Struct is a special kind of customized type -there are more customized types.
Use the following format to define a customized type.
```Go
type typeName typeLiteral
```
Examples of customized types:
```Go
type age int
type money float32
type months map[string]int
m := months {
"January":31,
"February":28,
...
"December":31,
}
```
I hope that you know how to use customized types now. Similar to `typedef` in C, we use `ages` to substitute `int` in the above example.
Let's get back to talking about `method`.
You can use as many methods in custom types as you want.
```Go
package main
import "fmt"
const (
WHITE = iota
BLACK
BLUE
RED
YELLOW
)
type Box struct {
width, height, depth float64
color Color
}
type Color byte
type BoxList []Box //a slice of boxes
// method
func (b Box) Volume() float64 {
return b.width * b.height * b.depth
}
// method with a pointer receiver
func (b *Box) SetColor(c Color) {
b.color = c
}
// method
func (bl BoxList) BiggestsColor() Color {
v := 0.00
k := Color(WHITE)
for _, b := range bl {
if b.Volume() > v {
v = b.Volume()
k = b.color
}
}
return k
}
// method
func (bl BoxList) PaintItBlack() {
for i, _ := range bl {
bl[i].SetColor(BLACK)
}
}
// method
func (c Color) String() string {
strings := []string{"WHITE", "BLACK", "BLUE", "RED", "YELLOW"}
return strings[c]
}
func main() {
boxes := BoxList{
Box{4, 4, 4, RED},
Box{10, 10, 1, YELLOW},
Box{1, 1, 20, BLACK},
Box{10, 10, 1, BLUE},
Box{10, 30, 1, WHITE},
Box{20, 20, 20, YELLOW},
}
fmt.Printf("We have %d boxes in our set\n", len(boxes))
fmt.Println("The volume of the first one is", boxes[0].Volume(), "cm³")
fmt.Println("The color of the last one is", boxes[len(boxes)-1].color.String())
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
// Let's paint them all black
boxes.PaintItBlack()
fmt.Println("The color of the second one is", boxes[1].color.String())
fmt.Println("Obviously, now, the biggest one is", boxes.BiggestsColor().String())
}
```
We define some constants and customized types.
- Use `Color` as alias of `byte`.
- Define a struct `Box` which has fields height, width, length and color.
- Define a struct `BoxList` which has `Box` as its field.
Then we defined some methods for our customized types.
- `Volume()` uses Box as its receiver and returns the volume of Box.
- `SetColor(c Color)` changes Box's color.
- `BiggestsColor()` returns the color which has the biggest volume.
- `PaintItBlack()` sets color for all Box in BoxList to black.
- `String()` use Color as its receiver, returns the string format of color name.
Is it much clearer when we use words to describe our requirements? We often write our requirements before we start coding.
### Use pointer as receiver
Let's take a look at `SetColor` method. Its receiver is a pointer of Box. Yes, you can use `*Box` as a receiver. Why do we use a pointer here? Because we want to change Box's color in this method. Thus, if we don't use a pointer, it will only change the value inside a copy of Box.
If we see that a receiver is the first argument of a method, it's not hard to understand how it works.
You might be asking why we aren't using `(*b).Color=c` instead of `b.Color=c` in the `SetColor()` method. Either one is OK here because Go knows how to interpret the assignment. Do you think Go is more fascinating now?
You may also be asking whether we should use `(&bl[i]).SetColor(BLACK)` in `PaintItBlack` because we pass a pointer to `SetColor`. Again, either one is OK because Go knows how to interpret it!
### Inheritance of method
We learned about inheritance of fields in the last section. Similarly, we also have method inheritance in Go. If an anonymous field has methods, then the struct that contains the field will have all the methods from it as well.
```Go
package main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Student struct {
Human // anonymous field
school string
}
type Employee struct {
Human
company string
}
// define a method in Human
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func main() {
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
sam.SayHi()
mark.SayHi()
}
```
### Method Overriding
If we want Employee to have its own method `SayHi`, we can define a method that has the same name in Employee, and it will hide `SayHi` in Human when we call it.
```Go
package main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Student struct {
Human
school string
}
type Employee struct {
Human
company string
}
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func (e *Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
e.company, e.phone) //Yes you can split into 2 lines here.
}
func main() {
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
sam.SayHi()
mark.SayHi()
}
```
You are able to write an Object-oriented program now, and methods use rule of capital letter to decide whether public or private as well.
## Links
- [Directory](preface.md)
- Previous section: [struct](02.4.md)
- Next section: [interface](02.6.md)
# 2.6 Interface
## Interface
One of the subtlest design features in Go are interfaces. After reading this section, you will likely be impressed by their implementation.
### What is an interface
In short, an interface is a set of methods that we use to define a set of actions.
Like the examples in previous sections, both Student and Employee can `SayHi()`, but they don't do the same thing.
Let's do some more work. We'll add one more method `Sing()` to them, along with the `BorrowMoney()` method to Student and the `SpendSalary()` method to Employee.
Now, Student has three methods called `SayHi()`, `Sing()` and `BorrowMoney()`, and Employee has `SayHi()`, `Sing()` and `SpendSalary()`.
This combination of methods is called an interface and is implemented by both Student and Employee. So, Student and Employee implement the interface: `SayHi()` and `Sing()`. At the same time, Employee doesn't implement the interface: `BorrowMoney()`, and Student doesn't implement the interface: `SpendSalary()`. This is because Employee doesn't have the method `BorrowMoney()` and Student doesn't have the method `SpendSalary()`.
### Type of Interface
An interface defines a set of methods, so if a type implements all the methods we say that it implements the interface.
```Go
type Human struct {
name string
age int
phone string
}
type Student struct {
Human
school string
loan float32
}
type Employee struct {
Human
company string
money float32
}
// define interfaces
type Men interface {
SayHi()
Sing(lyrics string)
Guzzle(beerStein string)
}
type YoungChap interface {
SayHi()
Sing(song string)
BorrowMoney(amount float32)
}
type ElderlyGent interface {
SayHi()
Sing(song string)
SpendSalary(amount float32)
}
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func (h *Human) Sing(lyrics string) {
fmt.Println("La la, la la la, la la la la la...", lyrics)
}
func (h *Human) Guzzle(beerStein string) {
fmt.Println("Guzzle Guzzle Guzzle...", beerStein)
}
// Employee overloads SayHi
func (e *Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
e.company, e.phone) //Yes you can split into 2 lines here.
}
func (s *Student) BorrowMoney(amount float32) {
s.loan += amount // (again and again and...)
}
func (e *Employee) SpendSalary(amount float32) {
e.money -= amount // More vodka please!!! Get me through the day!
}
```
We know that an interface can be implemented by any type, and one type can implement many interfaces simultaneously.
Note that any type implements the empty interface `interface{}` because it doesn't have any methods and all types have zero methods by default.
### Value of interface
So what kind of values can be put in the interface? If we define a variable as a type interface, any type that implements the interface can assigned to this variable.
Like the above example, if we define a variable "m" as interface Men, then any one of Student, Human or Employee can be assigned to "m". So we could have a slice of Men, and any type that implements interface Men can assign to this slice. Be aware however that the slice of interface doesn't have the same behavior as a slice of other types.
```Go
package main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Student struct {
Human
school string
loan float32
}
type Employee struct {
Human
company string
money float32
}
// Interface Men implemented by Human, Student and Employee
type Men interface {
SayHi()
Sing(lyrics string)
}
// method
func (h Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
// method
func (h Human) Sing(lyrics string) {
fmt.Println("La la la la...", lyrics)
}
// method
func (e Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
e.company, e.phone) //Yes you can split into 2 lines here.
}
func main() {
mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
tom := Employee{Human{"Tom", 36, "444-222-XXX"}, "Things Ltd.", 5000}
// define interface i
var i Men
//i can store Student
i = mike
fmt.Println("This is Mike, a Student:")
i.SayHi()
i.Sing("November rain")
//i can store Employee
i = tom
fmt.Println("This is Tom, an Employee:")
i.SayHi()
i.Sing("Born to be wild")
// slice of Men
fmt.Println("Let's use a slice of Men and see what happens")
x := make([]Men, 3)
// these three elements are different types but they all implemented interface Men
x[0], x[1], x[2] = paul, sam, mike
for _, value := range x {
value.SayHi()
}
}
```
An interface is a set of abstract methods, and can be implemented by non-interface types. It cannot therefore implement itself.
### Empty interface
An empty interface is an interface that doesn't contain any methods, so all types implement an empty interface. This fact is very useful when we want to store all types at some point, and is similar to void* in C.
```Go
// define a as empty interface
var void interface{}
// vars
i := 5
s := "Hello world"
// a can store value of any type
void = i
void = s
```
If a function uses an empty interface as its argument type, it can accept any type; if a function uses empty interface as its return value type, it can return any type.
### Method arguments of an interface
Any variable can be used in an interface. So how can we use this feature to pass any type of variable to a function?
For example we use `fmt.Println` a lot, but have you ever noticed that it can accept any type of argument? Looking at the open source code of `fmt`, we see the following definition.
```Go
type Stringer interface {
String() string
}
```
This means any type that implements interface Stringer can be passed to fmt.Println as an argument. Let's prove it.
```Go
package main
import (
"fmt"
"strconv"
)
type Human struct {
name string
age int
phone string
}
// Human implements fmt.Stringer
func (h Human) String() string {
return "Name:" + h.name + ", Age:" + strconv.Itoa(h.age) + " years, Contact:" + h.phone
}
func main() {
Bob := Human{"Bob", 39, "000-7777-XXX"}
fmt.Println("This Human is : ", Bob)
}
```
Looking back to the example of Box, you will find that Color implements interface Stringer as well, so we are able to customize the print format. If we don't implement this interface, fmt.Println prints the type with its default format.
```Go
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
fmt.Println("The biggest one is", boxes.BiggestsColor())
```
Attention: If the type implemented the interface `error`, fmt will call `Error()`, so you don't have to implement Stringer at this point.
### Type of variable in an interface
If a variable is the type that implements an interface, we know that any other type that implements the same interface can be assigned to this variable. The question is how can we know the specific type stored in the interface. There are two ways which I will show you.
- Assertion of Comma-ok pattern
Go has the syntax `value, ok := element.(T)`. This checks to see if the variable is the type that we expect, where "value" is the value of the variable, "ok" is a variable of boolean type, "element" is the interface variable and the T is the type of assertion.
If the element is the type that we expect, ok will be true, false otherwise.
Let's use an example to see more clearly.
```Go
package main
import (
"fmt"
"strconv"
)
type Element interface{}
type List []Element
type Person struct {
name string
age int
}
func (p Person) String() string {
return "(name: " + p.name + " - age: " + strconv.Itoa(p.age) + " years)"
}
func main() {
list := make(List, 3)
list[0] = 1 // an int
list[1] = "Hello" // a string
list[2] = Person{"Dennis", 70}
for index, element := range list {
if value, ok := element.(int); ok {
fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
} else if value, ok := element.(string); ok {
fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
} else if value, ok := element.(Person); ok {
fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)
} else {
fmt.Printf("list[%d] is of a different type\n", index)
}
}
}
```
It's quite easy to use this pattern, but if we have many types to test, we'd better use `switch`.
- switch test
Let's use `switch` to rewrite the above example.
```Go
package main
import (
"fmt"
"strconv"
)
type Element interface{}
type List []Element
type Person struct {
name string
age int
}
func (p Person) String() string {
return "(name: " + p.name + " - age: " + strconv.Itoa(p.age) + " years)"
}
func main() {
list := make(List, 3)
list[0] = 1 //an int
list[1] = "Hello" //a string
list[2] = Person{"Dennis", 70}
for index, element := range list {
switch value := element.(type) {
case int:
fmt.Printf("list[%d] is an int and its value is %d\n", index, value)
case string:
fmt.Printf("list[%d] is a string and its value is %s\n", index, value)
case Person:
fmt.Printf("list[%d] is a Person and its value is %s\n", index, value)
default:
fmt.Println("list[%d] is of a different type", index)
}
}
}
```
One thing you should remember is that `element.(type)` cannot be used outside of the `switch` body, which means in that case you have to use the `comma-ok` pattern .
### Embedded interfaces
The most beautiful thing is that Go has a lot of built-in logic syntax, such as anonymous fields in struct. Not suprisingly, we can use interfaces as anonymous fields as well, but we call them `Embedded interfaces`. Here, we follow the same rules as anonymous fields. More specifically, if an interface has another interface embedded within it, it will behave as if it has all the methods that the embedded interface has.
We can see that the source file in `container/heap` has the following definition:
```Go
type Interface interface {
sort.Interface // embedded sort.Interface
Push(x interface{}) //a Push method to push elements into the heap
Pop() interface{} //a Pop method that pops elements from the heap
}
```
We see that `sort.Interface` is an embedded interface, so the above Interface has the three methods contained within the `sort.Interface` implicitly.
```Go
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less returns whether the element with index i should sort
// before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
```
Another example is the `io.ReadWriter` in package `io`.
```Go
// io.ReadWriter
type ReadWriter interface {
Reader
Writer
}
```
### Reflection
Reflection in Go is used for determining information at runtime. We use the `reflect` package, and [The Laws of Reflection](http://golang.org/doc/articles/laws_of_reflection.html) post explains how reflect works in Go.
There are three steps involved when using reflect. First, we need to convert an interface to reflect types (reflect.Type or reflect.Value, this depends on the situation).
```Go
t := reflect.TypeOf(i) // get meta-data in type i, and use t to get all elements
v := reflect.ValueOf(i) // get actual value in type i, and use v to change its value
```
After that, we can convert the reflected types to get the values that we need.
```Go
var x float64 = 3.4
t := reflect.TypeOf(x)
v := reflect.ValueOf(x)
fmt.Println("type:", t)
fmt.Println("value:", v)
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
```
Finally, if we want to change the values of the reflected types, we need to make it modifiable. As discussed earlier, there is a difference between pass by value and pass by reference. The following code will not compile.
```Go
var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1)
```
Instead, we must use the following code to change the values from reflect types.
```Go
var x float64 = 3.4
p := reflect.ValueOf(&x)
v := p.Elem()
v.SetFloat(7.1)
```
We have just discussed the basics of reflection, however you must practice more in order to understand more.
## Links
- [Directory](preface.md)
- Previous section: [Object-oriented](02.5.md)
- Next section: [Concurrency](02.7.md)
# Concurrency
It is said that Go is the C of the 21st century. I think there are two reasons for it. First, Go is a simple language. Second, concurrency is a hot topic in today's world, and Go supports this feature at the language level.
## goroutine
goroutines and concurrency are built into the core design of Go. They're similar to threads but work differently. Go also gives you full support to sharing memory in your goroutines. One goroutine usually uses 4~5 KB of stack memory. Therefore, it's not hard to run thousands of goroutines on a single computer. A goroutine is more lightweight, more efficient and more convenient than system threads.
goroutines run on the thread manager at runtime in Go. We use the `go` keyword to create a new goroutine, which is a function at the underlying level ( ***main() is a goroutine*** ).
```Go
go hello(a, b, c)
```
Let's see an example.
```Go
package main
import (
"fmt"
"runtime"
)
func say(s string) {
for i := 0; i < 5; i++ {
runtime.Gosched()
fmt.Println(s)
}
}
func main() {
go say("world") // create a new goroutine
say("hello") // current goroutine
}
```
Output:
```
hello
world
hello
world
hello
world
hello
world
hello
```
We see that it's very easy to use concurrency in Go by using the keyword `go`. In the above example, these two goroutines share some memory, but we would better off following the design recipe: Don't use shared data to communicate, use communication to share data.
runtime.Gosched() means let the CPU execute other goroutines, and come back at some point.
In Go 1.5,the runtime now sets the default number of threads to run simultaneously, defined by GOMAXPROCS, to the number of cores available on the CPU.
Before Go 1.5,The scheduler only uses one thread to run all goroutines, which means it only implements concurrency. If you want to use more CPU cores in order to take advantage of parallel processing, you have to call runtime.GOMAXPROCS(n) to set the number of cores you want to use. If `n<1`, it changes nothing.
## channels
goroutines run in the same memory address space, so you have to maintain synchronization when you want to access shared memory. How do you communicate between different goroutines? Go uses a very good communication mechanism called `channel`. A `channel` is like two-way pipeline in Unix shells: use `channel` to send or receive data. The only data type that can be used in channels is the type `channel` and the keyword `chan`. Be aware that you have to use `make` to create a new `channel`.
```Go
ci := make(chan int)
cs := make(chan string)
cf := make(chan interface{})
```
channel uses the operator `<-` to send or receive data.
```Go
ch <- v // send v to channel ch.
v := <-ch // receive data from ch, and assign to v
```
Let's see more examples.
```Go
package main
import "fmt"
func sum(a []int, c chan int) {
total := 0
for _, v := range a {
total += v
}
c <- total // send total to c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
}
```
Sending and receiving data in channels blocks by default, so it's much easier to use synchronous goroutines. What I mean by block is that a goroutine will not continue when receiving data from an empty channel, i.e (`value := <-ch`), until other goroutines send data to this channel. On the other hand, the goroutine will not continue until the data it sends to a channel, i.e (`ch<-5`), is received.
## Buffered channels
I introduced non-buffered channels above. Go also has buffered channels that can store more than a single element. For example, `ch := make(chan bool, 4)`, here we create a channel that can store 4 boolean elements. So in this channel, we are able to send 4 elements into it without blocking, but the goroutine will be blocked when you try to send a fifth element and no goroutine receives it.
```Go
ch := make(chan type, n)
n == 0 ! non-buffer(block)
n > 0 ! buffer(non-block until n elements in the channel)
```
You can try the following code on your computer and change some values.
```Go
package main
import "fmt"
func main() {
c := make(chan int, 2) // change 2 to 1 will have runtime error, but 3 is fine
c <- 1
c <- 2
fmt.Println(<-c)
fmt.Println(<-c)
}
```
## Range and Close
We can use range to operate on buffer channels as in slice and map.
```Go
package main
import (
"fmt"
)
func fibonacci(n int, c chan int) {
x, y := 1, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
close(c)
}
func main() {
c := make(chan int, 10)
go fibonacci(cap(c), c)
for i := range c {
fmt.Println(i)
}
}
```
`for i := range c` will not stop reading data from channel until the channel is closed. We use the keyword `close` to close the channel in above example. It's impossible to send or receive data on a closed channel; you can use `v, ok := <-ch` to test if a channel is closed. If `ok` returns false, it means the there is no data in that channel and it was closed.
Remember to always close channels in producers and not in consumers, or it's very easy to get into panic status.
Another thing you need to remember is that channels are not like files. You don't have to close them frequently unless you are sure the channel is completely useless, or you want to exit range loops.
## Select
In the above examples, we only use one channel, but how can we deal with more than one channel? Go has a keyword called `select` to listen to many channels.
`select` is blocking by default and it continues to execute only when one of channels has data to send or receive. If several channels are ready to use at the same time, select chooses which to execute randomly.
```Go
package main
import "fmt"
func fibonacci(c, quit chan int) {
x, y := 1, 1
for {
select {
case c <- x:
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
}
}
}
func main() {
c := make(chan int)
quit := make(chan int)
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
quit <- 0
}()
fibonacci(c, quit)
}
```
`select` has a `default` case as well, just like `switch`. When all the channels are not ready for use, it executes the default case (it doesn't wait for the channel anymore).
```Go
select {
case i := <-c:
// use i
default:
// executes here when c is blocked
}
```
## Timeout
Sometimes a goroutine becomes blocked. How can we avoid this to prevent the whole program from blocking? It's simple, we can set a timeout in the select.
```Go
func main() {
c := make(chan int)
o := make(chan bool)
go func() {
for {
select {
case v := <-c:
println(v)
case <-time.After(5 * time.Second):
println("timeout")
o <- true
break
}
}
}()
<-o
}
```
## Runtime goroutine
The package `runtime` has some functions for dealing with goroutines.
- `runtime.Goexit()`
Exits the current goroutine, but defered functions will be executed as usual.
- `runtime.Gosched()`
Lets the scheduler execute other goroutines and comes back at some point.
- `runtime.NumCPU() int`
Returns the number of CPU cores
- `runtime.NumGoroutine() int`
Returns the number of goroutines
- `runtime.GOMAXPROCS(n int) int`
Sets how many CPU cores you want to use
## Links
- [Directory](preface.md)
- Previous section: [interface](02.6.md)
- Next section: [Summary](02.8.md)
# 2.8 Summary
In this chapter, we mainly introduced the 25 Go keywords. Let's review what they are and what they do.
```Go
break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var
```
- `var` and `const` are used to define variables and constants.
- `package` and `import` are for package use.
- `func` is used to define functions and methods.
- `return` is used to return values in functions or methods.
- `defer` is used to define defer functions.
- `go` is used to start a new goroutine.
- `select` is used to switch over multiple channels for communication.
- `interface` is used to define interfaces.
- `struct` is used to define special customized types.
- `break`, `case`, `continue`, `for`, `fallthrough`, `else`, `if`, `switch`, `goto` and `default` were introduced in section 2.3.
- `chan` is the type of channel for communication among goroutines.
- `type` is used to define customized types.
- `map` is used to define map which is similar to hash tables in other languages.
- `range` is used for reading data from `slice`, `map` and `channel`.
If you understand how to use these 25 keywords, you've learned a lot of Go already.
## Links
- [Directory](preface.md)
- Previous section: [Concurrency](02.7.md)
- Next chapter: [Web foundation](03.0.md)
# 3 Web foundation
The reason you are reading this book is that you want to learn to build web applications in Go. As I've said before, Go provides many powerful packages like `http`. These packages can help you a lot when trying to build web applications. I'll teach you everything you need to know in the following chapters, and we'll talk about some concepts of the web and how to run web applications in Go in this chapter.
## Links
- [Directory](preface.md)
- Previous chapter: [Chapter 2 Summary](02.8.md)
- Next section: [Web working principles](03.1.md)
# Web working principles
Every time you open your browsers, type some URLs and press enter, you will see beautiful web pages appear on your screen. But do you know what is happening behind these simple actions?
Normally, your browser is a client. After you type a URL, it takes the host part of the URL and sends it to a Domain Name Server (DNS) in order to get the IP address of the host. Then it connects to the IP address and asks to setup a TCP connection. The browser sends HTTP requests through the connection. The server handles them and replies with HTTP responses containing the content that make up the web page. Finally, the browser renders the body of the web page and disconnects from the server.
![](images/3.1.web2.png?raw=true)
Figure 3.1 Processes of users visit a website
A web server, also known as an HTTP server, uses the HTTP protocol to communicate with clients. All web browsers can be considered clients.
We can divide the web's working principles into the following steps:
- Client uses TCP/IP protocol to connect to server.
- Client sends HTTP request packages to server.
- Server returns HTTP response packages to client. If the requested resources include dynamic scripts, server calls script engine first.
- Client disconnects from server, starts rendering HTML.
This is a simple work flow of HTTP affairs -notice that the server closes its connections after it sends data to the clients, then waits for the next request.
## URL and DNS resolution
We always use URLs to access web pages, but do you know how URLs work?
The full name of a URL is Uniform Resource Locator. It's for describing resources on the internet and its basic form is as follows.
scheme://host[:port#]/path/.../[?query-string][#anchor]
scheme assign underlying protocol (such as HTTP, HTTPS, FTP)
host IP or domain name of HTTP server
port# default port is 80, and it can be omitted in this case.
If you want to use other ports, you must specify which port. For example,
http://www.cnblogs.com:8080/
path resources path
query-string data are sent to server
anchor anchor
DNS is an abbreviation of Domain Name System. It's the naming system for computer network services, and it converts domain names to actual IP addresses, just like a translator.
![](images/3.1.dns_hierachy.png?raw=true)
Figure 3.2 DNS working principles
To understand more about its working principle, let's see the detailed DNS resolution process as follows.
1. After typing the domain name `www.qq.com` in the browser, the operating system will check if there are any mapping relationships in the hosts' files for this domain name. If so, then the domain name resolution is complete.
2. If no mapping relationships exist in the hosts' files, the operating system will check if any cache exists in the DNS. If so, then the domain name resolution is complete.
3. If no mapping relationships exist in both the host and DNS cache, the operating system finds the first DNS resolution server in your TCP/IP settings, which is likely your local DNS server. When the local DNS server receives the query, if the domain name that you want to query is contained within the local configuration of its regional resources, it returns the results to the client. This DNS resolution is authoritative.
4. If the local DNS server doesn't contain the domain name but a mapping relationship exists in the cache, the local DNS server gives back this result to the client. This DNS resolution is not authoritative.
5. If the local DNS server cannot resolve this domain name either by configuration of regional resources or cache, it will proceed to the next step, which depends on the local DNS server's settings.
-If the local DNS server doesn't enable forwarding, it routes the request to the root DNS server, then returns the IP address of a top level DNS server which may know the domain name, `.com` in this case. If the first top level DNS server doesn't recognize the domain name, it again reroutes the request to the next top level DNS server until it reaches one that recognizes the domain name. Then the top level DNS server asks this next level DNS server for the IP address corresponding to `www.qq.com`.
-If the local DNS server has forwarding enabled, it sends the request to an upper level DNS server. If the upper level DNS server also doesn't recognize the domain name, then the request keeps getting rerouted to higher levels until it finally reaches a DNS server which recognizes the domain name.
Whether or not the local DNS server enables forwarding, the IP address of the domain name always returns to the local DNS server, and the local DNS server sends it back to the client.
![](images/3.1.dns_inquery.png?raw=true)
Figure 3.3 DNS resolution work flow
`Recursive query process` simply means that the enquirers change in the process. Enquirers do not change in `Iterative query` processes.
Now we know clients get IP addresses in the end, so the browsers are communicating with servers through IP addresses.
## HTTP protocol
The HTTP protocol is a core part of web services. It's important to know what the HTTP protocol is before you understand how the web works.
HTTP is the protocol that is used to facilitate communication between browser and web server. It is based on the TCP protocol and usually uses port 80 on the side of the web server. It is a protocol that utilizes the request-response model -clients send requests and servers respond. According to the HTTP protocol, clients always setup new connections and send HTTP requests to servers. Servers are not able to connect to clients proactively, or establish callback connections. The connection between a client and a server can be closed by either side. For example, you can cancel your download request and HTTP connection and your browser will disconnect from the server before you finish downloading.
The HTTP protocol is stateless, which means the server has no idea about the relationship between the two connections even though they are both from same client. To solve this problem, web applications use cookies to maintain the state of connections.
Because the HTTP protocol is based on the TCP protocol, all TCP attacks will affect HTTP communications in your server. Examples of such attacks are SYN flooding, DoS and DDoS attacks.
### HTTP request package (browser information)
Request packages all have three parts: request line, request header, and body. There is one blank line between header and body.
GET /domains/example/ HTTP/1.1 // request line: request method, URL, protocol and its version
Host:www.iana.org // domain name
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4 // browser information
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 // mime that clients can accept
Accept-Encoding:gzip,deflate,sdch // stream compression
Accept-Charset:UTF-8,*;q=0.5 // character set in client side
// blank line
// body, request resource arguments (for example, arguments in POST)
We use fiddler to get the following request information.
![](images/3.1.http.png?raw=true)
Figure 3.4 Information of a GET request caught by fiddler
![](images/3.1.httpPOST.png?raw=true)
Figure 3.5 Information of a POST request caught by fiddler
**We can see that GET does not have a request body, unlike POST, which does.**
There are many methods you can use to communicate with servers in HTTP; GET, POST, PUT and DELETE are the 4 basic methods that we typically use. A URL represents a resource on a network, so these 4 methods define the query, change, add and delete operations that can act on these resources. GET and POST are very commonly used in HTTP. GET can append query parameters to the URL, using `?` to separate the URL and parameters and `&` between the arguments, like `EditPosts.aspx?name=test1&id=123456`. POST puts data in the request body because the URL implements a length limitation via the browser. Thus, POST can submit much more data than GET. Also, when we submit user names and passwords, we don't want this kind of information to appear in the URL, so we use POST to keep them invisible.
### HTTP response package (server information)
Let's see what information is contained in the response packages.
HTTP/1.1 200 OK // status line
Server: nginx/1.0.8 // web server software and its version in the server machine
Date:Date: Tue, 30 Oct 2012 04:14:25 GMT // responded time
Content-Type: text/html // responded data type
Transfer-Encoding: chunked // it means data were sent in fragments
Connection: keep-alive // keep connection
Content-Length: 90 // length of body
// blank line
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"... // message body
The first line is called the status line. It supplies the HTTP version, status code and status message.
The status code informs the client of the status of the HTTP server's response. In HTTP/1.1, 5 kinds of status codes were defined:
- 1xx Informational
- 2xx Success
- 3xx Redirection
- 4xx Client Error
- 5xx Server Error
Let's see more examples about response packages. 200 means server responded correctly, 302 means redirection.
![](images/3.1.response.png?raw=true)
Figure 3.6 Full information for visiting a website
### HTTP is stateless and Connection: keep-alive
The term stateless doesn't mean that the server has no ability to keep a connection. It simply means that the server doesn't recognize any relationships between any two requests.
In HTTP/1.1, Keep-alive is used by default. If clients have additional requests, they will use the same connection for them.
Notice that Keep-alive cannot maintain one connection forever; the application running in the server determines the limit with which to keep the connection alive for, and in most cases you can configure this limit.
## Request instance
![](images/3.1.web.png?raw=true)
Figure 3.7 All packages for opening one web page
We can see the entire communication process between client and server from the above picture. You may notice that there are many resource files in the list; these are called static files, and Go has specialized processing methods for these files.
This is the most important function of browsers: to request for a URL and retrieve data from web servers, then render the HTML. If it finds some files in the DOM such as CSS or JS files, browsers will request these resources from the server again until all the resources finish rendering on your screen.
Reducing HTTP request times is one way of improving the loading speed of web pages. By reducing the number of CSS and JS files that need to be loaded, both request latencies and pressure on your web servers can be reduced at the same time.
## Links
- [Directory](preface.md)
- Previous section: [Web foundation](03.0.md)
- Next section: [Build a simple web server](03.2.md)
# 3.2 Build a simple web server
We've discussed that web applications are based on the HTTP protocol, and Go provides full HTTP support in the `net/http` package. It's very easy to set a web server up using this package.
## Use http package setup a web server
package main
import (
"fmt"
"net/http"
"strings"
"log"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
r.ParseForm() // parse arguments, you have to call this by yourself
fmt.Println(r.Form) // print form information in server side
fmt.Println("path", r.URL.Path)
fmt.Println("scheme", r.URL.Scheme)
fmt.Println(r.Form["url_long"])
for k, v := range r.Form {
fmt.Println("key:", k)
fmt.Println("val:", strings.Join(v, ""))
}
fmt.Fprintf(w, "Hello astaxie!") // send data to client side
}
func main() {
http.HandleFunc("/", sayhelloName) // set router
err := http.ListenAndServe(":9090", nil) // set listen port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
After we execute the above code, the server begins listening to port 9090 in local host.
Open your browser and visit `http://localhost:9090`. You can see that `Hello astaxie` is on your screen.
Let's try another address with additional arguments: `http://localhost:9090/?url_long=111&url_long=222`
Now let's see what happens on both the client and server sides.
You should see the following information on the server side:
![](images/3.2.goweb.png?raw=true)
Figure 3.8 Server printed information
As you can see, we only need to call two functions in order to build a simple web server.
If you are working with PHP, you're probably asking whether or not we need something like Nginx or Apache. The answer is we don't, since Go listens to the TCP port by itself, and the function `sayhelloName` is the logic function just like a controller in PHP.
If you are working with Python you should know tornado, and the above example is very similar to that.
If you are working with Ruby, you may notice it is like script/server in ROR (Ruby on Rails).
We used two simple functions to setup a simple web server in this section, and this simple server already has the capacity for high concurrency operations. We will talk about how to utilize this in the next two sections.
## Links
- [Directory](preface.md)
- Previous section: [Web working principles](03.1.md)
- Next section: [How Go works with web](03.3.md)
# 3.3 How Go works with web
We learned to use the `net/http` package to build a simple web server in the previous section, and all those working principles are the same as those we will talk about in the first section of this chapter.
## Concepts in web principles
Request: request data from users, including POST, GET, Cookie and URL.
Response: response data from server to clients.
Conn: connections between clients and servers.
Handler: Request handling logic and response generation.
## http package operating mechanism
The following picture shows the work flow of a Go web server.
![](images/3.3.http.png?raw=true)
Figure 3.9 http work flow
1. Create a listening socket, listen to a port and wait for clients.
2. Accept requests from clients.
3. Handle requests, read HTTP header. If the request uses POST method, read data in the message body and pass them to handlers. Finally, socket returns response data to clients.
Once we know the answers to the three following questions, it's easy to know how the web works in Go.
- How do we listen to a port?
- How do we accept client requests?
- How do we allocate handlers?
In the previous section we saw that Go uses `ListenAndServe` to handle these steps: initialize a server object, call `net.Listen("tcp", addr)` to setup a TCP listener and listen to a specific address and port.
Let's take a look at the `http` package's source code.
//Build version go1.1.2.
func (srv *Server) Serve(l net.Listener) error {
defer l.Close()
var tempDelay time.Duration // how long to sleep on accept failure
for {
rw, e := l.Accept()
if e != nil {
if ne, ok := e.(net.Error); ok && ne.Temporary() {
if tempDelay == 0 {
tempDelay = 5 * time.Millisecond
} else {
tempDelay *= 2
}
if max := 1 * time.Second; tempDelay > max {
tempDelay = max
}
log.Printf("http: Accept error: %v; retrying in %v", e, tempDelay)
time.Sleep(tempDelay)
continue
}
return e
}
tempDelay = 0
c, err := srv.newConn(rw)
if err != nil {
continue
}
go c.serve()
}
}
How do we accept client requests after we begin listening to a port? In the source code, we can see that `srv.Serve(net.Listener)` is called to handle client requests. In the body of the function there is a `for{}`. It accepts a request, creates a new connection then starts a new goroutine, passing the request data to the `go c.serve()` goroutine. This is how Go supports high concurrency, and every goroutine is independent.
How do we use specific functions to handle requests? `conn` parses request `c.ReadRequest()` at first, then gets the corresponding handler: `handler := sh.srv.Handler` which is the second argument we passed when we called `ListenAndServe`. Because we passed `nil`, Go uses its default handler `handler = DefaultServeMux`. So what is `DefaultServeMux` doing here? Well, its the router variable which can call handler functions for specific URLs. Did we set this? Yes, we did. We did this in the first line where we used `http.HandleFunc("/", sayhelloName)`. We're using this function to register the router rule for the "/" path. When the URL is `/`, the router calls the function `sayhelloName`. DefaultServeMux calls ServerHTTP to get handler functions for different paths, calling `sayhelloName` in this specific case. Finally, the server writes data and responds to clients.
Detailed work flow:
![](images/3.3.illustrator.png?raw=true)
Figure 3.10 Work flow of handling an HTTP request
I think you should know how Go runs web servers now.
## Links
- [Directory](preface.md)
- Previous section: [Build a simple web server](03.2.md)
- Next section: [Get into http package](03.4.md)
# 3.4 Get into http package
In previous sections, we learned about the work flow of the web and talked a little bit about Go's `http` package. In this section, we are going to learn about two core functions in the `http` package: Conn and ServeMux.
## goroutine in Conn
Unlike normal HTTP servers, Go uses goroutines for every job initiated by Conn in order to achieve high concurrency and performance, so every job is independent.
Go uses the following code to wait for new connections from clients.
```Go
c, err := srv.newConn(rw)
if err != nil {
continue
}
go c.serve()
```
As you can see, it creates a new goroutine for every connection, and passes the handler that is able to read data from the request to the goroutine.
## Customized ServeMux
We used Go's default router in previous sections when discussing conn.server, with the router passing request data to a back-end handler.
The struct of the default router:
```Go
type ServeMux struct {
mu sync.RWMutex // because of concurrency, we have to use a mutex here
m map[string]muxEntry // router rules, every string mapping to a handler
}
```
The struct of muxEntry:
```Go
type muxEntry struct {
explicit bool // exact match or not
h Handler
}
```
The interface of Handler:
```Go
type Handler interface {
ServeHTTP(ResponseWriter, *Request) // routing implementer
}
```
`Handler` is an interface, but if the function `sayhelloName` didn't implement this interface, then how did we add it as handler? The answer lies in another type called `HandlerFunc` in the `http` package. We called `HandlerFunc` to define our `sayhelloName` method, so `sayhelloName` implemented `Handler` at the same time. It's like we're calling `HandlerFunc(f)`, and the function `f` is force converted to type `HandlerFunc`.
```Go
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
```
How does the router call handlers after we set the router rules?
The router calls `mux.handler.ServeHTTP(w, r)` when it receives requests. In other words, it calls the `ServeHTTP` interface of the handlers which have implemented it.
Now, let's see how `mux.handler` works.
```Go
func (mux *ServeMux) handler(r *Request) Handler {
mux.mu.RLock()
defer mux.mu.RUnlock()
// Host-specific pattern takes precedence over generic ones
h := mux.match(r.Host + r.URL.Path)
if h == nil {
h = mux.match(r.URL.Path)
}
if h == nil {
h = NotFoundHandler()
}
return h
}
```
The router uses the request's URL as a key to find the corresponding handler saved in the map, then calls handler.ServeHTTP to execute functions to handle the data.
You should understand the default router's work flow by now, and Go actually supports customized routers. The second argument of `ListenAndServe` is for configuring customized routers. It's an interface of `Handler`. Therefore, any router that implements the `Handler` interface can be used.
The following example shows how to implement a simple router.
```Go
package main
import (
"fmt"
"net/http"
)
type MyMux struct {
}
func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
sayhelloName(w, r)
return
}
http.NotFound(w, r)
return
}
func sayhelloName(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello myroute!")
}
func main() {
mux := &MyMux{}
http.ListenAndServe(":9090", mux)
}
```
# Routing
If you do not want to use a Router, you can still achieve what we wrote in the above section by replacing the second argument to `ListenAndServe` to nil and registering the URLs using a `HandleFunc` function which goes through all the registered URLs to find the best match, so care must be taken about the order of the registering.
sample code:
```Go
http.HandleFunc("/", views.ShowAllTasksFunc)
http.HandleFunc("/complete/", views.CompleteTaskFunc)
http.HandleFunc("/delete/", views.DeleteTaskFunc)
//ShowAllTasksFunc is used to handle the "/" URL which is the default ons
//TODO add http404 error
func ShowAllTasksFunc(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
context := db.GetTasks("pending") //true when you want non deleted tasks
//db is a package which interacts with the database
if message != "" {
context.Message = message
}
homeTemplate.Execute(w, context)
message = ""
} else {
message = "Method not allowed"
http.Redirect(w, r, "/", http.StatusFound)
}
}
```
This is fine for simple applications which doesn't requires parameterized routing, what when you need that? You can either use the existing toolkits or frameworks, but since this book is about writing webapps in golang, we are going to teach how to handle this scenario as well.
When the match is made on the `HandleFunc` function, the URL is matched, so suppose we are writing a todo list manager and we want to delete a task so the URL we decide for that application is `/delete/1`, so we register the delete URL like this
`http.HandleFunc("/delete/", views.DeleteTaskFunc)`
`/delete/1` this URL matches closest with the "/delete/" URL than any other URL so in the `r.URL.path` we get the entire URL of the request.
```Go
http.HandleFunc("/delete/", views.DeleteTaskFunc)
//DeleteTaskFunc is used to delete a task, trash = move to recycle bin, delete = permanent delete
func DeleteTaskFunc(w http.ResponseWriter, r *http.Request) {
if r.Method == "DELETE" {
id := r.URL.Path[len("/delete/"):]
if id == "all" {
db.DeleteAll()
http.Redirect(w, r, "/", http.StatusFound)
} else {
id, err := strconv.Atoi(id)
if err != nil {
fmt.Println(err)
} else {
err = db.DeleteTask(id)
if err != nil {
message = "Error deleting task"
} else {
message = "Task deleted"
}
http.Redirect(w, r, "/", http.StatusFound)
}
}
} else {
message = "Method not allowed"
http.Redirect(w, r, "/", http.StatusFound)
}
}
```
link: https://github.com/thewhitetulip/Tasks/blob/master/views/views.go#L170-#L195
In this above method what we basically do is in the function which handles the `/delete/` URL we take its compelete URL, which is `/delete/1`, then we take a slice of the string and extract everything which starts after the delete word which is the actual parameter, in this case it is `1`. Then we use the `strconv` package to convert it to an integer and delete the task with that taskID.
In more complex scenarios too we can use this method, the advantage is that we don't have to use any third party toolkit, but then again third party toolkits are useful in their own right, you need to make a decision which method you'd prefer. No answer is the right answer.
## Go code execution flow
Let's take a look at the whole execution flow.
- Call `http.HandleFunc`
1. Call HandleFunc of DefaultServeMux
2. Call Handle of DefaultServeMux
3. Add router rules to map[string]muxEntry of DefaultServeMux
- Call `http.ListenAndServe(":9090", nil)`
1. Instantiate Server
2. Call ListenAndServe method of Server
3. Call net.Listen("tcp", addr) to listen to port
4. Start a loop and accept requests in the loop body
5. Instantiate a Conn and start a goroutine for every request: `go c.serve()`
6. Read request data: `w, err := c.readRequest()`
7. Check whether handler is empty or not, if it's empty then use DefaultServeMux
8. Call ServeHTTP of handler
9. Execute code in DefaultServeMux in this case
10. Choose handler by URL and execute code in that handler function: `mux.handler.ServeHTTP(w, r)`
11. How to choose handler:
A. Check router rules for this URL
B. Call ServeHTTP in that handler if there is one
C. Call ServeHTTP of NotFoundHandler otherwise
## Links
- [Directory](preface.md)
- Previous section: [How Go works with web](03.3.md)
- Next section: [Summary](03.5.md)
# 3.5 Summary
In this chapter, we introduced HTTP, DNS resolution flow and how to build a simple web server. Then we talked about how Go implements web servers for us by looking at the source code of the `net/http` package.
I hope that you now know much more about web development, and you should see that it's quite easy and flexible to build a web application in Go.
## Links
- [Directory](preface.md)
- Previous section: [Get into http package](03.4.md)
- Next chapter: [User form](04.0.md)
# 4 User form
A user form is something that is very commonly used when developing web applications. It provides the ability to communicate between clients and servers. You must be very familiar with forms if you are a web developer; if you are a C/C++ programmer, you may want to ask: what is a user form?
A form is an area that contains form elements. Users can input information into form elements like text boxes, drop down lists, radio buttons, check boxes, etc. We use the form tag `<form>` to define forms.
<form>
...
input elements
...
</form>
Go already has many convenient functions to deal with user forms. You can easily get form data in HTTP requests, and they are easy to integrate into your own web applications. In section 4.1, we are going to talk about how to handle form data in Go. Also, since you cannot trust any data coming from the client side, you must first validate the data before using it. We'll go through some examples about how to validate form data in section 4.2.
We say that HTTP is stateless. How can we identify that certain forms are from the same user? And how do we make sure that one form can only be submitted once? We'll look at some details concerning cookies (a cookie is information that can be saved on the client side and added to the request header when the request is sent to the server) in both sections 4.3 and 4.4.
Another common use-case for forms is uploading files. In section 4.5, you will learn how to do this as well as controlling the file upload size before it begins uploading, in Go.
## Links
- [Directory](preface.md)
- Previous chapter: [Chapter 3 Summary](03.5.md)
- Next section: [Process form inputs](04.1.md)
# 4.1 Process form inputs
Before we begin, let's take a look at a simple example of a typical user form, saved as `login.gtpl` in your project folder.
```html
<html>
<head>
<title></title>
</head>
<body>
<form action="/login" method="post">
Username:<input type="text" name="username">
Password:<input type="password" name="password">
<input type="submit" value="Login">
</form>
</body>
</html>
```
This form will submit to `/login` on the server. After the user clicks the login button, the data will be sent to the `login` handler registered by the server router. Then we need to know whether it uses the POST method or GET.
This is easy to find out using the `http` package. Let's see how to handle the form data on the login page.
```Go
package main
import (
"fmt"
"html/template"
"log"
"net/http"
"strings"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
r.ParseForm() //Parse url parameters passed, then parse the response packet for the POST body (request body)
// attention: If you do not call ParseForm method, the following data can not be obtained form
fmt.Println(r.Form) // print information on server side.
fmt.Println("path", r.URL.Path)
fmt.Println("scheme", r.URL.Scheme)
fmt.Println(r.Form["url_long"])
for k, v := range r.Form {
fmt.Println("key:", k)
fmt.Println("val:", strings.Join(v, ""))
}
fmt.Fprintf(w, "Hello astaxie!") // write data to response
}
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) //get request method
if r.Method == "GET" {
t, _ := template.ParseFiles("login.gtpl")
t.Execute(w, nil)
} else {
r.ParseForm()
// logic part of log in
fmt.Println("username:", r.Form["username"])
fmt.Println("password:", r.Form["password"])
}
}
func main() {
http.HandleFunc("/", sayhelloName) // setting router rule
http.HandleFunc("/login", login)
err := http.ListenAndServe(":9090", nil) // setting listening port
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
```
Here we use `r.Method` to get the request method, and it returns an http verb -"GET", "POST", "PUT", etc.
In the `login` function, we use `r.Method` to check whether it's a login page or login processing logic. In other words, we check to see whether the user is simply opening the page, or trying to log in. Serve shows the page only when the request comes in via the GET method, and it executes the login logic when the request uses the POST method.
You should see the following interface after opening `http://127.0.0.1:9090/login` in your browser.
![](images/4.1.login.png?raw=true)
Figure 4.1 User login interface
The server will not print anything until after we type in a username and password, because the handler doesn't parse the form until we call `r.ParseForm()`. Let's add `r.ParseForm()` before `fmt.Println("username:", r.Form["username"])`, compile our program and test it again. You will find that the information is printed on the server side now.
`r.Form` contains all of the request arguments, for instance the query-string in the URL and the data in POST and PUT. If the data has conflicts, for example parameters that have the same name, the server will save the data into a slice with multiple values. The Go documentation states that Go will save the data from GET and POST requests in different places.
Try changing the value of the action in the form `http://127.0.0.1:9090/login` to `http://127.0.0.1:9090/login?username=astaxie` in the `login.gtpl` file, test it again, and you will see that the slice is printed on the server side.
![](images/4.1.slice.png?raw=true)
Figure 4.2 Server prints request data
The type of `request.Form` is `url.Value`. It saves data with the format `key=value`.
```Go
v := url.Values{}
v.Set("name", "Ava")
v.Add("friend", "Jess")
v.Add("friend", "Sarah")
v.Add("friend", "Zoe")
// v.Encode() == "name=Ava&friend=Jess&friend=Sarah&friend=Zoe"
fmt.Println(v.Get("name"))
fmt.Println(v.Get("friend"))
fmt.Println(v["friend"])
```
**Tips** Requests have the ability to access form data using the `FormValue()` method. For example, you can change `r.Form["username"]` to `r.FormValue("username")`, and Go calls `r.ParseForm` automatically. Notice that it returns the first value if there are arguments with the same name, and it returns an empty string if there is no such argument.
## Links
- [Directory](preface.md)
- Previous section: [User form](04.0.md)
- Next section: [Verification of inputs](04.2.md)
# 4.2 Verification of inputs
One of the most important principles in web development is that you cannot trust anything from client side user forms. You have to validate all incoming data before using it. Many websites are affected by this problem, which is simple yet crucial.
There are two ways of verifying form data that are in common use. The first is JavaScript validation on the front-end, and the second is server validation on the back-end. In this section, we are going to talk about server side validation in web development.
## Required fields
Sometimes we require that users input some fields but they fail to complete the field. For example in the previous section when we required a username. You can use the `len` function to get the length of a field in order to ensure that users have entered something.
```Go
if len(r.Form["username"][0])==0{
// code for empty field
}
```
`r.Form` treats different form element types differently when they are blank. For empty textboxes, text areas and file uploads, it returns an empty string; for radio buttons and check boxes, it doesn't even create the corresponding items. Instead, you will get errors if you try to access it. Therefore, it's safer to use `r.Form.Get()` to get field values since it will always return empty if the value does not exist. On the other hand, `r.Form.Get()` can only get one field value at a time, so you need to use `r.Form` to get the map of values.
## Numbers
Sometimes you require numbers rather than other text for the field value. For example, let's say that you require the age of a user in integer form only, i.e 50 or 10, instead of "old enough" or "young man". If we require a positive number, we can convert the value to the `int` type first, then process it.
```Go
getint,err:=strconv.Atoi(r.Form.Get("age"))
if err!=nil{
// error occurs when convert to number, it may not a number
}
// check range of number
if getint >100 {
// too big
}
```
Another way to do this is by using regular expressions.
```Go
if m, _ := regexp.MatchString("^[0-9]+$", r.Form.Get("age")); !m {
return false
}
```
For high performance purposes, regular expressions are not efficient, however simple regular expressions are usually fast enough. If you are familiar with regular expressions, it's a very convenient way to verify data. Notice that Go uses [RE2](http://code.google.com/p/re2/wiki/Syntax), so all UTF-8 characters are supported.
## Chinese
Sometimes we need users to input their Chinese names and we have to verify that they all use Chinese rather than random characters. For Chinese verification, regular expressions are the only way.
```Go
if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", r.Form.Get("realname")); !m {
return false
}
```
## English letters
Sometimes we need users to input only English letters. For example, we require someone's English name, like astaxie instead of asta谢. We can easily use regular expressions to perform our verification.
```Go
if m, _ := regexp.MatchString("^[a-zA-Z]+$", r.Form.Get("engname")); !m {
return false
}
```
## E-mail address
If you want to know whether users have entered valid E-mail addresses, you can use the following regular expression:
```Go
if m, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`, r.Form.Get("email")); !m {
fmt.Println("no")
}else{
fmt.Println("yes")
}
```
## Drop down list
Let's say we require an item from our drop down list, but instead we get a value fabricated by hackers. How do we prevent this from happening?
Suppose we have the following `<select>`:
```html
<select name="fruit">
<option value="apple">apple</option>
<option value="pear">pear</option>
<option value="banana">banana</option>
</select>
```
We can use the following strategy to sanitize our input:
```Go
slice:=[]string{"apple","pear","banana"}
for _, v := range slice {
if v == r.Form.Get("fruit") {
return true
}
}
return false
```
All the functions I've shown above are in my open source project for operating on slices and maps: [https://github.com/astaxie/beeku](https://github.com/astaxie/beeku)
## Radio buttons
If we want to know whether the user is male or female, we may use a radio button, returning 1 for male and 2 for female. However, some little kid who just read his first book on HTTP, decides to send to you a 3. Will your program throw an exception? As you can see, we need to use the same method as we did for our drop down list to make sure that only expected values are returned by our radio button.
```html
<input type="radio" name="gender" value="1">Male
<input type="radio" name="gender" value="2">Female
```
And we use the following code to validate the input:
```Go
slice:=[]int{1,2}
for _, v := range slice {
if v == r.Form.Get("gender") {
return true
}
}
return false
```
## Check boxes
Suppose there are some check boxes for user interests, and that you don't want extraneous values here either. You can validate these ase follows:
```html
<input type="checkbox" name="interest" value="football">Football
<input type="checkbox" name="interest" value="basketball">Basketball
<input type="checkbox" name="interest" value="tennis">Tennis
```
In this case, the sanitization is a little bit different to validating the button and check box inputs since here we get a slice from the check boxes.
```Go
slice:=[]string{"football","basketball","tennis"}
a:=Slice_diff(r.Form["interest"],slice)
if a == nil{
return true
}
return false
```
## Date and time
Suppose you want users to input valid dates or times. Go has the `time` package for converting year, month and day to their corresponding times. After that, it's easy to check it.
```Go
t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
fmt.Printf("Go launched at %s\n", t.Local())
```
After you have the time, you can use the `time` package for more operations, depending on your needs.
In this section, we've discussed some common methods of validating form data on the server side. I hope that you now understand more about data validation in Go, especially how to use regular expressions to your advantage.
## Links
- [Directory](preface.md)
- Previous section: [Process form inputs](04.1.md)
- Next section: [Cross site scripting](04.3.md)
# 4.3 Cross site scripting
Today's websites have much more dynamic content in order to improve user experience, which means that we must provide dynamic information depending on every individual's behavior. Unfortunately, dynamic websites are susceptible to malicious attacks known as "Cross site scripting" (known as "XSS"). Static websites are not susceptible to Cross site scripting.
Attackers often inject malicious scripts like JavaScript, VBScript, ActiveX or Flash into those websites that have loopholes. Once they have successfully injected their scripts, user information can be stolen and your website can be flooded with spam. The attackers can also change user settings to whatever they want.
If you wish to prevent this kind of attack, you should combine the following two approaches:
- Validation of all data from users, which we talked about in the previous section.
- Carefully handle data that will be sent to clients in order to prevent any injected scripts from running on browsers.
So how can we do these two things in Go? Fortunately, the `html/template` package has some useful functions to escape data as follows:
- `func HTMLEscape(w io.Writer, b []byte)` escapes b to w.
- `func HTMLEscapeString(s string) string` returns a string after escaping from s.
- `func HTMLEscaper(args ...interface{}) string` returns a string after escaping from multiple arguments.
Let's change the example in section 4.1:
```Go
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // print at server side
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // responded to clients
```
If someone tries to input the username as `<script>alert()</script>`, we will see the following content in the browser:
![](images/4.3.escape.png?raw=true)
Figure 4.3 JavaScript after escaped
Functions in the `html/template` package help you to escape all HTML tags. What if you just want to print `<script>alert()</script>` to browsers? You should use `text/template` instead.
```Go
import "text/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
```
Output:
```html
Hello, <script>alert('you have been pwned')</script>!
```
Or you can use the `template.HTML` type :
Variable content will not be escaped if its type is `template.HTML`.
```Go
import "html/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", template.HTML("<script>alert('you have been pwned')</script>"))
```
Output:
```html
Hello, <script>alert('you have been pwned')</script>!
```
One more example of escaping:
```Go
import "html/template"
...
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
```
Output:
```html
Hello, &lt;script&gt;alert(&#39;you have been pwned&#39;)&lt;/script&gt;!
```
## Links
- [Directory](preface.md)
- Previous section: [Verification of inputs](04.2.md)
- Next section: [Duplicate submissions](04.4.md)
# 4.4 Duplicate submissions
I don't know if you've ever seen some blogs or BBS' that have more than one post that are exactly the same, but I can tell you that it's because users submitted duplicate post forms. There are many things that can cause duplicate submissions; sometimes users just double click the submit button, or they want to modify some content after posting and press the back button. In some cases it is by the intentional actions of malicious users. It's easy to see how duplicate submissions can lead to many problems. Thus, we have to use effective means to prevent it.
The solution is to add a hidden field with a unique token to your form, and to always check this token before processing the incoming data. Also, if you are using Ajax to submit a form, use JavaScript to disable the submit button once the form has been submitted.
Let's improve the example from section 4.2:
```html
<input type="checkbox" name="interest" value="football">Football
<input type="checkbox" name="interest" value="basketball">Basketball
<input type="checkbox" name="interest" value="tennis">Tennis
Username:<input type="text" name="username">
Password:<input type="password" name="password">
<input type="hidden" name="token" value="{{.}}">
<input type="submit" value="Login">
```
We use an MD5 hash (time stamp) to generate the token, and added it to both a hidden field on the client side form and a session cookie on the server side (Chapter 6). We can then use this token to check whether or not this form was submitted.
```Go
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) // get request method
if r.Method == "GET" {
crutime := time.Now().Unix()
h := md5.New()
io.WriteString(h, strconv.FormatInt(crutime, 10))
token := fmt.Sprintf("%x", h.Sum(nil))
t, _ := template.ParseFiles("login.gtpl")
t.Execute(w, token)
} else {
// log in request
r.ParseForm()
token := r.Form.Get("token")
if token != "" {
// check token validity
} else {
// give error if no token
}
fmt.Println("username length:", len(r.Form["username"][0]))
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // print in server side
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // respond to client
}
}
```
![](images/4.4.token.png?raw=true)
Figure 4.4 The content in browser after adding a token
You can refresh this page and you will see a different token every time. This ensures that every form is unique.
For now, you can prevent many duplicate submission attacks by adding tokens to your forms, but it cannot prevent all deceptive attacks of this type. There is much more work that needs to be done.
## Links
- [Directory](preface.md)
- Previous section: [Cross site scripting](04.3.md)
- Next section: [File upload](04.5.md)
# 4.5 File upload
Suppose you have a website like Instagram and you want users to upload their beautiful photos. How would you implement that functionality?
You have to add property `enctype` to the form that you want to use for uploading photos. There are three possible values for this property:
```
application/x-www-form-urlencoded Transcode all characters before uploading (default).
multipart/form-data No transcoding. You must use this value when your form has file upload controls.
text/plain Convert spaces to "+", but no transcoding for special characters.
```
Therefore, the HTML content of a file upload form should look like this:
```html
<html>
<head>
<title>Upload file</title>
</head>
<body>
<form enctype="multipart/form-data" action="http://127.0.0.1:9090/upload" method="post">
<input type="file" name="uploadfile" />
<input type="hidden" name="token" value="{{.}}"/>
<input type="submit" value="upload" />
</form>
</body>
</html>
```
We need to add a function on the server side to handle this form.
```Go
http.HandleFunc("/upload", upload)
// upload logic
func upload(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method)
if r.Method == "GET" {
crutime := time.Now().Unix()
h := md5.New()
io.WriteString(h, strconv.FormatInt(crutime, 10))
token := fmt.Sprintf("%x", h.Sum(nil))
t, _ := template.ParseFiles("upload.gtpl")
t.Execute(w, token)
} else {
r.ParseMultipartForm(32 << 20)
file, handler, err := r.FormFile("uploadfile")
if err != nil {
fmt.Println(err)
return
}
defer file.Close()
fmt.Fprintf(w, "%v", handler.Header)
f, err := os.OpenFile("./test/"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
io.Copy(f, file)
}
}
```
As you can see, we need to call `r.ParseMultipartForm` for uploading files. The function ParseMultipartForm takes the `maxMemory` argument. After you call `ParseMultipartForm`, the file will be saved in the server memory with `maxMemory` size. If the file size is larger than `maxMemory`, the rest of the data will be saved in a system temporary file. You can use `r.FormFile` to get the file handle and use `io.Copy` to save to your file system.
You don't need to call `r.ParseForm` when you access other non-file fields in the form because Go will call it when it's necessary. Also, calling `ParseMultipartForm` once is enough -multiple calls make no difference.
We use three steps for uploading files as follows:
1. Add `enctype="multipart/form-data"` to your form.
2. Call `r.ParseMultipartForm` on the server side to save the file either to memory or to a temporary file.
3. Call `r.FormFile` to get the file handle and save to the file system.
The file handler is the `multipart.FileHeader`. It uses the following struct:
```Go
type FileHeader struct {
Filename string
Header textproto.MIMEHeader
// contains filtered or unexported fields
}
```
![](images/4.5.upload2.png?raw=true)
Figure 4.5 Print information on server after receiving file.
## Clients upload files
I showed an example of using a form to a upload a file. We can impersonate a client form to upload files in Go as well.
```Go
package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"os"
)
func postFile(filename string, targetUrl string) error {
bodyBuf := &bytes.Buffer{}
bodyWriter := multipart.NewWriter(bodyBuf)
// this step is very important
fileWriter, err := bodyWriter.CreateFormFile("uploadfile", filename)
if err != nil {
fmt.Println("error writing to buffer")
return err
}
// open file handle
fh, err := os.Open(filename)
if err != nil {
fmt.Println("error opening file")
return err
}
defer fh.Close()
//iocopy
_, err = io.Copy(fileWriter, fh)
if err != nil {
return err
}
contentType := bodyWriter.FormDataContentType()
bodyWriter.Close()
resp, err := http.Post(targetUrl, contentType, bodyBuf)
if err != nil {
return err
}
defer resp.Body.Close()
resp_body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
fmt.Println(resp.Status)
fmt.Println(string(resp_body))
return nil
}
// sample usage
func main() {
target_url := "http://localhost:9090/upload"
filename := "./astaxie.pdf"
postFile(filename, target_url)
}
```
The above example shows you how to use a client to upload files. It uses `multipart.Write` to write files into cache and sends them to the server through the POST method.
If you have other fields that need to write into data, like username, call `multipart.WriteField` as needed.
## Links
- [Directory](preface.md)
- Previous section: [Duplicate submissions](04.4.md)
- Next section: [Summary](04.6.md)
# 4.6 Summary
In this chapter, we mainly learned how to process form data in Go through several examples like logging in users and uploading files. We also emphasized that validating user data is extremely important for website security, and we used one section to talk about how to filter data with regular expressions.
I hope that you now know more about the communication process between client and server.
## Links
- [Directory](preface.md)
- Previous section: [File upload](04.5.md)
- Next chapter: [Database](05.0.md)
# 5 Database
For web developers, the database is at the core of web development. You can save almost anything into a database and query or update data inside it, like user information, products or news articles.
Go doesn't provide any database drivers, but it does have a driver interface defined in the `database/sql` package. People can develop database drivers based on that interface. In section 5.1, we are going to talk about database driver interface design in Go. In sections 5.2 to 5.4, I will introduce some SQL database drivers to you. In section 5.5, I will present the ORM that I have developed which is based on the `database/sql` interface standard. It is compatible with most drivers that have implemented the `database/sql` interface, and it makes it easy to access databases idiomatically in Go.
NoSQL has been a hot topic in recent years. More websites are deciding to use NoSQL databases as their main database instead of just for the purpose of caching. I will introduce you to two NoSQL databases, which are MongoDB and Redis, in section 5.6.
## Links
- [Directory](preface.md)
- Previous Chapter: [Chapter 4 Summary](04.6.md)
- Next section: [database/sql interface](05.1.md)
# 5.1 database/sql interface
Go doesn't provide any official database drivers, unlike other languages like PHP which do. However, it does have some database driver interface standards for developers to develop database drivers with. The advantage is that if your code is developed according to these interface standards, you will not need to change any code if your database changes. Let's see what these database interface standards are.
## sql.Register
This function is in the `database/sql` package for registering database drivers when you use third-party database drivers. All of these should call the `Register(name string, driver driver.Driver)` function in `init()` in order to register themselves.
Let's take a look at the corresponding mymysql and sqlite3 driver code:
```Go
//https://github.com/mattn/go-sqlite3 driver
func init() {
sql.Register("sqlite3", &SQLiteDriver{})
}
//https://github.com/mikespook/mymysql driver
// Driver automatically registered in database/sql
var d = Driver{proto: "tcp", raddr: "127.0.0.1:3306"}
func init() {
Register("SET NAMES utf8")
sql.Register("mymysql", &d)
}
```
We see that all third-party database drivers implement this function to register themselves, and Go uses a map to save user drivers inside of `database/sql`.
```Go
var drivers = make(map[string]driver.Driver)
drivers[name] = driver
```
Therefore, this registration function can register as many drivers as you may require, each with different names.
We always see the following code when we use third-party drivers:
```Go
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
```
Here, the underscore (also known as a 'blank') `_` can be quite confusing for many beginners, but this is a great feature in Go. We already know that this underscore identifier is used for discarding values from function returns, and also that you must use all packages that you've imported in your code in Go. So when the blank is used with import, it means that you need to execute the init() function of that package without directly using it, which is a perfect fit for the use-case of registering database drivers.
## driver.Driver
`Driver` is an interface containing an `Open(name string)` method that returns a `Conn` interface.
```Go
type Driver interface {
Open(name string) (Conn, error)
}
```
This is a one-time Conn, which means it can only be used once per goroutine. The following code will cause errors to occur:
```Go
...
go goroutineA (Conn) // query
go goroutineB (Conn) // insert
...
```
Because Go has no idea which goroutine does which operation, the query operation may get the result of the insert operation, and vice-versa.
All third-party drivers should have this function to parse the name of Conn and return the correct results.
## driver.Conn
This is a database connection interface with some methods, and as i've said above, the same Conn can only be used once per goroutine.
```Go
type Conn interface {
Prepare(query string) (Stmt, error)
Close() error
Begin() (Tx, error)
}
```
- `Prepare` returns the prepare status of corresponding SQL commands for querying and deleting, etc.
- `Close` closes the current connection and cleans resources. Most third-party drivers implement some kind of connection pool, so you don't need to cache connections which can cause unexpected errors.
- `Begin` returns a Tx that represents a transaction handle. You can use it for querying, updating, rolling back transactions, etc.
## driver.Stmt
This is a ready status that corresponds with Conn, so it can only be used once per goroutine (as is the case with Conn).
```Go
type Stmt interface {
Close() error
NumInput() int
Exec(args []Value) (Result, error)
Query(args []Value) (Rows, error)
}
```
- `Close` closes the current connection but still returns row data if it is executing a query operation.
- `NumInput` returns the number of obligate arguments. Database drivers should check their caller's arguments when the result is greater than 0, and it returns -1 when database drivers don't know any obligate argument.
- `Exec` executes the `update/insert` SQL commands prepared in `Prepare`, returns `Result`.
- `Query` executes the `select` SQL command prepared in `Prepare`, returns row data.
## driver.Tx
Generally, transaction handles only have submit or rollback methods, and database drivers only need to implement these two methods.
```Go
type Tx interface {
Commit() error
Rollback() error
}
```
## driver.Execer
This is an optional interface.
```Go
type Execer interface {
Exec(query string, args []Value) (Result, error)
}
```
If the driver doesn't implement this interface, when you call DB.Exec, it will automatically call Prepare, then return Stmt. After that it executes the Exec method of Stmt, then closes Stmt.
## driver.Result
This is the interface for results of `update/insert` operations.
```Go
type Result interface {
LastInsertId() (int64, error)
RowsAffected() (int64, error)
}
```
- `LastInsertId` returns auto-increment Id number after a database insert operation.
- `RowsAffected` returns rows that were affected by query operations.
## driver.Rows
This is the interface for the result of a query operation.
```Go
type Rows interface {
Columns() []string
Close() error
Next(dest []Value) error
}
```
- `Columns` returns field information of database tables. The slice has a one-to-one correspondence with SQL query fields only, and does not return all fields of that database table.
- `Close` closes Rows iterator.
- `Next` returns next data and assigns to dest, converting all strings into byte arrays, and gets io.EOF error if no more data is available.
## driver.RowsAffected
This is an alias of int64, but it implements the Result interface.
```Go
type RowsAffected int64
func (RowsAffected) LastInsertId() (int64, error)
func (v RowsAffected) RowsAffected() (int64, error)
```
## driver.Value
This is an empty interface that can contain any kind of data.
```Go
type Value interface{}
```
The Value must be something that drivers can operate on or nil, so it should be one of the following types:
```Go
int64
float64
bool
[]byte
string [*] Except Rows.Next which cannot return string
time.Time
```
## driver.ValueConverter
This defines an interface for converting normal values to driver.Value.
```Go
type ValueConverter interface {
ConvertValue(v interface{}) (Value, error)
}
```
This interface is commonly used in database drivers and has many useful features:
- Converts driver.Value to a corresponding database field type, for example converts int64 to uint16.
- Converts database query results to driver.Value.
- Converts driver.Value to a user defined value in the `scan` function.
## driver.Valuer
This defines an interface for returning driver.Value.
```Go
type Valuer interface {
Value() (Value, error)
}
```
Many types implement this interface for conversion between driver.Value and itself.
At this point, you should know a bit about developing database drivers in Go. Once you can implement interfaces for operations like add, delete, update, etc., there are only a few problems left related to communicating with specific databases.
## database/sql
database/sql defines even more high-level methods on top of database/sql/driver for more convenient database operations, and it suggests that you implement a connection pool.
```Go
type DB struct {
driver driver.Driver
dsn string
mu sync.Mutex // protects freeConn and closed
freeConn []driver.Conn
closed bool
}
```
As you can see, the `Open` function returns a DB that has a freeConn, and this is a simple connection pool. Its implementation is very simple and ugly. It uses `defer db.putConn(ci, err)` in the Db.prepare function to put a connection into the connection pool. Everytime you call the Conn function, it checks the length of freeConn. If it's greater than 0, that means there is a reusable connection and it directly returns to you. Otherwise it creates a new connection and returns.
## Links
- [Directory](preface.md)
- Previous section: [Database](05.0.md)
- Next section: [MySQL](05.2.md)
# 5.2 MySQL
The LAMP stack has been very popular on the internet in recent years, and the M in LAMP stand for MySQL. MySQL is famous because it's open source and easy to use. As such, it has become the de-facto database in the back-ends of many websites.
## MySQL drivers
There are a couple of drivers that support MySQL in Go. Some of them implement the `database/sql` interface, and others use their own interface standards.
- [https://github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) supports `database/sql`, written in pure Go.
- [https://github.com/ziutek/mymysql](https://github.com/ziutek/mymysql) supports `database/sql` and user defined interfaces, written in pure Go.
I'll use the first driver in the following examples (I use this one in my personal projects too), and I also recommend that you use it for the following reasons:
- It's a new database driver and supports more features.
- It fully supports `database/sql` interface standards.
- Supports keep-alive, long connections with thread-safety.
## Samples
In the following sections, I'll use the same database table structure for different databases, then create SQL as follows:
```sql
CREATE TABLE `userinfo` (
`uid` INT(10) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(64) NULL DEFAULT NULL,
`department` VARCHAR(64) NULL DEFAULT NULL,
`created` DATE NULL DEFAULT NULL,
PRIMARY KEY (`uid`)
);
```
The following example shows how to operate on a database based on the `database/sql` interface standards.
```Go
package main
import (
_ "github.com/go-sql-driver/mysql"
"database/sql"
"fmt"
)
func main() {
db, err := sql.Open("mysql", "astaxie:astaxie@/test?charset=utf8")
checkErr(err)
// insert
stmt, err := db.Prepare("INSERT userinfo SET username=?,department=?,created=?")
checkErr(err)
res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
checkErr(err)
id, err := res.LastInsertId()
checkErr(err)
fmt.Println(id)
// update
stmt, err = db.Prepare("update userinfo set username=? where uid=?")
checkErr(err)
res, err = stmt.Exec("astaxieupdate", id)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect)
// query
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
for rows.Next() {
var uid int
var username string
var department string
var created string
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println(uid)
fmt.Println(username)
fmt.Println(department)
fmt.Println(created)
}
rows.Close()
// delete
stmt, err = db.Prepare("delete from userinfo where uid=?")
checkErr(err)
res, err = stmt.Exec(id)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect)
db.Close()
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
```
Let me explain a few of the important functions here:
- `sql.Open()` opens a registered database driver. The Go-MySQL-Driver registered the mysql driver here. The second argument is the DSN (Data Source Name) that defines information pertaining to the database connection. It supports following formats:
user@unix(/path/to/socket)/dbname?charset=utf8
user:password@tcp(localhost:5555)/dbname?charset=utf8
user:password@/dbname
user:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname
- `db.Prepare()` returns a SQL operation that is going to be executed. It also returns the execution status after executing SQL.
- `db.Query()` executes SQL and returns a Rows result.
- `stmt.Exec()` executes SQL that has been prepared and stored in Stmt.
Note that we use the format `=?` to pass arguments. This is necessary for preventing SQL injection attacks.
## Links
- [Directory](preface.md)
- Previous section: [database/sql interface](05.1.md)
- Next section: [SQLite](05.3.md)
# 5.3 SQLite
SQLite is an open source, embedded relational database. It has a self-contained, zero-configuration and transaction-supported database engine. Its characteristics are highly portable, easy to use, compact, efficient and reliable. In most of cases, you only need a binary file of SQLite to create, connect and operate a database. If you are looking for an embedded database solution, SQLite is worth considering. You can say SQLite is the open source version of Access.
## SQLite drivers
There are many database drivers for SQLite in Go, but many of them do not support the `database/sql` interface standards.
- [https://github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) supports `database/sql`, based on cgo.
- [https://github.com/feyeleanor/gosqlite3](https://github.com/feyeleanor/gosqlite3) doesn't support `database/sql`, based on cgo.
- [https://github.com/phf/go-sqlite3](https://github.com/phf/go-sqlite3) doesn't support `database/sql`, based on cgo.
The first driver is the only one that supports the `database/sql` interface standard in its SQLite driver, so I use this in my projects -it will make it easy to migrate my code in the future if I need to.
## Samples
We create the following SQL:
```sql
CREATE TABLE `userinfo` (
`uid` INTEGER PRIMARY KEY AUTOINCREMENT,
`username` VARCHAR(64) NULL,
`department` VARCHAR(64) NULL,
`created` DATE NULL
);
```
An example:
```Go
package main
import (
"database/sql"
"fmt"
"time"
_ "github.com/mattn/go-sqlite3"
)
func main() {
db, err := sql.Open("sqlite3", "./foo.db")
checkErr(err)
// insert
stmt, err := db.Prepare("INSERT INTO userinfo(username, department, created) values(?,?,?)")
checkErr(err)
res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
checkErr(err)
id, err := res.LastInsertId()
checkErr(err)
fmt.Println(id)
// update
stmt, err = db.Prepare("update userinfo set username=? where uid=?")
checkErr(err)
res, err = stmt.Exec("astaxieupdate", id)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect)
// query
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
var uid int
var username string
var department string
var created time.Time
for rows.Next() {
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println(uid)
fmt.Println(username)
fmt.Println(department)
fmt.Println(created)
}
rows.Close() //good habit to close
// delete
stmt, err = db.Prepare("delete from userinfo where uid=?")
checkErr(err)
res, err = stmt.Exec(id)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect)
db.Close()
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
```
You may have noticed that the code is almost the same as in the previous section, and that we only changed the name of the registered driver and called `sql.Open` to connect to SQLite in a different way.
Note that sometimes you can't use the `for` statement because you don't have more than one row, then you can use the `if` statement
```Go
if rows.Next() {
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println(uid)
fmt.Println(username)
fmt.Println(department)
fmt.Println(created)
}
```
Also you have to do a `rows.Next()`, without using that you can't fetch data in the `Scan` function.
Transactions
===============
The above example shows how you fetch data from the database, but when you want to write a web application then it will not only be necessary to fetch data from the db but it will also be required to write data into it. For that purpose, you should use transactions because for various reasons, such as having multiple go routines which access the database, the database might get locked. This is undesirable in your web application and the use of transactions is effective in ensuring your database activities either pass or fail completely depending on circumstances. It is clear that using transactions can prevent a lot of things from going wrong with the web app.
```Go
trashSQL, err := database.Prepare("update task set is_deleted='Y',last_modified_at=datetime() where id=?")
if err != nil {
fmt.Println(err)
}
tx, err := database.Begin()
if err != nil {
fmt.Println(err)
}
_, err = tx.Stmt(trashSQL).Exec(id)
if err != nil {
fmt.Println("doing rollback")
tx.Rollback()
} else {
tx.Commit()
}
```
As it is clear from the above block of code, you first prepare a statement, after which you execute it, depending on the output of that execution then you either roll it back or commit it.
As a final note on this section, there is a useful SQLite management tool available: [http://sqlitebrowser.org](http://sqlitebrowser.org)
## Links
- [Directory](preface.md)
- Previous section: [MySQL](05.2.md)
- Next section: [PostgreSQL](05.4.md)
# 5.4 PostgreSQL
PostgreSQL is an object-relational database management system available for many platforms including Linux, FreeBSD, Solaris, Microsoft Windows and Mac OS X. It is released under an MIT-style license, and is thus free and open source software. It's larger than MySQL because it's designed for enterprise usage as an alternative to Oracle. Postgresql is a good choice for enterprise type projects.
## PostgreSQL drivers
There are many database drivers available for PostgreSQL. Here are three examples of them:
- [https://github.com/lib/pq](https://github.com/lib/pq) supports `database/sql`, written in pure Go.
- [https://github.com/jbarham/gopgsqldriver](https://github.com/jbarham/gopgsqldriver) supports `database/sql`, written in pure Go.
- [https://github.com/lxn/go-pgsql](https://github.com/lxn/go-pgsql) supports `database/sql`, written in pure Go.
I will use the first one in the examples that follow.
## Samples
We create the following SQL:
```sql
CREATE TABLE userinfo
(
uid serial NOT NULL,
username character varying(100) NOT NULL,
department character varying(500) NOT NULL,
Created date,
CONSTRAINT userinfo_pkey PRIMARY KEY (uid)
)
WITH (OIDS=FALSE);
```
An example:
```Go
package main
import (
"database/sql"
"fmt"
_ "github.com/lib/pq"
"time"
)
const (
DB_USER = "postgres"
DB_PASSWORD = "postgres"
DB_NAME = "test"
)
func main() {
dbinfo := fmt.Sprintf("user=%s password=%s dbname=%s sslmode=disable",
DB_USER, DB_PASSWORD, DB_NAME)
db, err := sql.Open("postgres", dbinfo)
checkErr(err)
defer db.Close()
fmt.Println("# Inserting values")
var lastInsertId int
err = db.QueryRow("INSERT INTO userinfo(username,department,created) VALUES($1,$2,$3) returning uid;", "astaxie", "研发部门", "2012-12-09").Scan(&lastInsertId)
checkErr(err)
fmt.Println("last inserted id =", lastInsertId)
fmt.Println("# Updating")
stmt, err := db.Prepare("update userinfo set username=$1 where uid=$2")
checkErr(err)
res, err := stmt.Exec("astaxieupdate", lastInsertId)
checkErr(err)
affect, err := res.RowsAffected()
checkErr(err)
fmt.Println(affect, "rows changed")
fmt.Println("# Querying")
rows, err := db.Query("SELECT * FROM userinfo")
checkErr(err)
for rows.Next() {
var uid int
var username string
var department string
var created time.Time
err = rows.Scan(&uid, &username, &department, &created)
checkErr(err)
fmt.Println("uid | username | department | created ")
fmt.Printf("%3v | %8v | %6v | %6v\n", uid, username, department, created)
}
fmt.Println("# Deleting")
stmt, err = db.Prepare("delete from userinfo where uid=$1")
checkErr(err)
res, err = stmt.Exec(lastInsertId)
checkErr(err)
affect, err = res.RowsAffected()
checkErr(err)
fmt.Println(affect, "rows changed")
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
```
Note that PostgreSQL uses the `$1, $2` format instead of the `?` that MySQL uses, and it has a different DSN format in `sql.Open`.
Another thing is that the PostgreSQL driver does not support `sql.Result.LastInsertId()`.
So instead of this,
```Go
stmt, err := db.Prepare("INSERT INTO userinfo(username,departname,created) VALUES($1,$2,$3);")
res, err := stmt.Exec("astaxie", "研发部门", "2012-12-09")
fmt.Println(res.LastInsertId())
```
use `db.QueryRow()` and `.Scan()` to get the value for the last inserted id.
```Go
err = db.QueryRow("INSERT INTO TABLE_NAME values($1) returning uid;", VALUE1").Scan(&lastInsertId)
fmt.Println(lastInsertId)
```
## Links
- [Directory](preface.md)
- Previous section: [SQLite](05.3.md)
- Next section: [Develop ORM based on beedb](05.5.md)
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册