From cdaf20eb7fa1cebfcb9cd671e0225ad621e548a1 Mon Sep 17 00:00:00 2001 From: Anchor Date: Sun, 24 Aug 2014 16:24:49 -0700 Subject: [PATCH 01/20] fix some minor grammar issues --- en/eBook/01.3.md | 24 ++++++++++++------------ en/eBook/01.5.md | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/en/eBook/01.3.md b/en/eBook/01.3.md index e9a8d5b5..60e8b037 100644 --- a/en/eBook/01.3.md +++ b/en/eBook/01.3.md @@ -2,17 +2,17 @@ ## Go commands -Go language comes with a complete set of command operation tool, you can execute the command line `go` to see them: +The Go language comes with a complete set of command operation tools, you can execute the command line `go` to see them: ![](images/1.3.go.png?raw=true) Figure 1.3 Go command displays detailed information -These are all useful for us, let's see how to use some of them. +These are all useful for us. Let's see how to use some of them. ## go build -This command is for compiling tests, it will compile dependence packages if it's necessary. +This command is for compiling tests. It will compile dependence packages if it's necessary. - If the package is not the `main` package such as `mymath` in section 1.2, nothing will be generated after you executed `go build`. If you need package file `.a` in `$GOPATH/pkg`, use `go install` instead. - If the package is the `main` package, it will generate an executable file in the same folder. If you want the file to be generated in `$GOPATH/bin`, use `go install` or `go build -o ${PATH_HERE}/a.exe.` @@ -30,7 +30,7 @@ This command is for compiling tests, it will compile dependence packages if it's ## go clean -This command is for clean files that are generated by compilers, including following files. +This command is for cleaning files that are generated by compilers, including the following files. _obj/ // old directory of object, left by Makefiles _test/ // old directory of test, left by Makefiles @@ -43,17 +43,17 @@ This command is for clean files that are generated by compilers, including follo DIR.test(.exe) // generated by go test -c MAINFILE(.exe) // generated by go build MAINFILE.go -I usually use this command to clean my files before I upload my project to the Github, these are useful for local tests, but useless for version control. +I usually use this command to clean my files before I upload my project to the Github. These are useful for local tests, but useless for version control. ## go fmt -The people who are working with C/C++ should know that people are always arguing about code style between K&R-style and ANSI-style, which one is better. However in Go, there is only one code style which is forced to use. For example, you must put left brace in the end of the line, and can't put it in a single line, otherwise you will get compile errors! Fortunately, you don't have to remember these rules, `go fmt` does this job for you, just execute command `go fmt .go` in terminal. I don't use this command very much because IDEs usually execute this command automatically when you save source files, I will talk about IDEs more in next section. +The people who are working with C/C++ should know that people are always arguing about code style between K&R-style and ANSI-style, which one is better. However in Go, there is only one code style which is enforced. For example, you must put a left brace in the end of the line, and can't put it in a single line, otherwise you will get compile errors! Fortunately, you don't have to remember these rules. `go fmt` does this job for you. Just execute the command `go fmt .go` in terminal. I don't use this command very much because IDEs usually execute this command automatically when you save source files. I will talk about IDEs more in next section. We usually use `gofmt -w` instead of `go fmt`, the latter will not rewrite your source files after formatted code. `gofmt -w src` formats the whole project. ## go get -This command is for getting remote packages, it supports BitBucket, Github, Google Code, Launchpad so far. There are actually two things happening after we executed this command. The first thing is to download source code, then executes `go install`. Before you use this command, make sure you have installed related tools. +This command is for getting remote packages, it supports BitBucket, Github, Google Code, Launchpad so far. There are actually two things that happen after we executed this command. The first thing is to download the source code, then execute `go install`. Before you use this command, make sure you have installed all the related tools. BitBucket (Mercurial Git) Github (git) @@ -64,24 +64,24 @@ In order to use this command, you have to install these tools correctly. Don't f ## go install -This command compiles all packages and generate files, then move them to `$GOPATH/pkg` or `$GOPATH/bin`. +This command compiles all packages and generates files, then moves them to `$GOPATH/pkg` or `$GOPATH/bin`. ## go test -This command loads all files whose name include `*_test.go` and generate test files, then prints information looks like follows. +This command loads all files whose name include `*_test.go` and generates test files, then prints information that looks like the following. ok archive/tar 0.011s FAIL archive/zip 0.022s ok compress/gzip 0.033s ... -It tests all your test files as default, use command `go help testflag` for more details. +It tests all your test files by default, use command `go help testflag` for more details. ## go doc -Many people said that we don't need any third-party documentation for programming in Go(actually I've made a [CHM](https://github.com/astaxie/godoc) already), Go has a powerful tool to manage documentation by itself. +Many people said that we don't need any third-party documentation for programming in Go (actually I've made a [CHM](https://github.com/astaxie/godoc) already), Go has a powerful tool to manage documentation by itself. -So how to look up packages' information in documentation? If you want to get more details about package `builtin`, use command `go doc builtin`, and use command `go doc net/http` for package `http`. If you want to see more details about specific functions, use command `godoc fmt Printf`, and `godoc -src fmt Printf` to view source code. +So how do we look up package information in documentation? If you want to get more details about the package `builtin`, use command `go doc builtin`, and use command `go doc net/http` for package `http`. If you want to see more details about specific functions, use command `godoc fmt Printf`, and `godoc -src fmt Printf` to view source code. Execute command `godoc -http=:8080`, then open `127.0.0.1:8080` in your browsers, you should see a localized golang.org. It can not only show the standard packages' information, but also packages in your `$GOPATH/pkg`. It's great for people who are suffering from the Great Firewall of China. diff --git a/en/eBook/01.5.md b/en/eBook/01.5.md index 351687d0..adca77c2 100644 --- a/en/eBook/01.5.md +++ b/en/eBook/01.5.md @@ -1,9 +1,9 @@ # 1.5 Summary -In this chapter, we talked about how to install Go through three ways, including from source code, standard package and third-party tools. Then we showed you how to configure Go development environment, mainly about `$GOPATH`. After that, we introduced the steps in compile and deployment of Go programs. Then we talked about Go commands, these commands including compile, install, format, test. Finally, there are many powerful tools to develop Go programs, such as LiteIDE, Sublime Text, Vim, Emacs, Eclipse, IntelliJ IDEA, etc. You can choose any one you like exploring the world of Go. +In this chapter, we talked about how to install Go through using three different methods: including from source code, standard package and via third-party tools. Then we showed you how to configure the Go development environment, mainly covering how to setup your `$GOPATH`. After that, we introduced the steps in compilation and deployment of Go programs. We then covered Go commands, including the compile, install, format and test commands. Finally, there are many powerful tools to develop Go programs such as LiteIDE, Sublime Text, Vim, Emacs, Eclipse, IntelliJ IDEA, etc. You can choose any one you like exploring the world of Go. ## Links - [Directory](preface.md) - Previous section: [Go development tools](01.4.md) -- Next chapter: [Go basic knowledge](02.0.md) \ No newline at end of file +- Next chapter: [Go basic knowledge](02.0.md) From 3efe5b8e43f3b1d46f4c6f10e7d9604f94af1c86 Mon Sep 17 00:00:00 2001 From: Anchor Date: Tue, 26 Aug 2014 18:10:03 -0700 Subject: [PATCH 02/20] Minor grammar and typo fixes for 2.0, 2.1 and 2.2 --- en/eBook/02.0.md | 6 +-- en/eBook/02.1.md | 10 ++-- en/eBook/02.2.md | 132 +++++++++++++++++++++++------------------------ 3 files changed, 73 insertions(+), 75 deletions(-) diff --git a/en/eBook/02.0.md b/en/eBook/02.0.md index 3ef864b1..0cae98b6 100644 --- a/en/eBook/02.0.md +++ b/en/eBook/02.0.md @@ -1,6 +1,6 @@ # 2 Go basic knowledge -Go is a compiled system programming language, and it belongs to the C-family. However, its compilation speed is much faster than other C-family languages. It has only 25 keywords, even less than 26 English letters! Let's take a look at these keywords before we get started. +Go is a compiled system programming language, and it belongs to the C-family. However, its compilation speed is much faster than other C-family languages. It has only 25 keywords..., even less than 26 English letters! Let's take a look at these keywords before we get started. break default func interface select case defer go map struct @@ -8,10 +8,10 @@ Go is a compiled system programming language, and it belongs to the C-family. Ho const fallthrough if range type continue for import return var -In this chapter, I'm going to teach you some basic Go knowledge. You will find how concise the Go programming language is, and the beautiful design of the language. Programming can be very fun in Go. After we complete this chapter, you'll be familiar with the above keywords. +In this chapter, I'm going to teach you some basic Go knowledge. You will find out how concise the Go programming language is, and the beautiful design of the language. Programming can be very fun in Go. After we complete this chapter, you'll be familiar with the above keywords. ## Links - [Directory](preface.md) - Previous chapter: [Chapter 1 Summary](01.5.md) -- Next section: ["Hello, Go"](02.1.md) \ No newline at end of file +- Next section: ["Hello, Go"](02.1.md) diff --git a/en/eBook/02.1.md b/en/eBook/02.1.md index 6ad095ce..e3c14dce 100644 --- a/en/eBook/02.1.md +++ b/en/eBook/02.1.md @@ -1,10 +1,10 @@ # 2.1 Hello, Go -Before we start building an application in Go, we need to learn how to write a simple program. It's like you cannot build a building without knowing how to build its foundation. Therefore, we are going to learn the basic syntax to run some simple programs in this section. +Before we start building an application in Go, we need to learn how to write a simple program. You can't expect to build a building without first knowing how to build its foundation. Therefore, we are going to learn the basic syntax to run some simple programs in this section. ## Program -According to international practice, before you learn how to programming in some languages, you may want to know how to write a program to print "Hello world". +According to international practice, before you learn how to program in some languages, you will want to know how to write a program to print "Hello world". Are you ready? Let's Go! @@ -26,7 +26,7 @@ One thing that you should know in the first is that Go programs are composed by `package` (In this case is `package main`) tells us this source file belongs to `main` package, and the keyword `main` tells us this package will be compiled to a program instead of package files whose extensions are `.a`. -Every executable program has one and only one `main` package, and you need an entry function called `main` without any argument and return value in the `main` package. +Every executable program has one and only one `main` package, and you need an entry function called `main` without any arguments or return values in the `main` package. In order to print `Hello, world…`, we called a function called `Printf`. This function is coming from `fmt` package, so we import this package in the third line of source code, which is `import "fmt"` @@ -44,10 +44,10 @@ You may notice that the example above contains many non-ASCII characters. The pu ## Conclusion -Go uses `package` (like modules in Python) to organize programs. The function `main.main()` (this function must be in the `main` package) is the entry point of any program. Go supports UTF-8 characters because one of the creators of Go is a creator of UTF-8, so Go supports multi-language from the time it was born. +Go uses `package` (like modules in Python) to organize programs. The function `main.main()` (this function must be in the `main` package) is the entry point of any program. Go supports UTF-8 characters because one of the creators of Go is a creator of UTF-8, so Go supports multiple languages from the time it was born. ## Links - [Directory](preface.md) - Previous section: [Go basic knowledge](02.0.md) -- Next section: [Go foundation](02.2.md) \ No newline at end of file +- Next section: [Go foundation](02.2.md) diff --git a/en/eBook/02.2.md b/en/eBook/02.2.md index 261447f5..0a13f419 100644 --- a/en/eBook/02.2.md +++ b/en/eBook/02.2.md @@ -4,9 +4,9 @@ In this section, we are going to teach you how to define constants, variables wi ## Define variables -There are many forms of syntax that can define variables in Go. +There are many forms of syntax that can use to define variables in Go. -Use keyword `var` is the basic form to define variables, notice that Go puts variable type `after` variable name. +The keyword `var` is the basic form to define variables, notice that Go puts the variable type `after` the variable name. // define a variable with name “variableName” and type "type" var variableName type @@ -29,7 +29,7 @@ Define multiple variables with initial values. */ var vname1, vname2, vname3 type = v1, v2, v3 -Do you think it's too tedious to define variables use the way above? Don't worry because Go team found this problem as well. Therefore if you want to define variables with initial values, we can just omit variable type, so the code will look like this: +Do you think it's too tedious to define variables use the way above? Don't worry because the Go team has found this to be aproblem. Therefore if you want to define variables with initial values, we can just omit the variable type, so the code will look like this instead: /* Define three variables with type "type", and initialize their values. @@ -37,7 +37,7 @@ Do you think it's too tedious to define variables use the way above? Don't worry */ var vname1, vname2, vname3 = v1, v2, v3 -Well, I know this is still not simple enough for you, so do I. Let's see how we fix it. +Well, I know this is still not simple enough for you. Let's see how we fix it. /* Define three variables with type "type", and initialize their values. @@ -45,13 +45,13 @@ Well, I know this is still not simple enough for you, so do I. Let's see how we */ vname1, vname2, vname3 := v1, v2, v3 -Now it looks much better. Use `:=` to replace `var` and `type`, this is called brief statement. But wait, it has one limitation that this form can only be used inside of functions. You will get compile errors if you try to use it outside of function bodies. Therefore, we usually use `var` to define global variables, and we can use this brief statement in `var()`. +Now it looks much better. Use `:=` to replace `var` and `type`, this is called a brief statement. But wait, it has one limitation: this form can only be used inside of functions. You will get compile errors if you try to use it outside of function bodies. Therefore, we usually use `var` to define global variables and we can use this brief statement in `var()`. -`_` (blank) is a special name of variable, any value that is given to it will be ignored. For example, we give `35` to `b`, and discard `34`.( ***This example just show you how it works. It looks useless here because we often use this symbol when we get function return values.*** ) +`_` (blank) is a special variable name. Any value that is given to it will be ignored. For example, we give `35` to `b`, and discard `34`.( ***This example just show you how it works. It looks useless here because we often use this symbol when we get function return values.*** ) _, b := 34, 35 -If you don't use any variable that you defined in the program, compiler will give you compile errors. Try to compile following code, see what happens. +If you don't use any variable that you defined in the program, the compiler will give you compile errors. Try to compile following code, and see what happens. package main @@ -61,7 +61,7 @@ If you don't use any variable that you defined in the program, compiler will giv ## Constants -So-called constants are the values that are determined in the compile time, and you cannot change them during runtime. In Go, you can use number, boolean or string as type of constants. +So-called constants are the values that are determined during compile time and you cannot change them during runtime. In Go, you can use number, boolean or string as types of constants. Define constants as follows. @@ -93,7 +93,7 @@ In Go, we use `bool` to define a variable as boolean type, the value can only be ### Numerical types -Integer types including signed and unsigned integer types. Go has `int` and `uint` at the same time, they have same length, but specific length depends on your operating system. They use 32-bit in 32-bit operating systems, and 64-bit in 64-bit operating systems. Go also has types that have specific length including `rune`, `int8`, `int16`, `int32`, `int64`, `byte`, `uint8`, `uint16`, `uint32`, `uint64`. Note that `rune` is alias of `int32` and `byte` is alias of `uint8`. +Integer types includ both signed and unsigned integer types. Go has `int` and `uint` at the same time, they have same length, but specific length depends on your operating system. They use 32-bit in 32-bit operating systems, and 64-bit in 64-bit operating systems. Go also has types that have specific length including `rune`, `int8`, `int16`, `int32`, `int64`, `byte`, `uint8`, `uint16`, `uint32`, `uint64`. Note that `rune` is alias of `int32` and `byte` is alias of `uint8`. One important thing you should know that you cannot assign values between these types, this operation will cause compile errors. @@ -103,11 +103,11 @@ One important thing you should know that you cannot assign values between these c := a + b -Although int has longer length than uint8, and has same length as int32, but you cannot assign values between them. ( ***c will be asserted as type `int` here*** ) +Although int has a longer length than uint8, and has the same length as int32, you cannot assign values between them. ( ***c will be asserted as type `int` here*** ) -Float types have `float32` and `float64`, and no type called `float`, latter one is default type if you use brief statement. +Float types have the `float32` and `float64` types and no type called `float`. The latter one is the default type if using brief statement. -That's all? No! Go has complex number as well. `complex128` (with a 64-bit real and 64-bit imaginary part)is default type, if you need smaller type, there is one called `complex64` (with a 32-bit real and 32-bit imaginary part). Its form is `RE+IMi`, where `RE` is real part and `IM` is imaginary part, the last `i` is imaginary number. There is a example of complex number. +That's all? No! Go support complex numbers as well. `complex128` (with a 64-bit real and 64-bit imaginary part) is the default type, if you need a smaller type, there is one called `complex64` (with a 32-bit real and 32-bit imaginary part). Its form is `RE+IMi`, where `RE` is real part and `IM` is imaginary part, the last `i` is imaginary number. There is a example of complex number. var c complex64 = 5+5i //output: (5+5i) @@ -115,7 +115,7 @@ That's all? No! Go has complex number as well. `complex128` (with a 64-bit real ### String -We just talked about that Go uses UTF-8 character set. Strings are represented by double quotes `""` or backtracks ``` `. +We just talked about how Go uses the UTF-8 character set. Strings are represented by double quotes `""` or backtracks ``` `. // sample code var frenchHello string // basic form to define string @@ -126,7 +126,7 @@ We just talked about that Go uses UTF-8 character set. Strings are represented b frenchHello = "Bonjour" // basic form of assign values } -It's impossible to change string values by index, you will get errors when you compile following code. +It's impossible to change string values by index. You will get errors when you compile following code. var s string = "hello" s[0] = 'c' @@ -139,7 +139,7 @@ What if I really want to change just one character in a string? Try following co s2 := string(c) // convert back to string type fmt.Printf("%s\n", s2) -You can use operator `+` to combine two strings. +You use the `+` operator to combine two strings. s := "hello," m := " world" @@ -170,7 +170,7 @@ Go has one `error` type for purpose of dealing with error messages. There is als ### Underlying data structure -The following picture comes from a article about [Go data structure](http://research.swtch.com/godata) in [Russ Cox Blog](http://research.swtch.com/). As you can see, Go gives blocks in memory to store data. +The following picture comes from an article about [Go data structure](http://research.swtch.com/godata) in [Russ Cox Blog](http://research.swtch.com/). As you can see, Go utilizes blocks of memory to store data. ![](images/2.2.basic.png?raw=true) @@ -180,7 +180,7 @@ Figure 2.1 Go underlying data structure ### Define by group -If you want to define multiple constants, variables or import packages, you can use group form. +If you want to define multiple constants, variables or import packages, you can use the group form. Basic form. @@ -218,13 +218,13 @@ Unless you assign the value of constant is `iota`, the first value of constant i ### iota enumerate -Go has one keyword `iota`, this keyword is to make `enum`, it begins with `0`, increased by `1`. +Go has one keyword called `iota`, this keyword is to make `enum`, it begins with `0`, increased by `1`. const( x = iota // x == 0 y = iota // y == 1 z = iota // z == 2 - w // If there is no expression after constants name, it uses the last expression, so here is saying w = iota implicitly. Therefore w == 3, and y and x both can omit "= iota" as well. + w // If there is no expression after the constants name, it uses the last expression, so it's saying w = iota implicitly. Therefore w == 3, and y and x both can omit "= iota" as well. ) const v = iota // once iota meets keyword `const`, it resets to `0`, so v = 0. @@ -237,8 +237,8 @@ Go has one keyword `iota`, this keyword is to make `enum`, it begins with `0`, i The reason that Go is concise because it has some default behaviors. -- Any variable starts with capital letter means it will be exported, private otherwise. -- Same rule for functions and constants, no `public` or `private` keyword exists in Go. +- Any variable that begins with a capital letter means it will be exported, private otherwise. +- The same rule applies for functions and constants, no `public` or `private` keyword exists in Go. ## array, slice, map @@ -248,7 +248,7 @@ The reason that Go is concise because it has some default behaviors. var arr [n]type -in `[n]type`, `n` is the length of array, `type` is the type of its elements. Like other languages, we use `[]` to get or set element values in array. +in `[n]type`, `n` is the length of the array, `type` is the type of its elements. Like other languages, we use `[]` to get or set element values within arrays. var arr [10]int // an array of type int arr[0] = 42 // array is 0-based @@ -256,22 +256,22 @@ in `[n]type`, `n` is the length of array, `type` is the type of its elements. Li fmt.Printf("The first element is %d\n", arr[0]) // get element value, it returns 42 fmt.Printf("The last element is %d\n", arr[9]) //it returns default value of 10th element in this array, which is 0 in this case. -Because length is a part of array type, `[3]int` and `[4]int` are different types, so we cannot change length of arrays. When you use arrays as arguments, functions get their copies instead of references! If you want to use reference, you may want to use `slice` which we will talk about latter. +Because length is a part of the array type, `[3]int` and `[4]int` are different types, so we cannot change the length of arrays. When you use arrays as arguments, functions get their copies instead of references! If you want to use reference, you may want to use `slice`, which we'll talk about later. It's possible to use `:=` when you define arrays. - a := [3]int{1, 2, 3} // define a int array with 3 elements + a := [3]int{1, 2, 3} // define an int array with 3 elements - b := [10]int{1, 2, 3} // define a int array with 10 elements, and first three are assigned, rest of them use default value 0. + b := [10]int{1, 2, 3} // define a int array with 10 elements, of which the first three are assigned. The rest of them use the default value 0. - c := [...]int{4, 5, 6} // use `…` replace with number of length, Go will calculate it for you. + c := [...]int{4, 5, 6} // use `…` to replace the length paramter and Go will calculate it for you. -You may want to use arrays as arrays' elements, let's see how to do it. +You may want to use arrays as arrays' elements. Let's see how to do this. // define a two-dimensional array with 2 elements, and each element has 4 elements. doubleArray := [2][4]int{[4]int{1, 2, 3, 4}, [4]int{5, 6, 7, 8}} - // You can write about declaration in a shorter way. + // The declaration can be written more concisely as follows. easyArray := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}} Array underlying data structure. @@ -282,34 +282,34 @@ Figure 2.2 Multidimensional array mapping relationship ### slice -In many situations, array is not a good choice. For example, we don't know how long the array will be when we define it, so we need "dynamic array". This is called `slice` in Go. +In many situations, the array type is not a good choice -for instance when we don't know how long the array will be when we define it. Thus, we need a "dynamic array". This is called `slice` in Go. -`slice` is not really `dynamic array`, it's a reference type. `slice` points to an underlying `array`, its declaration is similar to `array`, but doesn't need length. +`slice` is not really a `dynamic array`. It's a reference type. `slice` points to an underlying `array` whose declaration is similar to `array`, but doesn't need length. - // just like to define array, but no length this time + // just like defining an array, but this time, we exclude the length. var fslice []int Then we define a `slice`, and initialize its data. slice := []byte {'a', 'b', 'c', 'd'} -`slice` can redefine from exists slices or arrays. `slice` use `array[i:j]` to slice, where `i` is start index and `j` is end index, but notice that `array[j]` will not be sliced, now the length of slice is `j-i`. +`slice` can redefine existing slices or arrays. `slice` uses `array[i:j]` to slice, where `i` is the start index and `j` is end index, but notice that `array[j]` will not be sliced since the length of the slice is `j-i`. - // define a slice with 10 elements which types are byte + // define a slice with 10 elements whose types are bytes var ar = [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'} // define two slices with type []byte var a, b []byte - // a points to elements from 3rd to 5th in array ar. + // 'a' points to elements from 3rd to 5th in array ar. a = ar[2:5] - // now a has elements ar[2],ar[3] and ar[4] + // now 'a' has elements ar[2],ar[3] and ar[4] - // b is another slice of array ar + // 'b' is another slice of array ar b = ar[3:5] - // now b has elements ar[3] and ar[4] + // now 'b' has elements ar[3] and ar[4] -Notice that differences between `slice` and `array` when you define them. We use `[…]` let Go calculates length but use `[]` to define slice only. +Notice the differences between `slice` and `array` when you define them. We use `[…]` to let Go calculate length but use `[]` to define slice only. Their underlying data structure. @@ -320,10 +320,10 @@ Figure 2.3 Correspondence between slice and array slice has some convenient operations. - `slice` is 0-based, `ar[:n]` equals to `ar[0:n]` -- Second index will be the length of `slice` if you omit it, `ar[n:]` equals to `ar[n:len(ar)]`. +- The second index will be the length of `slice` if omitted, `ar[n:]` equals to `ar[n:len(ar)]`. - You can use `ar[:]` to slice whole array, reasons are explained in first two statements. -More examples about `slice` +More examples pertaining to `slice` // define an array var array = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'} @@ -339,21 +339,21 @@ More examples about `slice` aSlice = array[3:7] // aSlice has elements d,e,f,g,len=4,cap=7 bSlice = aSlice[1:3] // bSlice contains aSlice[1], aSlice[2], so it has elements e,f bSlice = aSlice[:3] // bSlice contains aSlice[0], aSlice[1], aSlice[2], so it has d,e,f - bSlice = aSlice[0:5] // slcie could be expanded in range of cap, now bSlice contains d,e,f,g,h + bSlice = aSlice[0:5] // slice could be expanded in range of cap, now bSlice contains d,e,f,g,h bSlice = aSlice[:] // bSlice has same elements as aSlice does, which are d,e,f,g -`slice` is reference type, so one of them changes will affect others. For instance, `aSlice` and `bSlice` above, if you change value of element in `aSlice`, `bSlice` will be changed as well. +`slice` is a reference type, so any changes will affect other variables pointing to the same slice or array. For instance, in the case of `aSlice` and `bSlice` above, if you change the value of an element in `aSlice`, `bSlice` will be changed as well. -`slice` is like a struct by definition, it contains 3 parts. +`slice` is like a struct by definition and it contains 3 parts. - A pointer that points to where `slice` starts. -- length of `slice`. +- The length of `slice`. - Capacity, the length from start index to end index of `slice`. Array_a := [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'} Slice_a := Array_a[2:5] -Underlying data structure of code above as follows. +The underlying data structure of the code above as follows. ![](images/2.2.slice2.png?raw=true) @@ -361,20 +361,20 @@ Figure 2.4 Array information of slice There are some built-in functions for slice. -- `len` gets length of `slice`. -- `cap` gets maximum length of `slice` +- `len` gets the length of `slice`. +- `cap` gets the maximum length of `slice` - `append` appends one or more elements to `slice`, and returns `slice` . -- `copy` copies elements from one slice to the other, and returns number of elements were copied. +- `copy` copies elements from one slice to the other, and returns the number of elements that were copied. -Attention: `append` will change array that `slice` points to, and affect other slices that point the same array. Also, if there is not enough length for the slice (`(cap-len) == 0`), `append` returns new array for this slice, at this point, other slices point to the old array will not be affected. +Attention: `append` will change the array that `slice` points to, and affect other slices that point to the same array. Also, if there is not enough length for the slice (`(cap-len) == 0`), `append` returns a new array for this slice. When this happens, other slices pointing to the old array will not be affected. ### map -`map` is like dictionary in Python, use form `map[keyType]valueType` to define it. +`map` is behaves like a dictionary in Python. Use the form `map[keyType]valueType` to define it. -Let's see some code, the set and get value in `map` is like `slice`, use `key` as agent, but index in `slice` can only be int type, and `map` can use much more than that, `int`, `string`, whatever you want. Also, they are all able to use `==` and `!=` to compare values. +Let's see some code. The 'set' and 'get' values in `map` are similar to `slice`, however the index in `slice` can only be of type 'int' while `map` can use much more than that: for example `int`, `string`, or whatever you want. Also, they are all able to use `==` and `!=` to compare values. - // use string as key type, int as value type, and you have to use `make` initialize it. + // use string as the key type, int as the value type, and `make` initialize it. var numbers map[string] int // another way to define map numbers := make(map[string]int) @@ -385,22 +385,20 @@ Let's see some code, the set and get value in `map` is like `slice`, use `key` a fmt.Println("The third number is: ", numbers["three"]) // get values // It prints: The third number is: 3 -`map` is like form in our lives, left side are `key`s, another side are values. - Some notes when you use map. -- `map` is disorderly, every time you print `map` will get different results. It's impossible to get value by `index`, you have to use `key`. -- `map` doesn't have fixed length, it's a reference type as `slice` does. -- `len` works for `map` also, it returns how many `key`s that map has. -- It's quite easy to change value through `map`, simply use `numbers["one"]=11` to change value of `key` one to `11`. +- `map` is disorderly. Everytime you print `map` you will get different results. It's impossible to get values by `index` -you have to use `key`. +- `map` doesn't have a fixed length. It's a reference type just like `slice`. +- `len` works for `map` also. It returns how many `key`s that map has. +- It's quite easy to change the value through `map`. Simply use `numbers["one"]=11` to change the value of `key` one to `11`. -You can use form `key:val` to initialize map's values, and `map` has method inside to check if the `key` exists. +You can use form `key:val` to initialize map's values, and `map` has built-in methods to check if the `key` exists. -Use `delete` to delete element in `map`. +Use `delete` to delete an element in `map`. // Initialize a map rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 } - // map has two return values. For second value, if the key doesn't exist,ok is false,true otherwise. + // map has two return values. For the second return value, if the key doesn't exist,'ok' returns false. It returns true otherwise. csharpRating, ok := rating["C#"] if ok { fmt.Println("C# is in the map and its rating is ", csharpRating) @@ -410,7 +408,7 @@ Use `delete` to delete element in `map`. delete(rating, "C") // delete element with key "c" -As I said above, `map` is a reference type, if two `map`s point to same underlying data, any change will affect both of them. +As I said above, `map` is a reference type. If two `map`s point to same underlying data, any change will affect both of them. m := make(map[string]string) m["Hello"] = "Bonjour" @@ -419,23 +417,23 @@ As I said above, `map` is a reference type, if two `map`s point to same underlyi ### make, new -`make` does memory allocation for built-in models, such as `map`, `slice`, and `channel`), `new` is for types' memory allocation. +`make` does memory allocation for built-in models, such as `map`, `slice`, and `channel`), while `new` is for types' memory allocation. -`new(T)` allocates zero-value to type `T`'s memory, returns its memory address, which is the value of type `*T`. By Go's term, it returns a pointer, which points to type `T`'s zero-value. +`new(T)` allocates zero-value to type `T`'s memory, returns its memory address, which is the value of type `*T`. By Go's definition, it returns a pointer which points to type `T`'s zero-value. `new` returns pointers. -Built-in function `make(T, args)` has different purposes from `new(T)`, `make` can be used for `slice`, `map`, and `channel`, and returns a type `T` with initial value. The reason of doing this is because these three types' underlying data must be initialized before they point to them. For example, a `slice` contains a pointer points to underlying `array`, length and capacity. Before these data were initialized, `slice` is `nil`, so for `slice`, `map`, `channel`, `make` initializes their underlying data, and assigns some suitable values. +The built-in function `make(T, args)` has different purposes than `new(T)`. `make` can be used for `slice`, `map`, and `channel`, and returns a type `T` with an initial value. The reason for doing this is because the underlying data of these three types must be initialized before they point to them. For example, a `slice` contains a pointer that points to the underlying `array`, length and capacity. Before these data are initialized, `slice` is `nil`, so for `slice`, `map` and `channel`, `make` initializes their underlying data and assigns some suitable values. `make` returns non-zero values. -The following picture shows how `new` and `make` be different. +The following picture shows how `new` and `make` are different. ![](images/2.2.makenew.png?raw=true) Figure 2.5 Underlying memory allocation of make and new -As for zero-value, it doesn't mean empty value. It's the value that variables are not assigned manually, usually is 0, there is list of some zero-values. +Zero-value does not mean empty value. It's the value that variables default to in most cases. Here is a list of some zero-values. int 0 int8 0 From d5fd1a0f9b4c24c278d22e4aee8467c19e41ff47 Mon Sep 17 00:00:00 2001 From: Anchor Date: Wed, 27 Aug 2014 14:30:41 -0700 Subject: [PATCH 03/20] Fixed grammar and syntax in 02.3.md --- en/eBook/02.3.md | 108 +++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/en/eBook/02.3.md b/en/eBook/02.3.md index cbda3029..fe94fd8f 100644 --- a/en/eBook/02.3.md +++ b/en/eBook/02.3.md @@ -1,14 +1,14 @@ # 2.3 Control statements and functions -In this section, we are going to talk about control statements and function operation in Go. +In this section, we are going to talk about control statements and function operations in Go. ## Control statement -The greatest inventions in programming language is flow control. Because of them, you are able to use simple control statements represent complex logic. There are three categories, conditional, cycle control and unconditional jump. +The greatest invention in programming is flow control. Because of them, you are able to use simple control statements that can be used to represent complex logic. There are three categories of flow control: conditional, cycle control and unconditional jump. ### if -`if` is the most common keyword in your programs. If it meets the conditions then does something, does something else if not. +`if` will most likely be the most common keyword in your programs. If it meets the conditions, then it does something and it does something else if not. `if` doesn't need parentheses in Go. @@ -18,7 +18,7 @@ The greatest inventions in programming language is flow control. Because of them fmt.Println("x is less than 10") } -The most useful thing of `if` in Go is that it can have one initialization statement before the conditional statement. The scope of variables which are defined in this initialization statement is only in the block of `if`. +The most useful thing concerning `if` in Go is that it can have one initialization statement before the conditional statement. The scope of the variables defined in this initialization statement are only available inside the block of the defining `if`. // initialize x, then check if x greater than if x := computedValue(); x > 10 { @@ -42,7 +42,7 @@ Use if-else for multiple conditions. ### goto -Go has `goto`, be careful when you use it. `goto` has to jump to the `label` that in the body of same code block. +Go has a `goto` keyword, but be careful when you use it. `goto` reroutes the control flow to a previously defined `label` within the body of same code block. func myFunc() { i := 0 @@ -52,19 +52,19 @@ Go has `goto`, be careful when you use it. `goto` has to jump to the `label` tha goto Here // jump to label "Here" } -Label name is case sensitive. +The label name is case sensitive. ### for -`for` is the most powerful control logic in Go, it can read data in loops and iterative operations, just like `while`. +`for` is the most powerful control logic in Go. It can read data in loops and iterative operations, just like `while`. for expression1; expression2; expression3 { //... } -`expression1`, `expression2` and `expression3` are all expressions obviously, where `expression1` and `expression3` are variable defination or return values from functions, and `expression2` is a conditional statement. `expression1` will be executed before every loop, and `expression3` will be after. +`expression1`, `expression2` and `expression3` are all expressions, where `expression1` and `expression3` are variable definitions or return values from functions, and `expression2` is a conditional statement. `expression1` will be executed before every loop, and `expression3` will be executed after. -An example is more useful than hundreds of words. +Examples are more useful than words. package main import "fmt" @@ -78,7 +78,7 @@ An example is more useful than hundreds of words. } // Print:sum is equal to 45 -Sometimes we need multiple assignments, but Go doesn't have operator `,`, so we use parallel assignment like `i, j = i + 1, j - 1`. +Sometimes we need multiple assignments, but Go doesn't have the `,` operator, so we use parallel assignment like `i, j = i + 1, j - 1`. We can omit `expression1` and `expression3` if they are not necessary. @@ -87,14 +87,14 @@ We can omit `expression1` and `expression3` if they are not necessary. sum += sum } -Omit `;` as well. Feel familiar? Yes, it's `while`. +Omit `;` as well. Feel familiar? Yes, it's identical to `while`. sum := 1 for sum < 1000 { sum += sum } -There are two important operations in loops which are `break` and `continue`. `break` jumps out the loop, and `continue` skips current loop and starts next one. If you have nested loops, use `break` with labels together. +There are two important operations in loops which are `break` and `continue`. `break` jumps out of the loop, and `continue` skips the current loop and starts the next one. If you have nested loops, use `break` along with labels. for index := 10; index>0; index-- { if index == 5{ @@ -105,14 +105,14 @@ There are two important operations in loops which are `break` and `continue`. `b // break prints 10、9、8、7、6 // continue prints 10、9、8、7、6、4、3、2、1 -`for` could read data from `slice` and `map` when it is used with `range`. +`for` can read data from `slice` and `map` when it is used together with `range`. for k,v:=range map { fmt.Println("map's key:",k) fmt.Println("map's val:",v) } -Because Go supports multi-value return and gives compile errors when you don't use values that was defined, so you may want to use `_` to discard some return values. +Because Go supports multi-value returns and gives compile errors when you don't use values that were defined, you may want to use `_` to discard certain return values. for _, v := range map{ fmt.Println("map's val:", v) @@ -120,7 +120,7 @@ Because Go supports multi-value return and gives compile errors when you don't u ### switch -Sometimes you may think you use too much `if-else` to implement some logic, also it's not looking nice and herd to maintain in the future. Now it's time to use `switch` to solve this problem. +Sometimes you may find that you are using too many `if-else` statements to implement some logic, which may make it difficult to read and maitain in the future. This is the perfect time to use the `switch` statement to solve this problem. switch sExpr { case expr1: @@ -133,7 +133,7 @@ Sometimes you may think you use too much `if-else` to implement some logic, also other code } -The type of `sExpr`, `expr1`, `expr2`, and `expr3` must be the same. `switch` is very flexible, conditions don't have to be constants, it executes from top to down until it matches conditions. If there is no statement after keyword `switch`, then it matches `true`. +The type of `sExpr`, `expr1`, `expr2`, and `expr3` must be the same. `switch` is very flexible. Conditions don't have to be constants and it executes from top to bottom until it matches conditions. If there is no statement after the keyword `switch`, then it matches `true`. i := 10 switch i { @@ -147,7 +147,7 @@ The type of `sExpr`, `expr1`, `expr2`, and `expr3` must be the same. `switch` is fmt.Println("All I know is that i is an integer") } -In fifth line, we put many values in one `case`, and we don't need `break` in the end of `case` body. It will jump out of switch body once it matched any case. If you want to continue to match more cases, you need to use statement `fallthrough`. +In the fifth line, we put many values in one `case`, and we don't need to add the `break` keyword at the end of `case`'s body. It will jump out of the switch body once it matched any case. If you want to continue to matching more cases, you need to use the`fallthrough` statement. integer := 6 switch integer { @@ -170,7 +170,7 @@ In fifth line, we put many values in one `case`, and we don't need `break` in th fmt.Println("default case") } -This program prints following information. +This program prints the following information. integer <= 6 integer <= 7 @@ -179,7 +179,7 @@ This program prints following information. ## Functions -Use the keyword `func` to define a function. +Use the `func` keyword to define a function. func funcName(input1 type1, input2 type2) (output1 type1, output2 type2) { // function body @@ -187,15 +187,15 @@ Use the keyword `func` to define a function. return value1, value2 } -We can get following information from above example. +We extrapolate the following information from the example above. - Use keyword `func` to define a function `funcName`. -- Functions have zero or one or more than one arguments, argument type after the argument name and broke up by `,`. +- Functions have zero, one or more than one arguments. The argument type comes after the argument name and arguments are separated by `,`. - Functions can return multiple values. -- There are two return values named `output1` and `output2`, you can omit name and use type only. -- If there is only one return value and you omitted the name, you don't need brackets for return values anymore. -- If the function doesn't have return values, you can omit return part. -- If the function has return values, you have to use `return` statement in some places in the body of function. +- There are two return values named `output1` and `output2`, you can omit their names and use their type only. +- If there is only one return value and you omitted the name, you don't need brackets for the return values. +- If the function doesn't have return values, you can omit the return parameters altogether. +- If the function has return values, you have to use the `return` statement somewhere in the body of the function. Let's see one practical example. (calculate maximum value) @@ -223,13 +223,13 @@ Let's see one practical example. (calculate maximum value) fmt.Printf("max(%d, %d) = %d\n", y, z, max(y,z)) // call function here } -In the above example, there are two arguments in function `max`, their type are both `int`, so the first type can be omitted, like `a, b int` instead of `a int, b int`. Same rules for more arguments. Notice here the `max` only have one return value, so we only write type of return value, this is a short form. +In the above example, there are two arguments in the function `max`, their types are both `int` so the first type can be omitted. For instance, `a, b int` instead of `a int, b int`. The same rules apply for additional arguments. Notice here that `max` only has one return value, so we only need to write the type of its return value -this is the short form of writing it. ### Multi-value return -One thing that Go is better than C is that it supports multi-value return. +One thing that Go is better at than C is that it supports multi-value returns. -We use above example here. +We'll use the following example here. package main import "fmt" @@ -249,7 +249,7 @@ We use above example here. fmt.Printf("%d * %d = %d\n", x, y, xTIMESy) } -Above example return two values without name, and you can name them also. If we named return values, we just use `return` to return values is fine because they initializes in the function automatically. Notice that if your functions are going to be used outside the package, which means your functions name start with capital letter, you'd better write complete statement for `return`; it makes your code more readable. +The above example returns two values without names -you have the option of naming them also. If we named the return values, we would just need to use `return` to return the values since they are initialized in the function automatically. Notice that if your functions are going to be used outside of the package, which means your function names start with a capital letter, you'd better write complete statements for `return`; it makes your code more readable. func SumAndProduct(A, B int) (add int, Multiplied int) { add = A+B @@ -259,11 +259,11 @@ Above example return two values without name, and you can name them also. If we ### Variable arguments -Go supports variable arguments, which means you can give uncertain number of argument to functions. +Go supports variable arguments, which means you can give an uncertain numbers of argument to functions. func myfunc(arg ...int) {} -`arg …int` tells Go this is the function that has variable arguments. Notice that these arguments are type `int`. In the body of function, the `arg` becomes a `slice` of `int`. +`arg …int` tells Go that this is a function that has variable arguments. Notice that these arguments are type `int`. In the body of function, the `arg` becomes a `slice` of `int`. for _, n := range arg { fmt.Printf("And the number is: %d\n", n) @@ -271,9 +271,9 @@ Go supports variable arguments, which means you can give uncertain number of arg ### Pass by value and pointers -When we pass an argument to the function that was called, that function actually gets the copy of our variables, any change will not affect to the original variable. +When we pass an argument to the function that was called, that function actually gets the copy of our variables so any change will not affect to the original variable. -Let's see one example to prove my words. +Let's see one example to prove what i'm saying. package main import "fmt" @@ -301,7 +301,7 @@ The reason is very simple: when we called `add1`, we gave a copy of `x` to it, n Now you may ask how I can pass the real `x` to the function. -We need use pointers here. We know variables store in the memory, and they all have memory address, we change value of variable is to change the value in that variable's memory address. Therefore the function `add1` have to know the memory address of `x` in order to change its value. Here we pass `&x` to the function, and change argument's type to pointer type `*int`. Be aware that we pass a copy of pointer, not copy of value. +We need use pointers here. We know variables are stored in memory and that they all have memory addresses. So, if we want to change the value of a variable, we must change the value at that variable's memory address. Therefore the function `add1` has to know the memory address of `x` in order to change its value. Here we pass `&x` to the function, and change the argument's type to the pointer type `*int`. Be aware that we pass a copy of the pointer, not copy of value. package main import "fmt" @@ -323,15 +323,15 @@ We need use pointers here. We know variables store in the memory, and they all h fmt.Println("x = ", x) // should print "x = 4" } -Now we can change value of `x` in the functions. Why we use pointers? What are the advantages? +Now we can change the value of `x` in the functions. Why do we use pointers? What are the advantages? -- Use more functions to operate one variable. -- Low cost by passing memory addresses (8 bytes), copy is not an efficient way in both time and space to pass variables. -- `string`, `slice`, `map` are reference types, so they use pointers when pass to functions as default. (Attention: If you need to change length of `slice`, you have to pass pointers explicitly) +- Allows us to use more functions to operate on one variable. +- Low cost by passing memory addresses (8 bytes), copy is not an efficient way, both in terms of time and space, to pass variables. +- `string`, `slice`, `map` are reference types, so they use pointers when passing to functions by default. (Attention: If you need to change the length of `slice`, you have to pass pointers explicitly) ### defer -Go has a good design called `defer`, you can have many `defer` statements in one function; they will execute by reverse order when the program executes to the end of functions. Especially when the program open some resource files, these files have to be closed before the function return with errors. Let's see some examples. +Go has a well designed keyword called `defer`. You can have many `defer` statements in one function; they will execute in reverse order when the program executes to the end of functions. In the case where the program opens some resource files, these files would have to be closed before the function can return with errors. Let's see some examples. func ReadWrite() bool { file.Open("file") @@ -350,7 +350,7 @@ Go has a good design called `defer`, you can have many `defer` statements in one return true } -We saw some code repeat several times, `defer` solves this problem very well. It doesn't only help you make clean code, and also make code more readable. +We saw some code being repeated several times. `defer` solves this problem very well. It doesn't only help you to write clean code but also makes your code more readable. func ReadWrite() bool { file.Open("file") @@ -364,7 +364,7 @@ We saw some code repeat several times, `defer` solves this problem very well. It return true } -If there are more than one `defer`, they will execute by reverse order. The following example will print `4 3 2 1 0`. +If there are more than one `defer`s, they will execute by reverse order. The following example will print `4 3 2 1 0`. for i := 0; i < 5; i++ { defer fmt.Printf("%d ", i) @@ -372,11 +372,11 @@ If there are more than one `defer`, they will execute by reverse order. The foll ### Functions as values and types -Functions are also variables in Go, we can use `type` to define them. Functions that have same signature can be seen as same type. +Functions are also variables in Go, we can use `type` to define them. Functions that have the same signature can be seen as the same type. type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...]) -What's the advantage of this feature? So that we can pass functions as values. +What's the advantage of this feature? The answer is that it allows us to pass functions as values. package main import "fmt" @@ -418,15 +418,15 @@ What's the advantage of this feature? So that we can pass functions as values. fmt.Println("Even elements of slice are: ", even) } -It's very useful when we use interfaces. As you can see `testInt` is a variable that has function type, and return values and arguments of `filter` are the same as `testInt`. Therefore, we have more complex logic in our programs, and make code more flexible. +It's very useful when we use interfaces. As you can see `testInt` is a variable that has function type, and return values and arguments of `filter` are the same as `testInt`. Therefore, we can have complex logic in our programs, while maintaining flexibility in our code. ### Panic and Recover Go doesn't have `try-catch` structure like Java does. Instead of throwing exceptions, Go uses `panic` and `recover` to deal with errors. However, you shouldn't use `panic` very much, although it's powerful. -Panic is a built-in function to break normal flow of programs and get into panic status. When function `F` called `panic`, function `F` will not continue executing, but its `defer` functions are always executing. Then `F` goes back to its break point where causes panic status. The program will not end until all the functions return with panic to the first level of that `goroutine`. `panic` can be produced by calling `panic` in the program, and some errors also cause `panic` like array access out of bounds. +Panic is a built-in function to break the normal flow of programs and get into panic status. When a function `F` calls `panic`, `F` will not continue executing but its `defer` functions will continue to execute. Then `F` goes back to the break point which caused the panic status. The program will not terminate until all of these functions return with panic to the first level of that `goroutine`. `panic` can be produced by calling `panic` in the program, and some errors also cause `panic` like array access out of bounds errors. -Recover is a built-in function to recover `goroutine` from panic status, only call `recover` in `defer` functions is useful because normal functions will not be executed when the program is in the panic status. It catches `panic` value if the program is in the panic status, it gets `nil` if the program is not in panic status. +Recover is a built-in function to recover `goroutine`s from panic status. Calling `recover` in `defer` functions is useful because normal functions will not be executed when the program is in the panic status. It catches `panic` values if the program is in the panic status, and it gets `nil` if the program is not in panic status. The following example shows how to use `panic`. @@ -452,11 +452,11 @@ The following example shows how to check `panic`. ### `main` function and `init` function -Go has two retention which are called `main` and `init`, where `init` can be used in all packages and `main` can only be used in the `main` package. these two function are not able to have arguments or return values. Even though we can write many `init` function in one package, I strongly recommend to write only one `init` function for each package. +Go has two retentions which are called `main` and `init`, where `init` can be used in all packages and `main` can only be used in the `main` package. These two functions are not able to have arguments or return values. Even though we can write many `init` functions in one package, I strongly recommend writing only one `init` function for each package. -Go programs will call `init()` and `main()` automatically, so you don't need to call them by yourself. For every package, function `init` is optional, but `package main` has one and only one `main` function. +Go programs will call `init()` and `main()` automatically, so you don't need to call them by yourself. For every package, the `init` function is optional, but `package main` has one and only one `main` function. -Programs initializes and executes from `main` package, if `main` package imports other packages, they will be imported in the compile time. If one package is imported many times, it will be only compiled once. After imported packages, programs will initialize constants and variables in imported packages, then execute `init` function if it exists, and so on. After all the other packages were initialized, programs start initialize constants and variables in `main` package, then execute `init` function in package if it exists. The following figure shows the process. +Programs initialize and begin execution from the `main` package. If the `main` package imports other packages, they will be imported in the compile time. If one package is imported many times, it will be only compiled once. After importing packages, programs will initialize the constants and variables within the imported packages, then execute the `init` function if it exists, and so on. After all the other packages are initialized, programs will initialize constants and variables in the `main` package, then execute the `init` function inside the package if it exists. The following figure shows the process. ![](images/2.3.init.png?raw=true) @@ -474,7 +474,7 @@ Then we use functions in that package as follows. fmt.Println("hello world") -`fmt` is from Go standard library, it locates in $GOROOT/pkg. Go uses two ways to support third-party packages. +`fmt` is from Go standard library, it is located within $GOROOT/pkg. Go supports third-party packages in two ways. 1. Relative path import "./model" // load package in the same directory, I don't recommend this way. @@ -490,9 +490,9 @@ There are some special operators when we import packages, and beginners are alwa . "fmt" ) - The dot operator means you can omit package name when you call functions in that package. Now `fmt.Printf("Hello world")` becomes to `Printf("Hello world")`. + The dot operator means you can omit the package name when you call functions inside of that package. Now `fmt.Printf("Hello world")` becomes to `Printf("Hello world")`. 2. Alias operation. - It changes the name of package that we imported when we call functions in that package. + It changes the name of the package that we imported when we call functions that belong to that package. import( f "fmt" @@ -500,14 +500,14 @@ There are some special operators when we import packages, and beginners are alwa Now `fmt.Printf("Hello world")` becomes to `f.Printf("Hello world")`. 3. `_` operator. - This is the operator that hard to understand whitout someone explanning to you. + This is the operator that is difficult to understand without someone explaining it to you. import ( "database/sql" _ "github.com/ziutek/mymysql/godrv" ) - The `_` operator actually means we just import that package, and use `init` function in that package, and we are not sure if want to use functions in that package. + The `_` operator actually means we just want to import that package and execute its `init` function, and we are not sure if want to use the functions belonging to that package. ## Links From 61a6b4249047ad07e91e7791a03bdae45ed847ed Mon Sep 17 00:00:00 2001 From: Anchor Date: Thu, 28 Aug 2014 21:43:04 -0700 Subject: [PATCH 04/20] Grammar and syntax fixes for 02.4.md --- en/eBook/02.4.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/en/eBook/02.4.md b/en/eBook/02.4.md index 79a04a3a..0e7542fa 100644 --- a/en/eBook/02.4.md +++ b/en/eBook/02.4.md @@ -2,7 +2,7 @@ ## struct -We can define new type of container of other properties or fields in Go like in other programming languages. For example, we can create a type called `person` to represent a person, this type has name and age. We call this kind of type as `struct`. +We can define new types of containers of other properties or fields in Go just like in other programming languages. For example, we can create a type called `person` to represent a person, with fields name and age. We call this kind of type a `struct`. type person struct { name string @@ -25,21 +25,21 @@ Let's see how to use it. var P person // p is person type - P.name = "Astaxie" // assign "Astaxie" to the filed 'name' of p + P.name = "Astaxie" // assign "Astaxie" to the field 'name' of p P.age = 25 // assign 25 to field 'age' of p fmt.Printf("The person's name is %s\n", P.name) // access field 'name' of p -There are three more ways to define struct. +There are three more ways to define a struct. - Assign initial values by order P := person{"Tom", 25} -- Use format `field:value` to initialize without order +- Use the format `field:value` to initialize the struct without order P := person{age:24, name:"Bob"} -- Define a anonymous struct, then initialize it +- Define an anonymous struct, then initialize it P := struct{name string; age int}{"Amy",18} @@ -54,7 +54,7 @@ Let's see a complete example. age int } - // compare age of two people, return the older person and differences of age + // compare the age of two people, then return the older person and differences of age // struct is passed by value func Older(p1, p2 person) (person, int) { if p1.age>p2.age { @@ -88,9 +88,9 @@ Let's see a complete example. ### embedded fields in struct -I just introduced you how to define a struct with fields name and type. In fact, Go support fields without name but types, we call these embedded fields. +I've just introduced to you how to define a struct with field names and type.s In fact, Go supports fields without names, but with types. We call these embedded fields. -When the embedded field is a struct, all the fields in that struct will be the fields in the new struct implicitly. +When the embedded field is a struct, all the fields in that struct will implicitly be the fields in the struct in which it has been embdedded. Let's see one example. @@ -135,12 +135,12 @@ Let's see one example. Figure 2.7 Inheritance in Student and Human -We see that we access age and name in Student just like we access them in Human. This is how embedded field works. It is very cool, isn't it? Hold on, there is something cooler! You can even use Student to access Human this embedded field! +We see that we can access the age and name fields in Student just like we can in Human. This is how embedded fields work. It's very cool, isn't it? Hold on, there's something cooler! You can even use Student to access Human in this embedded field! mark.Human = Human{"Marcus", 55, 220} mark.Human.age -= 1 -All the types can be used as embedded fields. +All the types in Go can be used as embedded fields. package main import "fmt" @@ -179,11 +179,11 @@ All the types can be used as embedded fields. fmt.Println("Her preferred number is", jane.int) } -In above example we can see that all types can be embedded fields and we can use functions to operate them. +In the above example, we can see that all types can be embedded fields and we can use functions to operate on them. -There is one more problem, if Human has a field called `phone` and Student has a field with same name, what should we do? +There is one more problem however. If Human has a field called `phone` and Student has a field with same name, what should we do? -Go use a very simple way to solve it. The outer fields get upper access levels, which means when you access `student.phone`, we will get the field called phone in student, not in the Human struct. This feature can be simply seen as `overload` of field. +Go use a very simple way to solve it. The outer fields get upper access levels, which means when you access `student.phone`, we will get the field called phone in student, not the one in the Human struct. This feature can be simply seen as field `overload`ing. package main import "fmt" From 8e3a6026546252670901dd83fec239882b046a4f Mon Sep 17 00:00:00 2001 From: Anchor Date: Fri, 29 Aug 2014 23:27:48 -0700 Subject: [PATCH 05/20] Grammar and typo fixes for 02.5.md --- en/eBook/02.5.md | 56 ++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/en/eBook/02.5.md b/en/eBook/02.5.md index 8cda4cdb..c187beb6 100644 --- a/en/eBook/02.5.md +++ b/en/eBook/02.5.md @@ -1,10 +1,10 @@ # Object-oriented -We talked about functions and structs in the last two sections, did you ever think about using functions as fields of a struct? In this section, I will introduce you another form of method that has receiver, which is called `method`. +We talked about functions and structs in the last two sections, but did you ever consider using functions as fields of a struct? In this section, I will introduce you to another form of method that has a receiver, which is called `method`. ## method -Suppose you define a struct of rectangle, and you want to calculate its area, we usually use following code to achieve this goal. +Suppose you define a "rectangle" struct and you want to calculate its area. We'd typically use the following code to achieve this goal. package main import "fmt" @@ -24,19 +24,19 @@ Suppose you define a struct of rectangle, and you want to calculate its area, we fmt.Println("Area of r2 is: ", area(r2)) } -Above example can calculate rectangle's area, we use the function called `area`, but it's not a method of a rectangle struct (like methods in class in classic Object-oriented language). The function and struct are two independent things as you may notice. +The above example can calculate a rectangle's area. We use the function called `area`, but it's not a method of the rectangle struct (like class methods in classic object-oriented languages). The function and struct are two independent things as you may notice. -It's not a problem so far. What if you also have to calculate area of circle, square, pentagon, even more, you are going to add more functions with very similar name. +It's not a problem so far. However, if you also have to calculate the area of a circle, square, pentagon, or any other kind of shape, you are going to need to add additional functions with very similar names. ![](images/2.5.rect_func_without_receiver.png?raw=true) Figure 2.8 Relationship between function and struct -Obviously, it's not cool. Also the area should be the property of circle or rectangle. +Obviously that's not cool. Also, the area should really be the property of a circle or rectangle. -For those reasons, we have concepts about `method`. `method` is affiliated of type, it has same syntax as function except one more thing after the keyword `func` that is called `receiver` which is the main body of that method. +For those reasons, we have the `method` concept. `method` is affiliated with type. It has the same syntax as functions do except for an additional parameter after the `func` keyword called the `receiver`, which is the main body of that method. -Use the same example, `Rectangle.area()` belongs to rectangle, not as a peripheral function. More specifically, `length`, `width` and `area()` all belong to rectangle. +Using the same example, `Rectangle.area()` belongs directly to rectangle, instead of as a peripheral function. More specifically, `length`, `width` and `area()` all belong to rectangle. As Rob Pike said. @@ -46,7 +46,7 @@ Syntax of method. func (r ReceiverType) funcName(parameters) (results) -Let's change out example by using method. +Let's change our example using `method` instead. package main import ( @@ -84,25 +84,25 @@ Let's change out example by using method. Notes for using methods. -- If the name of methods is same, but they don't have same receivers, they are not same. -- methods are able to access fields in receivers. -- Use `.` to call a method in the struct, just like to call fields. +- If the name of methods are the same but they don't share the same receivers, they are not the same. +- Methods are able to access fields within receivers. +- Use `.` to call a method in the struct, the same way fields are called. ![](images/2.5.shapes_func_with_receiver_cp.png?raw=true) -Figure 2.9 Methods are difference in difference struct +Figure 2.9 Methods are different in different structs -In above example, method area() is respectively belonging to Rectangle and Circle, so the receivers are Rectangle and Circle. +In the example above, the area() methods belong to both Rectangle and Circle respectively, so the receivers are Rectangle and Circle. -One thing is worthy of note that the method with a dotted line means the receiver is passed by value, not by reference. The different between them is that the method could change receiver's value when the receiver is passed by reference, and it gets the copy of receiver when the receiver is passed by value. +One thing that's worth noting is that the method with a dotted line means the receiver is passed by value, not by reference. The difference between them is that a method can change its receiver's values when the receiver is passed by reference, and it gets a copy of the receiver when the receiver is passed by value. -Does the receiver can only be struct? Of course not, any type could be the receiver of a method. You may be confused about customized type, struct is a special type of customized type, there are more customized types. +Can the receiver only be a struct? Of course not. Any type can be the receiver of a method. You may be confused about customized types. Struct is a special kind of customized type -there are more customized types. -Use following format to define a customized type. +Use the following format to define a customized type. type typeName typeLiteral -Examples about customized type. +Examples of customized types: type ages int @@ -117,11 +117,11 @@ Examples about customized type. "December":31, } -I hope you know how to use customized type now. it's like `typedef` in C, we use `ages` to substitute `int` in above example. +I hope that you know how to use customized types now. Similar to `typedef` in C, we use `ages` to substitute `int` in the above example. -Let's get back to `method`. +Let's get back to talking about `method`. -You can use as many methods in customized types as you want. +You can use as many methods in custom types as you want. package main import "fmt" @@ -204,27 +204,27 @@ We define some constants and customized types. Then we defined some methods for our customized types. -- Volume() use Box as its receiver, returns volume of Box. +- Volume() uses Box as its receiver and returns volume of Box. - SetColor(c Color) changes Box's color. - BiggestsColor() returns the color which has the biggest volume. - PaintItBlack() sets color for all Box in BoxList to black. - String() use Color as its receiver, returns the string format of color name. -Is it much clear when we use words to describe our requirements? We often write our requirements before we start coding. +Is it much clearer when we use words to describe our requirements? We often write our requirements before we start coding. ### Use pointer as receiver -Let's take a look at method `SetColor`, its receiver is a pointer of Box. Yes, you can use `*Box` as receiver. Why we use pointer here? Because we want to change Box's color in this method, if we don't use pointer, it only changes value of copy of Box. +Let's take a look at `SetColor` method. Its receiver is a pointer of Box. Yes, you can use `*Box` as a receiver. Why do we use a pointer here? Because we want to change Box's color in this method. Thus, if we don't use a pointer, it will only change the value inside a copy of Box. -If we see receiver as the first argument of the method, it's not hard to understand how it works. +If we see that a receiver is the first argument of a method, it's not hard to understand how it works. -You may ask that we should use `(*b).Color=c` instead of `b.Color=c` in method SetColor(). Either one is OK here because Go knows it. Do you think Go is more fascinating now? +You might be asking why we aren't using `(*b).Color=c` instead of `b.Color=c` in the SetColor() method. Either one is OK here because Go knows how to interpret the assignment. Do you think Go is more fascinating now? -You may also ask we should use `(&bl[i]).SetColor(BLACK)` in `PaintItBlack` because we pass a pointer to `SetColor`. One more time, either one is OK because Go knows it! +You may also be asking whether we should use `(&bl[i]).SetColor(BLACK)` in `PaintItBlack` because we pass a pointer to `SetColor`. Again, either one is OK because Go knows how to interpret it! ### Inheritance of method -We learned inheritance of field in last section, and we also have inheritance of method in Go. So that if a anonymous field has methods, then the struct that contains the field have all methods from it as well. +We learned about inheritance of fields in the last section. Similarly, we also have method inheritance in Go. If an anonymous field has methods, then the struct that contains the field will have all the methods from it as well. package main import "fmt" @@ -260,7 +260,7 @@ We learned inheritance of field in last section, and we also have inheritance of ### Method overload -If we want Employee to have its own method `SayHi`, we can define the method that has same name in Employee, and it will hide `SayHi` in Human when we call it. +If we want Employee to have its own method `SayHi`, we can define a method that has the same name in Employee, and it will hide `SayHi` in Human when we call it. package main import "fmt" From 58c9366465726245656ad1088dfbd93577bb0faf Mon Sep 17 00:00:00 2001 From: Anchor Date: Tue, 2 Sep 2014 23:51:28 -0700 Subject: [PATCH 06/20] Grammar and typo fixes for 02.6.md --- en/eBook/02.6.md | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/en/eBook/02.6.md b/en/eBook/02.6.md index cecabc88..3d75ea7b 100644 --- a/en/eBook/02.6.md +++ b/en/eBook/02.6.md @@ -6,15 +6,15 @@ One of the subtlest design features in Go are interfaces. After reading this sec ### What is an interface -In short, an interface is a set of methods, that we use to define a set of actions. +In short, an interface is a set of methods that we use to define a set of actions. Like the examples in previous sections, both Student and Employee can `SayHi()`, but they don't do the same thing. -Let's do more work, we add one more method `Sing()` to them, also add `BorrowMoney()` to Student and `SpendSalary()` to Employee. +Let's do some more work. We'll add one more method `Sing()` to them, along with the `BorrowMoney()` method to Student and the `SpendSalary()` method to Employee. -Now Student has three methods called `SayHi()`, `Sing()`, `BorrowMoney()`, and Employee has `SayHi()`, `Sing()` and `SpendSalary()`. +Now, Student has three methods called `SayHi()`, `Sing()` and `BorrowMoney()`, and Employee has `SayHi()`, `Sing()` and `SpendSalary()`. -This combination of methods is called an interface, and is implemented by Student and Employee. So Student and Employee implement the interface: `SayHi()`, `Sing()`. At the same time, Employee doesn't implement the interface: `SayHi()`, `Sing()`, `BorrowMoney()`, and Student doesn't implement the interface: `SayHi()`, `Sing()`, `SpendSalary()`. This is because Employee doesn't have the method `BorrowMoney()` and Student doesn't have the method `SpendSalary()`. +This combination of methods is called an interface and is implemented by both Student and Employee. So, Student and Employee implement the interface: `SayHi()` and `Sing()`. At the same time, Employee doesn't implement the interface: `SayHi()`, `Sing()`, `BorrowMoney()`, and Student doesn't implement the interface: `SayHi()`, `Sing()`, `SpendSalary()`. This is because Employee doesn't have the method `BorrowMoney()` and Student doesn't have the method `SpendSalary()`. ### Type of Interface @@ -83,15 +83,15 @@ An interface defines a set of methods, so if a type implements all the methods w SpendSalary(amount float32) } -We know that an interface can be implemented by any type, and one type can implement many interfaces at the same time. +We know that an interface can be implemented by any type, and one type can implement many interfaces simultaneously. -Note that any type implements the empty interface `interface{}` because it doesn't have any methods and all types have zero methods as default. +Note that any type implements the empty interface `interface{}` because it doesn't have any methods and all types have zero methods by default. ### Value of interface So what kind of values can be put in the interface? If we define a variable as a type interface, any type that implements the interface can assigned to this variable. -Like the above example, if we define a variable m as interface Men, then any one of Student, Human or Employee can be assigned to m. So we could have a slice of Men, and any type that implements interface Men can assign to this slice. Be aware however that the slice of interface doesn't have the same behavior as a slice of other types. +Like the above example, if we define a variable "m" as interface Men, then any one of Student, Human or Employee can be assigned to "m". So we could have a slice of Men, and any type that implements interface Men can assign to this slice. Be aware however that the slice of interface doesn't have the same behavior as a slice of other types. package main @@ -171,7 +171,7 @@ An interface is a set of abstract methods, and can be implemented by non-interfa ### Empty interface -An empty interface is an interface that doesn't contain any methods, so all types implemented an empty interface. It's very useful when we want to store all types at some point, and is similar to void* in C. +An empty interface is an interface that doesn't contain any methods, so all types implement an empty interface. This fact is very useful when we want to store all types at some point, and is similar to void* in C. // define a as empty interface var a interface{} @@ -185,9 +185,9 @@ If a function uses an empty interface as its argument type, it can accept any ty ### Method arguments of an interface -Any variable that can be used in an interface, so we can think about how can we use this feature to pass any type of variable to the function. +Any variable can be used in an interface. So how can we use this feature to pass any type of variable to a function? -For example, we use fmt.Println a lot, but have you ever noticed that it accepts any type of arguments? Looking at the open source code of fmt, we see the following definition. +For example we use fmt.Println a lot, but have you ever noticed that it can accept any type of argument? Looking at the open source code of fmt, we see the following definition. type Stringer interface { String() string @@ -228,11 +228,11 @@ Attention: If the type implemented the interface `error`, fmt will call `error() ### Type of variable in an interface -If a variable is the type that implements an interface, we know that any other type that implements the same interface can be assigned to this variable. The question is how can we know the specific type stored in the interface. There are two ways that I'm going to tell you. +If a variable is the type that implements an interface, we know that any other type that implements the same interface can be assigned to this variable. The question is how can we know the specific type stored in the interface. There are two ways which I will show you. - Assertion of Comma-ok pattern -Go has the syntax `value, ok := element.(T)`. This checks to see if the variable is the type that we expect, where the value is the value of the variable, ok is a variable of boolean type, element is the interface variable and the T is the type of assertion. +Go has the syntax `value, ok := element.(T)`. This checks to see if the variable is the type that we expect, where "value" is the value of the variable, "ok" is a variable of boolean type, "element" is the interface variable and the T is the type of assertion. If the element is the type that we expect, ok will be true, false otherwise. @@ -322,13 +322,13 @@ Let's use `switch` to rewrite the above example. } -One thing you should remember is that `element.(type)` cannot be used outside of `switch` body, which means in that case you have you use pattern `comma-ok`. +One thing you should remember is that `element.(type)` cannot be used outside of the `switch` body, which means in that case you have to use the `comma-ok` pattern . ### Embedded interfaces -The most beautiful thing is that Go has a lot of built-in logic syntax, such as anonymous fields in struct. Not suprisingly, we can use interfaces as anonymous fields as well, but we call them `Embedded interfaces`. Here, we follows the same rules as anonymous fields. More specifically, if an interface has another interface as the embedded interface, it will have all the methods that the embedded interface has. +The most beautiful thing is that Go has a lot of built-in logic syntax, such as anonymous fields in struct. Not suprisingly, we can use interfaces as anonymous fields as well, but we call them `Embedded interfaces`. Here, we follow the same rules as anonymous fields. More specifically, if an interface has another interface embedded within it, it will have as if it has all the methods that the embedded interface has. -We can see source file in `container/heap` has one definition as follows. +We can see that the source file in `container/heap` has the following definition: type Interface interface { sort.Interface // embedded sort.Interface @@ -336,7 +336,7 @@ We can see source file in `container/heap` has one definition as follows. Pop() interface{} //a Pop elements that pops elements from the heap } -We see that `sort.Interface` is an embedded interface, so the above Interface has three methods that in `sort.Interface` implicitly. +We see that `sort.Interface` is an embedded interface, so the above Interface has the three methods contained within the `sort.Interface` implicitly. type Interface interface { // Len is the number of elements in the collection. @@ -360,12 +360,12 @@ Another example is the `io.ReadWriter` in package `io`. Reflection in Go is used for determining information at runtime. We use the `reflect` package, and this official [article](http://golang.org/doc/articles/laws_of_reflection.html) explains how reflect works in Go. -There are three steps to use reflect. First, we need to convert an interface to reflect types (reflect.Type or reflect.Value, this depends on the situation). +There are three steps involved when using reflect. First, we need to convert an interface to reflect types (reflect.Type or reflect.Value, this depends on the situation). t := reflect.TypeOf(i) // get meta-data in type i, and use t to get all elements v := reflect.ValueOf(i) // get actual value in type i, and use v to change its value -After that, we convert reflect types to get values that we need. +After that, we can convert the reflect types to get values that we need. var x float64 = 3.4 v := reflect.ValueOf(x) @@ -373,20 +373,20 @@ After that, we convert reflect types to get values that we need. fmt.Println("kind is float64:", v.Kind() == reflect.Float64) fmt.Println("value:", v.Float()) -Finally, if we want to change a value that is from reflect types, we need to make it modifiable. As discussed earlier, there is a difference between pass by value and pass by reference. The following code will not compile. +Finally, if we want to change values from reflect types, we need to make it modifiable. As discussed earlier, there is a difference between pass by value and pass by reference. The following code will not compile. var x float64 = 3.4 v := reflect.ValueOf(x) v.SetFloat(7.1) -Instead, we must use the following code to change value from reflect types. +Instead, we must use the following code to change the values from reflect types. var x float64 = 3.4 p := reflect.ValueOf(&x) v := p.Elem() v.SetFloat(7.1) - -I just talked about basic knowledge about reflection, you must pratice more to understand more. + +We have just discussed the basics of reflection, however you must practice more in order to understand more. ## Links From d0ee6ad49df58655dcb7410a6d035240dd35fa52 Mon Sep 17 00:00:00 2001 From: Anchor Date: Thu, 4 Sep 2014 23:35:45 -0700 Subject: [PATCH 07/20] Fix grammar and typos for 02.7.md --- en/eBook/02.7.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/en/eBook/02.7.md b/en/eBook/02.7.md index fa03448a..dd6ecf52 100644 --- a/en/eBook/02.7.md +++ b/en/eBook/02.7.md @@ -1,12 +1,12 @@ # Concurrency -It is said that Go is the C language of 21st century. I think there are two reasons: first, Go is a simple language; second, concurrency is a hot topic in today's world, and Go supports this feature at the language level. +It is said that Go is the C language of the 21st century. I think there are two reasons: first, Go is a simple language; second, concurrency is a hot topic in today's world, and Go supports this feature at the language level. ## goroutine -goroutines and concurrency are built into the core design of Go. They're similar to threads but work differently. More than a dozen goroutines maybe only have 5 or 6 underlying threads. Go also gives you full support to share memory in your goroutines. One goroutine usually uses 4~5 KB stack memory. Therefore, it's not hard to run thousands of goroutines in one computer. A goroutine is more lightweight, more efficient, and more convenient than system threads. +goroutines and concurrency are built into the core design of Go. They're similar to threads but work differently. More than a dozen goroutines maybe only have 5 or 6 underlying threads. Go also gives you full support to sharing memory in your goroutines. One goroutine usually uses 4~5 KB of stack memory. Therefore, it's not hard to run thousands of goroutines on a single computer. A goroutine is more lightweight, more efficient and more convenient than system threads. -goroutines run on the thread manager at runtime in Go. We use keyword `go` to create a new goroutine, which is a function at the underlying level ( ***main() is a goroutine*** ). +goroutines run on the thread manager at runtime in Go. We use the `go` keyword to create a new goroutine, which is a function at the underlying level ( ***main() is a goroutine*** ). go hello(a, b, c) @@ -47,11 +47,11 @@ We see that it's very easy to use concurrency in Go by using the keyword `go`. I runtime.Gosched() means let the CPU execute other goroutines, and come back at some point. -The scheduler only uses one thread to run all goroutines, which means it only implements concurrency. If you want to use more CPU cores in order to use parallel processing, you have to call runtime.GOMAXPROCS(n) to set the number of cores you want to use. If `n<1`, it changes nothing. This function may be removed in the future, see more details about parallel processing and concurrency in this [article](http://concur.rspace.googlecode.com/hg/talk/concur.html#landing-slide). +The scheduler only uses one thread to run all goroutines, which means it only implements concurrency. If you want to use more CPU cores in order to take advantage of parallel processing, you have to call runtime.GOMAXPROCS(n) to set the number of cores you want to use. If `n<1`, it changes nothing. This function may be removed in the future, see more details about parallel processing and concurrency in this [article](http://concur.rspace.googlecode.com/hg/talk/concur.html#landing-slide). ## channels -goroutines are running in the same memory address space, so you have to maintain synchronization when you want to access shared memory. How do you communicate between different goroutines? Go uses a very good communication mechanism called `channel`. `channel` is like a two-way pipeline in Unix shell: use channel to send or receive data. The only data type that can be used in channels is the type `channel` and keyword `chan`. Be aware that you have to use `make` to create a new `channel`. +goroutines run in the same memory address space, so you have to maintain synchronization when you want to access shared memory. How do you communicate between different goroutines? Go uses a very good communication mechanism called `channel`. `channel` is like a two-way pipeline in Unix shells: use `channel` to send or receive data. The only data type that can be used in channels is the type `channel` and the keyword `chan`. Be aware that you have to use `make` to create a new `channel`. ci := make(chan int) cs := make(chan string) @@ -87,11 +87,11 @@ Let's see more examples. fmt.Println(x, y, x + y) } -Sending and receiving data in channels blocks by default, so it's much easier to use synchronous goroutines. What I mean by block is that the goroutine will not continue when it receives data from an empty channel (`value := <-ch`), until other goroutines send data to this channel. On the other hand, the goroutine will not continue when it sends data to channel (`ch<-5`) until this data is received. +Sending and receiving data in channels blocks by default, so it's much easier to use synchronous goroutines. What I mean by block is that a goroutine will not continue when receiving data from an empty channel, i.e (`value := <-ch`), until other goroutines send data to this channel. On the other hand, the goroutine will not continue until the data it sends to a channel, i.e (`ch<-5`), is received. ## Buffered channels -I introduced non-buffered channels above, and Go also has buffered channels that can store more than one element. For example, `ch := make(chan bool, 4)`, here we create a channel that can store 4 boolean elements. So in this channel, we are able to send 4 elements into it without blocking, but the goroutine will be blocked when you try to send a fifth element and no goroutine receives it. +I introduced non-buffered channels above. Go also has buffered channels that can store more than a single element. For example, `ch := make(chan bool, 4)`, here we create a channel that can store 4 boolean elements. So in this channel, we are able to send 4 elements into it without blocking, but the goroutine will be blocked when you try to send a fifth element and no goroutine receives it. ch := make(chan type, n) @@ -139,17 +139,17 @@ We can use range to operate on buffer channels as in slice and map. } } -`for i := range c` will not stop reading data from channel until the channel is closed. We use the keyword `close` to close the channel in above example. It's impossible to send or receive data on a closed channel, you can use `v, ok := <-ch` to test if a channel is closed. If `ok` returns false, it means the there is no data in that channel and it was closed. +`for i := range c` will not stop reading data from channel until the channel is closed. We use the keyword `close` to close the channel in above example. It's impossible to send or receive data on a closed channel; you can use `v, ok := <-ch` to test if a channel is closed. If `ok` returns false, it means the there is no data in that channel and it was closed. -Remember to always close channel in producers, not in consumers, or it's very easy to get into panic status. +Remember to always close channels in producers and not in consumers, or it's very easy to get into panic status. -Another thing you need to remember is that channels are unlike files, and you don't have to close them frequently, unless you are sure the channel is completely useless, or you want to exit range loops. +Another thing you need to remember is that channels are not like files. You don't have to close them frequently unless you are sure the channel is completely useless, or you want to exit range loops. ## Select In the above examples, we only use one channel, but how can we deal with more than one channel? Go has a keyword called `select` to listen to many channels. -`select` is blocking by default, and it continues to execute only when one of channels has data to send or receive. If several channels are ready to use at the same time, select chooses which to execute randomly. +`select` is blocking by default and it continues to execute only when one of channels has data to send or receive. If several channels are ready to use at the same time, select chooses which to execute randomly. package main @@ -180,7 +180,7 @@ In the above examples, we only use one channel, but how can we deal with more th fibonacci(c, quit) } -`select` has `default` as well, just like `switch`. When all the channels are not ready to use, it executes default (doesn't wait for channel anymore). +`select` has a `default` case as well, just like `switch`. When all the channels are not ready for use, it executes the default case (it doesn't wait for the channel anymore). select { case i := <-c: @@ -191,7 +191,7 @@ In the above examples, we only use one channel, but how can we deal with more th ## Timeout -Sometimes a goroutine is blocked, but how can we avoid this to prevent the whole program blocking? We can set a timeout in select to do this. +Sometimes a goroutine becomes blocked. How can we avoid this to prevent the whole program from blocking? It's simple, we can set a timeout in the select. func main() { c := make(chan int) @@ -213,27 +213,27 @@ Sometimes a goroutine is blocked, but how can we avoid this to prevent the whole ## Runtime goroutine -The package `runtime` has some functions to deal with goroutines. +The package `runtime` has some functions for dealing with goroutines. - `runtime.Goexit()` - Exits the current goroutine, but defer functions will be executed as usual. + Exits the current goroutine, but defered functions will be executed as usual. - `runtime.Gosched()` - Lets the scheduler executes other goroutines, and comes back at some point. + Lets the scheduler execute other goroutines and comes back at some point. - `runtime.NumCPU() int` - Returns number of CPU cores + Returns the number of CPU cores - `runtime.NumGoroutine() int` - Returns number of goroutines + Returns the number of goroutines - `runtime.GOMAXPROCS(n int) int` - Set how many CPU cores that you want to use + Sets how many CPU cores you want to use ## Links From 8c1dd40893d666d670de2aea61ccf37e81a9cb95 Mon Sep 17 00:00:00 2001 From: Anchor Date: Thu, 4 Sep 2014 23:38:31 -0700 Subject: [PATCH 08/20] Fixed a few typos for 02.8.md --- en/eBook/02.8.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/en/eBook/02.8.md b/en/eBook/02.8.md index 4ea20f8f..b1306758 100644 --- a/en/eBook/02.8.md +++ b/en/eBook/02.8.md @@ -17,10 +17,10 @@ In this chapter, we mainly introduced the 25 Go keywords. Let's review what they - `select` is used to switch over multiple channels for communication. - `interface` is used to define interfaces. - `struct` is used to define special customized types. -- `break`, `case`, `continue`, `for`, `fallthrough`, `else`, `if`, `switch`, `goto`, `default` were introduced in section 2.3. +- `break`, `case`, `continue`, `for`, `fallthrough`, `else`, `if`, `switch`, `goto` and `default` were introduced in section 2.3. - `chan` is the type of channel for communication among goroutines. - `type` is used to define customized types. -- `map` is used to define map which is like hash table in others languages. +- `map` is used to define map which is similar to hash tables in other languages. - `range` is used for reading data from `slice`, `map` and `channel`. If you understand how to use these 25 keywords, you've learned a lot of Go already. @@ -29,4 +29,4 @@ If you understand how to use these 25 keywords, you've learned a lot of Go alrea - [Directory](preface.md) - Previous section: [Concurrency](02.7.md) -- Next chapter: [Web foundation](03.0.md) \ No newline at end of file +- Next chapter: [Web foundation](03.0.md) From f6642633b4cabbee561730d55ac41bd127d744fe Mon Sep 17 00:00:00 2001 From: Anchor Date: Sat, 6 Sep 2014 23:19:13 -0700 Subject: [PATCH 09/20] Improve clarity, grammar and typos in 03.0.md and 03.1.md --- en/eBook/03.0.md | 2 +- en/eBook/03.1.md | 79 +++++++++++++++++++++++++----------------------- 2 files changed, 42 insertions(+), 39 deletions(-) diff --git a/en/eBook/03.0.md b/en/eBook/03.0.md index 48595244..ca192cff 100644 --- a/en/eBook/03.0.md +++ b/en/eBook/03.0.md @@ -1,6 +1,6 @@ #3 Web foundation -The reason you are reading this book is that you want to learn to build web applications in Go. As I said before, Go provides many powerful packages like `http`. It helps you a lot when you build web applications. I'll teach you everything you should know in following chapters, and we'll talk about some concepts of the web and how to run web applications in Go in this chapter. +The reason you are reading this book is that you want to learn to build web applications in Go. As i've said before, Go provides many powerful packages like `http`. These packages can help you a lot when trying to build web applications. I'll teach you everything you need to know in the following chapters, and we'll talk about some concepts of the web and how to run web applications in Go in this chapter. ## Links diff --git a/en/eBook/03.1.md b/en/eBook/03.1.md index f18515c4..d8cba55f 100644 --- a/en/eBook/03.1.md +++ b/en/eBook/03.1.md @@ -1,70 +1,73 @@ # Web working principles -Every time you open your browsers, type some URLs and press enter, then you will see the beautiful web pages appear on you screen. But do you know what is happening behind this simple action? +Every time you open your browsers, type some URLs and press enter, you will see beautiful web pages appear on your screen. But do you know what is happening behind these simple actions? -Normally, your browser is a client, after you typed URL, it sends requests to DNS server, get IP address of the URL. Then it finds the server in that IP address, asks to setup TCP connections. When the browser finished sending HTTP requests, server starts handling your request packages, then return HTTP response packages to your browser. Finally, the browser renders bodies of the web pages, and disconnects from the server. +Normally, your browser is a client. After you type a URL, it sends your request to a DNS server in order to get the IP address of that URL. Then it finds the server in that IP address and asks to setup TCP connections. When the browser is finished sending HTTP requests, the server starts handling your request packages, then returns HTTP response packages to your browser. Finally, the browser renders bodies of the web pages and disconnects from the server. ![](images/3.1.web2.png?raw=true) Figure 3.1 Processes of users visit a website -A web server also known as a HTTP server, it uses HTTP protocol to communicate with clients. All web browsers can be seen as clients. +A web server, also known as an HTTP server, uses the HTTP protocol to communicate with clients. All web browsers can be considered as clients. -We can divide web working principles to following steps: +We can divide the web's working principles into the following steps: - Client uses TCP/IP protocol to connect to server. - Client sends HTTP request packages to server. -- Server returns HTTP response packages to client, if request resources including dynamic scripts, server calls script engine first. +- Server returns HTTP response packages to client. If the requested resources include dynamic scripts, server calls script engine first. - Client disconnects from server, starts rendering HTML. -This a simple work flow of HTTP affairs, notice that every time server closes connections after sent data to clients, and waits for next request. +This is a simple work flow of HTTP affairs -notice that the server closes connections after sending data to clients every time, then waits for the next request. ## URL and DNS resolution -We are always using URL to access web pages, but do you know how URL works? +We always use URLs to access web pages, but do you know how URLs work? -The full name of URL is Uniform Resource Locator, this is for describing resources on the internet. Its basic form as follows. +The full name of a URL is Uniform Resource Locator. It's for describing resources on the internet and its basic form is as follows. scheme://host[:port#]/path/.../[?query-string][#anchor] - scheme assign underlying protocol(such as HTTP, HTTPS, ftp) + scheme assign underlying protocol (such as HTTP, HTTPS, FTP) host IP or domain name of HTTP server - port# default port is 80, and you can omit in this case. If you want to use other ports, you must to specify which port. For example, http://www.cnblogs.com:8080/ + port# default port is 80, and it can be omitted in this case. If you want to use other ports, you must specify which port. For example, http://www.cnblogs.com:8080/ path resources path query-string data are sent to server anchor anchor -DNS is abbreviation of Domain Name System, it's the name system for computer network services, it converts domain name to actual IP addresses, just like a translator. +DNS is an abbreviation of Domain Name System. It's the naming system for computer network services, and it converts domain names to actual IP addresses, just like a translator. ![](images/3.1.dns_hierachy.png?raw=true) Figure 3.2 DNS working principles -To understand more about its working principle, let's see detailed DNS resolution process as follows. +To understand more about its working principle, let's see the detailed DNS resolution process as follows. -1. After typed domain name `www.qq.com` in the browser, operating system will check if there is any mapping relationship in the hosts file for this domain name, if so then finished the domain name resolution. -2. If no mapping relationship in the hosts file, operating system will check if there is any cache in the DNS, if so then finished the domain name resolution. -3. If no mapping relationship in the hosts and DNS cache, operating system finds the first DNS resolution server in your TCP/IP setting, which is local DNS server at this time. When local DNS server received query, if the domain name that you want to query is contained in the local configuration of regional resources, then gives back results to the client. This DNS resolution is authoritative. -4. If local DNS server doesn't contain the domain name, and there is a mapping relationship in the cache, local DNS server gives back this result to client. This DNS resolution is not authoritative. -5. If local DNS server cannot resolve this domain name either by configuration of regional resource or cache, it gets into next step depends on the local DNS server setting. If the local DNS server doesn't enable forward mode, it sends request to root DNS server, then returns the IP of top level DNS server may know this domain name, `.com` in this case. If the first top level DNS server doesn't know, it sends request to next top level DNS server until the one that knows the domain name. Then the top level DNS server asks next level DNS server for `qq.com`, then finds the `www.qq.com` in some servers. -6. If the local DNS server enabled forward mode, it sends request to upper level DNS server, if the upper level DNS server also doesn't know the domain name, then keep sending request to upper level. Whether local DNS server enables forward mode, server's IP address of domain name returns to local DNS server, and local server sends it to clients. +1. After typing the domain name `www.qq.com` in the browser, the operating system will check if there are any mapping relationships in the hosts' files for this domain name. If so, then the domain name resolution is complete. +2. If no mapping relationships exist in the hosts' files, the operating system will check if any cache exists in the DNS. If so, then the domain name resolution is complete. +3. If no mapping relationships exist in both the host and DNS cache, the operating system finds the first DNS resolution server in your TCP/IP settings, which is likely your local DNS server. When the local DNS server receives the query, if the domain name that you want to query is contained within the local configuration of its regional resources, it returns the results to the client. This DNS resolution is authoritative. +4. If the local DNS server doesn't contain the domain name but a mapping relationship exists in the cache, the local DNS server gives back this result to the client. This DNS resolution is not authoritative. +5. If the local DNS server cannot resolve this domain name either by configuration of regional resources or cache, it will proceed to the next step, which depends on the local DNS server's settings. +-If the local DNS server doesn't enable forwarding, it routes the request to the root DNS server, then returns the IP address of a top level DNS server which may know the domain name, `.com` in this case. If the first top level DNS server doesn't recognize the domain name, it again reroutes the request to the next top level DNS server until it reaches one that recognizes the domain name. Then the top level DNS server asks this next level DNS server for the IP address corresponding to `www.qq.com`. +-If the local DNS server has forwarding enabled, it sends the request to an upper level DNS server. If the upper level DNS server also doesn't recognize the domain name, then the request keeps getting rerouted to higher levels until it finally reaches a DNS server which recognizes the domain name. + +Whether or not the local DNS server enables forwarding, the IP address of the domain name always returns to the local DNS server, and the local DNS server sends it back to the client. ![](images/3.1.dns_inquery.png?raw=true) Figure 3.3 DNS resolution work flow -`Recursive query process` means the enquirers are changing in the process, and enquirers do not change in `Iterative query process`. +`Recursive query process` simply means that the enquirers change in the process. Enquirers do not change in `Iterative query` processes. Now we know clients get IP addresses in the end, so the browsers are communicating with servers through IP addresses. ## HTTP protocol -HTTP protocol is the core part of web services. It's important to know what is HTTP protocol before you understand how web works. +The HTTP protocol is a core part of web services. It's important to know what the HTTP protocol is before you understand how the web works. -HTTP is the protocol that used for communicating between browsers and web servers, it is based on TCP protocol, and usually use port 80 in the web server side. It is a protocol that uses request-response model, clients send request and servers response. According to HTTP protocol, clients always setup a new connection and send a HTTP request to server in every affair. Server is not able to connect to client proactively, or a call back connection. The connection between the client and the server can be closed by any side. For example, you can cancel your download task and HTTP connection. It disconnects from server before you finish downloading. +HTTP is the protocol that is used to facilitate communication between browsers and web servers. It is based on the TCP protocol and usually uses port 80 on the side of the web server. It is a protocol that utilizes the request-response model -clients send requests and servers respond. According to the HTTP protocol, clients always setup new connections and send HTTP requests to servers. Servers are not able to connect to clients proactively, or establish callback connections. The connection between a client and a server can be closed by either side. For example, you can cancel your download request and HTTP connection and your browser will disconnect from the server before you finish downloading. -HTTP protocol is stateless, which means the server has no idea about the relationship between two connections, even though they are both from same client. To solve this problem, web applications use Cookie to maintain sustainable state of connections. +The HTTP protocol is stateless, which means the server has no idea about the relationship between the two connections even though they are both from same client. To solve this problem, web applications use cookies to maintain the state of connections. -Because HTTP protocol is based on TCP protocol, so all TCP attacks will affect the HTTP communication in your server, such as SYN Flood, DoS and DDoS. +Because the HTTP protocol is based on the TCP protocol, all TCP attacks will affect HTTP communications in your server. Examples of such attacks are SYN flooding, DoS and DDoS attacks. ### HTTP request package (browser information) @@ -79,19 +82,19 @@ Request packages all have three parts: request line, request header, and body. T // blank line // body, request resource arguments (for example, arguments in POST) -We use fiddler to get following request information. +We use fiddler to get the following request information. ![](images/3.1.http.png?raw=true) -Figure 3.4 Information of GET method caught by fiddler +Figure 3.4 Information of a GET request caught by fiddler ![](images/3.1.httpPOST.png?raw=true) -Figure 3.5 Information of POST method caught by fiddler +Figure 3.5 Information of a POST request caught by fiddler -**We can see that GET method doesn't have request body that POST does.** +**We can see that GET does not have a request body, unlike POST, which does.** -There are many methods you can use to communicate with servers in HTTP, and GET, POST, PUT, DELETE are the basic 4 methods that we use. A URL represented a resource on the network, so these 4 method means query, change, add and delete operations. GET and POST are most commonly used in HTTP. GET appends data to the URL and uses `?` to break up them, uses `&` between arguments, like `EditPosts.aspx?name=test1&id=123456`. POST puts data in the request body because URL has length limitation by browsers, so POST can submit much more data than GET method. Also when we submit our user name and password, we don't want this kind of information appear in the URL, so we use POST to keep them invisible. +There are many methods you can use to communicate with servers in HTTP; GET, POST, PUT and DELETE are the 4 basic methods that we typically use. A URL represents a resource on a network, so these 4 methods define the query, change, add and delete operations that can act on these resources. GET and POST are very commonly used in HTTP. GET can append query parameters to the URL, using `?` to separate the URL and parameters and `&` between the arguments, like `EditPosts.aspx?name=test1&id=123456`. POST puts data in the request body because the URL implements a length limitation via the browser. Thus, POST can submit much more data than GET. Also, when we submit user names and passwords, we don't want this kind of information to appear in the URL, so we use POST to keep them invisible. ### HTTP response package (server information) @@ -107,9 +110,9 @@ Let's see what information is contained in the response packages. // blank line Date: Sun, 7 Sep 2014 23:07:12 -0700 Subject: [PATCH 10/20] Fix grammar and typos for 03.2.md --- en/eBook/03.2.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/en/eBook/03.2.md b/en/eBook/03.2.md index f32641ae..af81f3ff 100644 --- a/en/eBook/03.2.md +++ b/en/eBook/03.2.md @@ -1,6 +1,6 @@ # 3.2 Build a simple web server -We talked about that web applications are based on HTTP protocol, and Go provides fully ability for HTTP in package `net/http`, it's very easy to setup a web server by using this package. +We've discussed that web applications are based on the HTTP protocol, and Go provides full HTTP support in the `net/http` package. It's very easy to set a web server up using this package. ## Use http package setup a web server @@ -34,32 +34,32 @@ We talked about that web applications are based on HTTP protocol, and Go provide } } -After we executed above code, it starts listening to port 9090 in local host. +After we execute the above code, the server begins listening to port 9090 in local host. -Open your browser and visit `http://localhost:9090`, you can see that `Hello astaxie` is on your screen. +Open your browser and visit `http://localhost:9090`. You can see that `Hello astaxie` is on your screen. -Let's try another address with arguments: `http://localhost:9090/?url_long=111&url_long=222` +Let's try another address with additional arguments: `http://localhost:9090/?url_long=111&url_long=222` -Now see what happened in both client and server sides. +Now let's see what happens on both the client and server sides. -You should see following information in your server side: +You should see the following information on the server side: ![](images/3.2.goweb.png?raw=true) Figure 3.8 Server printed information -As you can see, we only need to call two functions to build a simple web server. +As you can see, we only need to call two functions in order to build a simple web server. -If you are working with PHP, you probably want to ask do we need something like Nginx or Apache, the answer is we don't need because Go listens to TCP port by itself, and the function `sayhelloName` is the logic function like controller in PHP. +If you are working with PHP, you're probably asking whether or not we need something like Nginx or Apache. The answer is we no, since Go listens to the TCP port by itself, and the function `sayhelloName` is the logic function just like a controller in PHP. -If you are working with Python, you should know tornado, and the above example is very similar to that. +If you are working with Python you should know tornado, and the above example is very similar to that. If you are working with Ruby, you may notice it is like script/server in ROR. -We use two simple functions to setup a simple web server in this section, and this simple server has already had ability for high concurrency. We will talk about how to use this feature in next two sections. +We used two simple functions to setup a simple web server in this section, and this simple server already has the capacity for high concurrency operations. We will talk about how to utilize this in the next two sections. ## Links - [Directory](preface.md) - Previous section: [Web working principles](03.1.md) -- Next section: [How Go works with web](03.3.md) \ No newline at end of file +- Next section: [How Go works with web](03.3.md) From c313c0e24bb5aaa529fc11e14285f74c4a85a8c4 Mon Sep 17 00:00:00 2001 From: Anchor Date: Mon, 8 Sep 2014 21:31:32 -0700 Subject: [PATCH 11/20] Fixed typos and grammar for 03.3.md --- en/eBook/03.3.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/en/eBook/03.3.md b/en/eBook/03.3.md index 416563b5..4c4a2717 100644 --- a/en/eBook/03.3.md +++ b/en/eBook/03.3.md @@ -1,8 +1,8 @@ # 3.3 How Go works with web -We learned to use `net/http` package to build a simple web server in previous section, but all the working principles are the same as we talked in first section of this chapter. +We learned to use the `net/http` package to build a simple web server in the previous section, and all those working principles are the same as those we will talk about in the first section of this chapter. -## Some concepts in web working principles +## Concepts in web principles Request: request data from users, including POST, GET, Cookie and URL. @@ -10,29 +10,29 @@ Response: response data from server to clients. Conn: connections between clients and servers. -Handler: logic of handle request and produce response. +Handler: Request handling logic and response generation. ## http package operating mechanism -The following picture shows that work flow of Go's web server. +The following picture shows the work flow of a Go web server. ![](images/3.3.http.png?raw=true) Figure 3.9 http work flow -1. Create listening socket, listen to a port and wait for clients. +1. Create a listening socket, listen to a port and wait for clients. 2. Accept requests from clients. -3. Handle requests, read HTTP header, if it uses POST method, also need to read data in message body and give them to handlers. Finally, socket returns response data to clients. +3. Handle requests, read HTTP header. If the request uses POST method, read data in the message body and pass them to handlers. Finally, socket returns response data to clients. -Once we know the answers of three following questions, it's easy to know how web works in Go. +Once we know the answers to the three following questions, it's easy to know how the web works in Go. -- How to listen to a port? -- How to accept client requests? -- How to allocate handlers? +- How do we listen to a port? +- How do we accept client requests? +- How do we allocate handlers? -In the previous section we saw that Go uses `ListenAndServe` to handle these problems: initialize a server object, call `net.Listen("tcp", addr)` to setup a TCP listener and listen to specific address and port. +In the previous section we saw that Go uses `ListenAndServe` to handle these steps: initialize a server object, call `net.Listen("tcp", addr)` to setup a TCP listener and listen to a specific address and port. -Let's take a look at `http` package's source code. +Let's take a look at the `http` package's source code. //Build version go1.1.2. func (srv *Server) Serve(l net.Listener) error { @@ -66,15 +66,15 @@ Let's take a look at `http` package's source code. } -How to accept client requests after listened to the port? In the source code, we can see that it calls `srv.Serve(net.Listener)` to handle client requests. In body of function there is a `for{}`, it accepts request, creates a new connection, and then starts a new goroutine, and passes request data to this goroutine: `go c.serve()`. This is how Go supports high concurrency, and every goroutine is independent. +How do we accept client requests after we begin listening to a port? In the source code, we can see that `srv.Serve(net.Listener)` is called to handle client requests. In the body of the function there is a `for{}`. It accepts a request, creates a new connection then starts a new goroutine, passing the request data to the `go c.serve()` goroutine. This is how Go supports high concurrency, and every goroutine is independent. -Now, how to use specific functions to handle requests? `conn` parses request `c.ReadRequest()` at first, and get corresponding handler: `handler := c.server.Handler` which is the second argument we passed when we called `ListenAndServe`. Because we passed `nil`, so Go uses it's default handler `handler = DefaultServeMux`. So what is `DefaultServeMux` doing here? Well, this is the variable of router at this time, it calls handler functions for specific URLs. Did we setting this? Yes, we did. Remember in the first line we used `http.HandleFunc("/", sayhelloName)`. It's like you use this function to register the router rule for "/" path. When the URL is `/`, router calls function `sayhelloName`. DefaultServeMux calls ServerHTTP to get handler function for different path, and it calls `sayhelloName` in this case. Finally, server writes data and response to clients. +How do we use specific functions to handle requests? `conn` parses request `c.ReadRequest()` at first, then gets the corresponding handler: `handler := c.server.Handler` which is the second argument we passed when we called `ListenAndServe`. Because we passed `nil`, Go uses its default handler `handler = DefaultServeMux`. So what is `DefaultServeMux` doing here? Well, its the router variable which can call handler functions for specific URLs. Did we set this? Yes, we did. We did this in the first line where we used `http.HandleFunc("/", sayhelloName)`. We're using this function to register the router rule for the "/" path. When the URL is `/`, the router calls the function `sayhelloName`. DefaultServeMux calls ServerHTTP to get handler functions for different paths, calling `sayhelloName` in this specific case. Finally, the server writes data and responds to clients. Detailed work flow: ![](images/3.3.illustrator.png?raw=true) -Figure 3.10 Work flow of handling a HTTP request +Figure 3.10 Work flow of handling an HTTP request I think you should know how Go runs web servers now. From 9516349850a972c8bd639ddee9a6275a13f73c4c Mon Sep 17 00:00:00 2001 From: Anchor Date: Tue, 9 Sep 2014 23:14:34 -0700 Subject: [PATCH 12/20] Edited 03.4.md for grammar, typos and improved clarity --- en/eBook/03.4.md | 50 ++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/en/eBook/03.4.md b/en/eBook/03.4.md index b367689b..08062cfb 100644 --- a/en/eBook/03.4.md +++ b/en/eBook/03.4.md @@ -1,12 +1,12 @@ # 3.4 Get into http package -In previous sections, we learned the work flow of web, and talked about a little about `http` package. In this section, we are going to learn two core functions in `http` package: Conn, ServeMux. +In previous sections, we learned about the work flow of the web and talked a little bit about Go's `http` package. In this section, we are going to learn about two core functions in the `http` package: Conn and ServeMux. ## goroutine in Conn -Unlike normal HTTP servers, Go uses goroutine for every affair that created by Conn in order to achieve high concurrency and performance, so every affair is independent. +Unlike normal HTTP servers, Go uses goroutines for every job initiated by Conn in order to achieve high concurrency and performance, so every job is independent. -Go uses following code to wait for new connections from clients. +Go uses the following code to wait for new connections from clients. c, err := srv.newConn(rw) if err != nil { @@ -14,16 +14,16 @@ Go uses following code to wait for new connections from clients. } go c.serve() -As you can see, it creates goroutine for every connection, and passes handler that is able to read data from request to the goroutine. +As you can see, it creates a new goroutine for every connection, and passes the handler that is able to read data from the request to the goroutine. ## Customized ServeMux -We used default router in previous section when talked about conn.server, the router passed request data to back-end handler. +We used Go's default router in previous sections when discussing conn.server, with the router passing request data to a back-end handler. -The struct of default router: +The struct of the default router: type ServeMux struct { - mu sync.RWMutex // because of concurrency, we have to use mutex here + mu sync.RWMutex // because of concurrency, we have to use a mutex here m map[string]muxEntry // router rules, every string mapping to a handler } @@ -40,7 +40,7 @@ The interface of Handler: ServeHTTP(ResponseWriter, *Request) // routing implementer } -`Handler` is a interface, but the function `sayhelloName` didn't implement this interface, why could we add it as handler? Because there is another type `HandlerFunc` in `http` package. We called `HandlerFunc` to define our `sayhelloName`, so `sayhelloName` implemented `Handler` at the same time. it's like we call `HandlerFunc(f)`, and function `f` is forced converted to type `HandlerFunc`. +`Handler` is an interface, but if the function `sayhelloName` didn't implement this interface, then how did we add it as handler? The answer lies in another type called `HandlerFunc` in the `http` package. We called `HandlerFunc` to define our `sayhelloName` method, so `sayhelloName` implemented `Handler` at the same time. It's like we're calling `HandlerFunc(f)`, and the function `f` is force converted to type `HandlerFunc`. type HandlerFunc func(ResponseWriter, *Request) @@ -49,9 +49,9 @@ The interface of Handler: f(w, r) } -How the router calls handlers after we set router rules? +How does the router call handlers after we set the router rules? -The router calls `mux.handler.ServeHTTP(w, r)` when it receives requests. In other words, it calls `ServeHTTP` interface of handlers. +The router calls `mux.handler.ServeHTTP(w, r)` when it receives requests. In other words, it calls the `ServeHTTP` interface of the handlers which have implemented it. Now, let's see how `mux.handler` works. @@ -70,9 +70,9 @@ Now, let's see how `mux.handler` works. return h } -The router uses URL as a key to find corresponding handler that saved in map, and calls handler.ServeHTTP to execute functions to handle data. +The router uses the request's URL as a key to find the corresponding handler saved in the map, then calls handler.ServeHTTP to execute functions to handle the data. -You should understand the router work flow now, and Go actually supports customized routers. The second argument of `ListenAndServe` is for configuring customized router, it's a interface of `Handler`. Therefore, any router implements interface `Handler` that can be used. +You should understand the default router's work flow by now, and Go actually supports customized routers. The second argument of `ListenAndServe` is for configuring customized routers. It's an interface of `Handler`. Therefore, any router that implements the `Handler` interface can be used. The following example shows how to implement a simple router. @@ -106,27 +106,27 @@ The following example shows how to implement a simple router. ## Go code execution flow -Let's take a look at the list of whole execution flow. +Let's take a look at the whole execution flow. - Call `http.HandleFunc` 1. Call HandleFunc of DefaultServeMux 2. Call Handle of DefaultServeMux 3. Add router rules to map[string]muxEntry of DefaultServeMux - Call `http.ListenAndServe(":9090", nil)` - 1. Instantiated Server - 2. Call ListenAndServe of Server - 3. Call net.Listen("tcp", addr) to listen to port. - 4. Start a loop, and accept requests in loop body. - 5. Instantiated a Conn and start a goroutine for every request: `go c.serve()`. - 6. Read request data: `w, err := c.readRequest()`. - 7. Check handler is empty or not, if it's empty then use DefaultServeMux. - 8. Call ServeHTTP of handler. - 9. Execute code in DefaultServeMux in this case. + 1. Instantiate Server + 2. Call ListenAndServe method of Server + 3. Call net.Listen("tcp", addr) to listen to port + 4. Start a loop and accept requests in the loop body + 5. Instantiate a Conn and start a goroutine for every request: `go c.serve()` + 6. Read request data: `w, err := c.readRequest()` + 7. Check whether handler is empty or not, if it's empty then use DefaultServeMux + 8. Call ServeHTTP of handler + 9. Execute code in DefaultServeMux in this case 10. Choose handler by URL and execute code in that handler function: `mux.handler.ServeHTTP(w, r)` 11. How to choose handler: - A. Check router rules for this URL. - B. Call ServeHTTP in that handler if there is one. - C. Call ServeHTTP of NotFoundHandler otherwise. + A. Check router rules for this URL + B. Call ServeHTTP in that handler if there is one + C. Call ServeHTTP of NotFoundHandler otherwise ## Links From c811182c2681fbeb73458930470eeeacef5c3349 Mon Sep 17 00:00:00 2001 From: Anchor Date: Tue, 9 Sep 2014 23:16:51 -0700 Subject: [PATCH 13/20] Fix typos and grammar flow in 03.5.md --- en/eBook/03.5.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/en/eBook/03.5.md b/en/eBook/03.5.md index 4c37f6d2..2d24cf9f 100644 --- a/en/eBook/03.5.md +++ b/en/eBook/03.5.md @@ -1,11 +1,11 @@ # 3.5 Summary -In this chapter, we introduced HTTP, DNS resolution flow and how to build a simple web server. Then we talked about how Go implements web server for us by looking at source code of package `net/http`. +In this chapter, we introduced HTTP, DNS resolution flow and how to build a simple web server. Then we talked about how Go implements web servers for us by looking at the source code of the `net/http` package. -I hope you know much more about web development, and you should see that it's quite easy and flexible to build a web application in Go. +I hope that you now know much more about web development, and you should see that it's quite easy and flexible to build a web application in Go. ## Links - [Directory](preface.md) - Previous section: [Get into http package](03.4.md) -- Next chapter: [User form](04.0.md) \ No newline at end of file +- Next chapter: [User form](04.0.md) From 81d8c3fdbee2ec64fef5e484022d283cfa09cd8f Mon Sep 17 00:00:00 2001 From: Anchor Date: Wed, 10 Sep 2014 22:28:15 -0700 Subject: [PATCH 14/20] Fix grammar, typos and sentence flow for clarity --- en/eBook/04.0.md | 10 +++++----- en/eBook/04.1.md | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/en/eBook/04.0.md b/en/eBook/04.0.md index ddbadca1..a6cf694e 100644 --- a/en/eBook/04.0.md +++ b/en/eBook/04.0.md @@ -1,8 +1,8 @@ # 4 User form -User form is the tool that is commonly used when we develop web applications, it provides ability to communicate between clients and servers. You must know form very much if you are web developers; if you are C/C++ programmers, you may want to ask: what is the user form? +A user form is something that is very commonly used when we develop web applications. It provides the ability to communicate between clients and servers. You must be very familiar with forms if you are a web developer; if you are a C/C++ programmer, you may want to ask: what is a user form? -Form is the area that contains form elements. Users can input information in these elements, like text box, drop down list, radio buttons, check box, etc. We use form tag `
` to define form. +A form is an area that contains form elements. Users can input information into form elements like text boxes, drop down lists, radio buttons, check boxes, etc. We use the form tag `` to define forms. ... @@ -10,11 +10,11 @@ Form is the area that contains form elements. Users can input information in the ...
-Go has already had many convenient functions to deal with use form, like you can easily get form data in HTTP requests, and there are easy to integrate to your own web applications. In section 4.1, we are going to talk about how to handle form data in Go, and because you cannot believe any data from clients, you have to verify data before use them. After that, we will show some examples about verifying form data in section 4.2. +Go already has many convenient functions to deal with user forms. You can easily get form data in HTTP requests, and they are easy to integrate into your own web applications. In section 4.1, we are going to talk about how to handle form data in Go. Also, since you cannot trust any data coming from the client side, you must first verify the data before using it. We'll go through some examples about how to verify form data in section 4.2. -We say that HTTP is stateless, how can we identify that these forms are from same user? And how to make sure that one form can only be submitted once? We have more detailed explanation about Cookie (Cookie is the information that can be saved in the client side, and put in the request header when the request is sent to the server) in both sections 4.3 and 4.4. +We say that HTTP is stateless. How can we identify that certain forms are from the same user? And how do we make sure that one form can only be submitted once? We'll look at some details concerning cookies (a cookie is information that can be saved on the client side and added to the request header when the request is sent to the server) in both sections 4.3 and 4.4. -Another big feature of form is uploading files. In section 4.5, you will learn how to use this feature and control file size before it starts uploading in Go. +Another big use-case of forms is uploading files. In section 4.5, you will learn how to do this as well as controlling the file upload size before it begins uploading, in Go. ## Links diff --git a/en/eBook/04.1.md b/en/eBook/04.1.md index 5f1d2410..a95ade6c 100644 --- a/en/eBook/04.1.md +++ b/en/eBook/04.1.md @@ -1,6 +1,6 @@ # 4.1 Process form inputs -Before we start talking, let's take a look a simple example of use form, save it as `login.gtpl` in your project folder. +Before we begin, let's take a look at a simple example of a typical user form, saved as `login.gtpl` in your project folder. @@ -15,9 +15,9 @@ Before we start talking, let's take a look a simple example of use form, save it -This form will submit to `/login` in server. After user clicked log in button, the data will be sent to `login` handler in server router. Then we need to know it uses POST method or GET. +This form will submit to `/login` on the server. After the user clicks the login button, the data will be sent to the `login` handler registered by the server router. Then we need to know whether it uses the POST method or GET. -It's easy to know through `http` package, let's see how to handle form data in log in page. +This is easy to find out using the `http` package. Let's see how to handle the form data on the login page. package main @@ -66,27 +66,27 @@ It's easy to know through `http` package, let's see how to handle form data in l } -Now we know use `r.Method` to get request method, and it returns a string like "GET", "POST", "PUT", etc. +Here we use `r.Method` to get the request method, and it returns an http verb -"GET", "POST", "PUT", etc. -In function `login`, we use `r.Method` to check if it's a log in page or log in process logic, which means you just open this page, or you are trying to log in. Serve shows page only when it uses GET method, process log in logic when it uses POST method. +In the `login` function, we use `r.Method` to check whether it's a login page or login processing logic. In other words, we check to see whether the user is simply opening the page, or trying to log in. Serve shows the page only when the request comes in via the GET method, and it executes the login logic when the request uses the POST method. -You should see following interface after you opened `http://127.0.0.1:9090/login` in your browser. +You should see the following interface after opening `http://127.0.0.1:9090/login` in your browser. ![](images/4.1.login.png?raw=true) -Figure 4.1 User log in interface +Figure 4.1 User login interface -Server will not print anything after we typed user name and password because handler doesn't parse form until we call `r.ParseForm()`. Let's add `r.ParseForm()` before `fmt.Println("username:", r.Form["username"])`, compile and test again. You should see information is printed in server side now. +The server will not print anything until after we type in a username and password, because the handler doesn't parse the form until we call `r.ParseForm()`. Let's add `r.ParseForm()` before `fmt.Println("username:", r.Form["username"])`, compile our program and test it again. You will find that the information is printed on the server side now. -`r.Form` contains all request arguments, like query-string in URL, data in POST and PUT. If the data have conflicts like have same name, it will save into a slice with multiple values. In Go documentation, it says Go will save data of GET and POST in different places. +`r.Form` contains all of the request arguments, for instance the query-string in the URL and the data in POST and PUT. If the data has conflicts, for example parameters that have the same name, the server will save the data into a slice with multiple values. The Go documentation states that Go will save the data from GET and POST requests in different places. -Try to change value of action in form `http://127.0.0.1:9090/login` to `http://127.0.0.1:9090/login?username=astaxie` in file `login.gtpl`, test again, and you will see the slice is printed in server side. +Try changing the value of the action in the form `http://127.0.0.1:9090/login` to `http://127.0.0.1:9090/login?username=astaxie` in the `login.gtpl` file, test it again, and you will see that the slice is printed on the server side. ![](images/4.1.slice.png?raw=true) Figure 4.2 Server prints request data -The type of `request.Form` is `url.Value`, it saves data with format `key=value`. +The type of `request.Form` is `url.Value`. It saves data with the format `key=value`. v := url.Values{} v.Set("name", "Ava") @@ -98,7 +98,7 @@ The type of `request.Form` is `url.Value`, it saves data with format `key=value` fmt.Println(v.Get("friend")) fmt.Println(v["friend"]) -**Tips** Request has ability to access form data by method `FormValue()`. For example, you can change `r.Form["username"]` to `r.FormValue("username")`, and it calls `r.ParseForm` automatically. Notice that it returns the first value if there are arguments with same name, and it returns empty string if there is no such argument. +**Tips** Requests have the ability to access form data using the `FormValue()` method. For example, you can change `r.Form["username"]` to `r.FormValue("username")`, and Go calls `r.ParseForm` automatically. Notice that it returns the first value if there are arguments with the same name, and it returns an empty string if there is no such argument. ## Links From afa42ed09906c4de363a50d5333f63f506bb7a6c Mon Sep 17 00:00:00 2001 From: Anchor Date: Thu, 11 Sep 2014 21:56:45 -0700 Subject: [PATCH 15/20] Fix typos, grammar and flow in 04.2.md --- en/eBook/04.2.md | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/en/eBook/04.2.md b/en/eBook/04.2.md index 21a2c157..291e4657 100644 --- a/en/eBook/04.2.md +++ b/en/eBook/04.2.md @@ -1,22 +1,22 @@ # 4.2 Verification of inputs -The most important principle in web development is that you cannot trust anything from user form, you have to verify all data before use them. You may know many websites are invaded by this problem which is simple but crucial. +One of the most important principles in web development is that you cannot trust anything from client side user forms. You have to verify all incoming data before use it. Many websites are affected by this problem, which is simple yet crucial. -There are two ways to verify form data that commonly used, the one is JavaScript verification in front-end, and another one is server verification in back-end. In this section, we are going to talk about the server verification in web development. +There are two ways of verify form data that are commonly used. One is JavaScript verification in the front-end, and the other is server verification in the back-end. In this section, we are going to talk about server side verification in web development. ## Required fields -Sometimes you ask users to input some fields but they don't, for example we need user name in previous section. You can use function `len` to get length of field to make sure users input this information. +Sometimes we require that users input some fields but they don't, for example in the previous section when we required a username. You can use the `len` function to get the length of a field in order to ensure that users have entered this information. if len(r.Form["username"][0])==0{ // code for empty field } -`r.Form` uses different treatments of different types of form elements when they are blanks. For empty text box, text area and file upload, it returns empty string; for radio button and check box, it doesn't even create corresponding items, and you will get errors if you try to access it. Therefore, we'd better use `r.Form.Get()` to get filed values because it always returns empty if the value does not exist. On the other hand, `r.Form.Get()` can only get one field value every time, so you need to use `r.Form` to get values in map. +`r.Form` treats different form element types differently when they are blank. For empty textboxes, text areas and file uploads, it returns an empty string; for radio buttons and check boxes, it doesn't even create the corresponding items. Instead, you will get errors if you try to access it. Therefore, it's safer to use `r.Form.Get()` to get filed values since it will always return empty if the value does not exist. On the other hand, `r.Form.Get()` can only get one field value at a time, so you need to use `r.Form` to get the map of values. ## Numbers -Sometimes you only need numbers for the field value. For example, you need age of users, like 50 or 10, instead of "old enough" or "young man". If we need positive numbers, we can convert to `int` type first and process them. +Sometimes you only need numbers for the field value. For example, let's say that you require the age of a user in integer form only, i.e 50 or 10, instead of "old enough" or "young man". If we require a positive number, we can convert the value to the `int` type first, then process it. getint,err:=strconv.Atoi(r.Form.Get("age")) if err!=nil{ @@ -28,17 +28,17 @@ Sometimes you only need numbers for the field value. For example, you need age o // too big } -Another way to do this is using regular expression. +Another way to do this is using regular expressions. if m, _ := regexp.MatchString("^[0-9]+$", r.Form.Get("age")); !m { return false } -For high performance purpose, regular expression is not an efficient way, but simple regular expression is fast enough. If you know regular expression before, you should it's a very convenient way to verify data. Notice that Go uses [RE2](http://code.google.com/p/re2/wiki/Syntax), all UTF-8 characters are supported. +For high performance purposes, regular expressions are not efficient, however simple regular expressions are usually fast enough. If you are familiar with regular expressions, it's a very convenient way to verify data. Notice that Go uses [RE2](http://code.google.com/p/re2/wiki/Syntax), so all UTF-8 characters are supported. ## Chinese -Sometimes we need users to input their Chinese name, we have to verify they use all Chinese rather than random characters. For Chinese verification, regular expression is the only way. +Sometimes we need users to input their Chinese names and we have to verify that they all use Chinese rather than random characters. For Chinese verification, regular expressions are the only way. if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", r.Form.Get("realname")); !m { return false @@ -46,7 +46,7 @@ Sometimes we need users to input their Chinese name, we have to verify they use ## English letters -Sometimes we need users to input English letters. For example, we need someone's English name, like astaxie instead of asta谢. We can easily use regular expression to do verification. +Sometimes we need users to input only English letters. For example, we require someone's English name, like astaxie instead of asta谢. We can easily use regular expressions to perform our verification. if m, _ := regexp.MatchString("^[a-zA-Z]+$", r.Form.Get("engname")); !m { return false @@ -54,7 +54,7 @@ Sometimes we need users to input English letters. For example, we need someone's ## E-mail address -If you want to know if users input valid E-mail address, you can use following regular expression: +If you want to know whether users have entered valid E-mail addresses, you can use the following regular expression: if m, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`, r.Form.Get("email")); !m { fmt.Println("no") @@ -64,19 +64,19 @@ If you want to know if users input valid E-mail address, you can use following r ## Drop down list -When we need item in our drop down list, but we get some values that are made by hackers, how can we prevent it? +Let's say we require an item from our drop down list, but instead we get a value fabricated by hackers. How do we prevent this from happening? -Suppose we have following ``: -Then, we use following way to verify: +We can use the following strategy to sanitize our input: - slice:=[]string{"apple","pear","banane"} + slice:=[]string{"apple","pear","banana"} for _, v := range slice { if v == r.Form.Get("fruit") { @@ -85,16 +85,16 @@ Then, we use following way to verify: } return false -All functions I showed above are in my open source project for operating slice and map: [https://github.com/astaxie/beeku](https://github.com/astaxie/beeku) +All the functions I've shown above are in my open source project for operating on slices and maps: [https://github.com/astaxie/beeku](https://github.com/astaxie/beeku) ## Radio buttons -If we want to know the user is male or female, we may use a radio button, return 1 for male and 2 for female. However, there is a little boy is reading book about HTTP, and send to you 3, will your program have exception? So we need to use same way for drop down list to make sure all values are expected. +If we want to know whether the user is male or female, we may use a radio button, returning 1 for male and 2 for female. However, some little kid who just read his first book on HTTP, decides to send to you a 3. Will your program have have exception? As you can see, we need to use the same method as we did for our drop down list to make sure that only expected values are returned by our radio button. Male Female -And we use following code to do verification: +And we use following code to verify the input: slice:=[]int{1,2} @@ -107,13 +107,13 @@ And we use following code to do verification: ## Check boxes -Suppose there are some check boxes for users' interests, and you don't want extra values as well. +Suppose there are some check boxes for user interests, and that you don't want extraneous values here either. Football Basketball Tennis -Here is a little bit different in verification between radio buttons and check boxes because we get a slice from check boxes. +In this case, the sanitization is a little bit different than verifying the button and check box inputs since here we get a slice from the check boxes. slice:=[]string{"football","basketball","tennis"} a:=Slice_diff(r.Form["interest"],slice) @@ -125,14 +125,14 @@ Here is a little bit different in verification between radio buttons and check b ## Date and time -Suppose you want to make users input valid date or time. Go has package `time` to convert year, month, day to corresponding time, then it's easy to check it. +Suppose you want users to input valid dates or times. Go has the `time` package for converting year, month and day to their corresponding times. After that, it's easy to check it. t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) fmt.Printf("Go launched at %s\n", t.Local()) -After you had time, you can use package `time` for more operations depend on your purposes. +After you have the time, you can use the `time` package for more operations, depending on your needs. -We talked about some common form data verification in server side, I hope you understand more about data verification in Go, especially how to use regular expression. +In this section, we've discussed some common methods for verifying form data server side. I hope that you now understand more about data verification in Go, especially how to use regular expressions to your advantage. ## Links From 67d57534cd38fc28bd44635e461c391bbc0809d3 Mon Sep 17 00:00:00 2001 From: Anchor Date: Fri, 12 Sep 2014 16:56:44 -0700 Subject: [PATCH 16/20] Correct grammar errors in 04.3.md --- en/eBook/04.3.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/en/eBook/04.3.md b/en/eBook/04.3.md index 06bd363d..edcc8a82 100644 --- a/en/eBook/04.3.md +++ b/en/eBook/04.3.md @@ -1,19 +1,19 @@ # 4.3 Cross site scripting -Today's websites have much more dynamic content in order to improve user experience, which means we can provide dynamic information depends on every individual's behavior. However, there is a thing called "Cross site scripting" (known as "XSS") always attacking dynamic websites, and static websites are completely fine at this time. +Today's websites have much more dynamic content in order to improve user experience, which means that we must provide dynamic information depending on every individual's behavior. Unfortunately, there is a thing called "Cross site scripting" (known as "XSS") always attacking dynamic websites, from which static websites are completely fine at this time. -Attackers often inject malicious scripts like JavaScript, VBScript, ActiveX or Flash into those websites that have loopholes. Once they have successful injection, your user information will be stolen and your website will full of spam, also they can change user settings to whatever they want. +Attackers often inject malicious scripts like JavaScript, VBScript, ActiveX or Flash into those websites that have loopholes. Once they have successfully injected their scripts, user information can be stolen and your website can be flooded with spam. The attackers can also change user settings to whatever they want. -If you want to prevent this kind of attack, you'd better combine two following approaches: +If you want to prevent this kind of attack, you should combine the two following approaches: -- Verification all data from users, which we talked about previous section. -- Give special handling for data that will be responded to clients, in order to prevent any injected script runs on browsers. +- Verification of all data from users, which we talked about in the previous section. +- Carefully handle data that will be sent to clients in order to prevent any injected scripts from running on browsers. -So how can we do these two jobs in Go? Fortunately, package `html/template` has some useful functions to escape data as follows: +So how can we do these two things in Go? Fortunately, the `html/template` package has some useful functions to escape data as follows: - `func HTMLEscape(w io.Writer, b []byte)` escapes b to w. -- `func HTMLEscapeString(s string) string` returns string after escaped from s. -- `func HTMLEscaper(args ...interface{}) string` returns string after escaped from multiple arguments. +- `func HTMLEscapeString(s string) string` returns a string after escaping from s. +- `func HTMLEscaper(args ...interface{}) string` returns a string after escaping from multiple arguments. Let's change the example in section 4.1: @@ -21,13 +21,13 @@ Let's change the example in section 4.1: fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password"))) template.HTMLEscape(w, []byte(r.Form.Get("username"))) // responded to clients -If we try to input user name as ``, we will see following content in the browser: +If someone tries to input the username as ``, we will see the following content in the browser: ![](images/4.3.escape.png?raw=true) Figure 4.3 JavaScript after escaped -Functions in package `html/template` help you escape all HTML tags, what if you just want to print `` to browsers? You should use `text/template` instead. +Functions in the `html/template` package help you to escape all HTML tags. What if you just want to print `` to browsers? You should use `text/template` instead. import "text/template" ... @@ -38,8 +38,8 @@ Output: Hello, ! -Or you can use type `template.HTML`: -Variable content will not be escaped if it's type is `template.HTML`. +Or you can use the `template.HTML` type : +Variable content will not be escaped if its type is `template.HTML`. import "html/template" ... @@ -50,7 +50,7 @@ Output: Hello, ! -One more example of escape +One more example of escaping: import "html/template" ... From 35414e9d8b2b5b08986902e32a5a71974a3c4a89 Mon Sep 17 00:00:00 2001 From: Anchor Date: Sat, 13 Sep 2014 09:40:43 -0700 Subject: [PATCH 17/20] Fix typos and grammar for 04.4.md --- en/eBook/04.4.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/en/eBook/04.4.md b/en/eBook/04.4.md index c93c4691..93792b5d 100644 --- a/en/eBook/04.4.md +++ b/en/eBook/04.4.md @@ -1,10 +1,10 @@ # 4.4 Duplicate submissions -I don't know if you have ever seen some blogs or BBS have more then one posts are exactly same, but I can tell you it's because users did duplicate submissions of post form at that time. There are batch of reasons can cause duplicate submissions, sometimes users just double click the submit button, or they want to modify some content after post and press back button, or it's by purpose of malicious users in some vote websites. It's easy to see how the duplicate submissions lead to many problems, so we have to use effective means to prevent it. +I don't know if you've ever seen some blogs or BBS' that have more than one posts that are exactly the same, but I can tell you that it's because users submitted duplicate post forms. There many things that can cause duplicate submissions; sometimes users just double click the submit button, or they want to modify some content after posting and press the back button. Other times it's the intentional actions of malicious users. It's easy to see how duplicate submissions can lead to many problems. Thus, we have to use effective means to prevent it. -The solution is that add a hidden field with unique token to your form, and check this token every time before processing data. Also, if you are using Ajax to submit form, use JavaScript to disable submit button once submitted. +The solution is to add a hidden field with a unique token to your form, and to always check this token before processing the incoming data. Also, if you are using Ajax to submit a form, use JavaScript to disable the submit button once the form has been submitted. -Let's improve example in section 4.2: +Let's improve the example from section 4.2: Football Basketball @@ -14,7 +14,7 @@ Let's improve example in section 4.2: -We used MD5(time stamp) to generate token, and added to hidden field and session in server side(Chapter 6), then we can use this token to check if this form was submitted. +We use an MD5 hash (time stamp) to generate the token, and added it to both a hidden field on the client side form and a session cookie on the server side (Chapter 6). We can then use this token to check whether or not this form was submitted. func login(w http.ResponseWriter, r *http.Request) { fmt.Println("method:", r.Method) // get request method @@ -44,14 +44,14 @@ We used MD5(time stamp) to generate token, and added to hidden field and session ![](images/4.4.token.png?raw=true) -Figure 4.4 The content in browser after added token +Figure 4.4 The content in browser after adding a token -You can refresh this page and you will see different token every time, so this keeps every form is unique. +You can refresh this page and you will see a different token every time. This ensures that every form is unique. -For now you can prevent many of duplicate submissions attacks by adding token to your form, but it cannot prevent all the deceptive attacks, there is much more work should be done. +For now, you can prevent many duplicate submission attacks by adding tokens to your forms, but it cannot prevent all deceptive attacks of this type. There is much more work that needs to be done. ## Links - [Directory](preface.md) - Previous section: [Cross site scripting](04.3.md) -- Next section: [File upload](04.5.md) \ No newline at end of file +- Next section: [File upload](04.5.md) From 01ace5c50ddaad75486ebea75c2aa4a23c021b6b Mon Sep 17 00:00:00 2001 From: Anchor Date: Sun, 14 Sep 2014 19:53:18 -0700 Subject: [PATCH 18/20] Fix typos and grammar for 04.5.md --- en/eBook/04.5.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/en/eBook/04.5.md b/en/eBook/04.5.md index d3f76688..25803e49 100644 --- a/en/eBook/04.5.md +++ b/en/eBook/04.5.md @@ -1,14 +1,14 @@ # 4.5 File upload -Suppose you have a website like Instagram, and you want users to upload their beautiful photos, how you are going to do? +Suppose you have a website like Instagram and you want users to upload their beautiful photos. How would you implement that functionality? -You have to add property `enctype` to the form that you want to use for uploading photos, and there are three possibilities for its value: +You have to add property `enctype` to the form that you want to use for uploading photos. There are three possible values for this property: - application/x-www-form-urlencoded Trans-coding all characters before upload(default). - multipart/form-data No trans-coding, you have to use this value when your form have file upload controls. - text/plain Convert spaces to "+", but no trans-coding for special characters. + application/x-www-form-urlencoded Transcode all characters before uploading (default). + multipart/form-data No transcoding. You must use this value when your form has file upload controls. + text/plain Convert spaces to "+", but no transcoding for special characters. -Therefore, HTML content of a file upload form should look like this: +Therefore, the HTML content of a file upload form should look like this: @@ -23,7 +23,7 @@ Therefore, HTML content of a file upload form should look like this: -We need to add a function in server side to handle this affair. +We need to add a function on the server side to handle this form. http.HandleFunc("/upload", upload) @@ -57,17 +57,17 @@ We need to add a function in server side to handle this affair. } } -As you can see, we need to call `r.ParseMultipartForm` for uploading files, the argument means the `maxMemory`. After you called `ParseMultipartForm`, file will be saved in your server memory with `maxMemory` size, if the file size is larger than `maxMemory`, rest of data will be saved in system temporary file. You can use `r.FormFile` to get file handle and use `io.Copy` to save to your file system. +As you can see, we need to call `r.ParseMultipartForm` for uploading files. The function `maxMemory` argument. After you call `ParseMultipartForm`, the file will be saved in the server memory with `maxMemory` size. If the file size is larger than `maxMemory`, the rest of the data will be saved in a system temporary file. You can use `r.FormFile` to get the file handle and use `io.Copy` to save to your file system. -You don't need to call `r.ParseForm` when you access other non-file fields in the form because Go will call it when it's necessary. Also call `ParseMultipartForm` once is enough, and no differences for multiple calls. +You don't need to call `r.ParseForm` when you access other non-file fields in the form because Go will call it when it's necessary. Also, calling `ParseMultipartForm` once is enough -multiple calls make no difference. We use three steps for uploading files as follows: 1. Add `enctype="multipart/form-data"` to your form. -2. Call `r.ParseMultipartForm` in server side to save file in memory or temporary file. -3. Call `r.FormFile` to get file handle and save to file system. +2. Call `r.ParseMultipartForm` on the server side to save the file either to memory or to a temporary file. +3. Call `r.FormFile` to get the file handle and save to the file system. -The file handler is the `multipart.FileHeader`, it uses following struct: +The file handler is the `multipart.FileHeader`. It uses the following struct: type FileHeader struct { Filename string @@ -77,11 +77,11 @@ The file handler is the `multipart.FileHeader`, it uses following struct: ![](images/4.5.upload2.png?raw=true) -Figure 4.5 Print information in server after received file. +Figure 4.5 Print information on server after receiving file. ## Clients upload files -I showed the example of using form to upload file, and we can impersonate a client form to upload file in Go as well. +I showed an example of using a form to a upload a file. We can impersonate a client form to upload files in Go as well. package main @@ -143,12 +143,12 @@ I showed the example of using form to upload file, and we can impersonate a clie postFile(filename, target_url) } -The above example shows you how to use client to upload file, it uses `multipart.Write` to write file in cache and sends to server through POST method. +The above example shows you how to use a client to upload files. It uses `multipart.Write` to write files into cache and sends them to the server through the POST method. -If you have other field need to write into data like user name, call `multipart.WriteField` as needed. +If you have other fields that need to write into data, like username, call `multipart.WriteField` as needed. ## Links - [Directory](preface.md) - Previous section: [Duplicate submissions](04.4.md) -- Next section: [Summary](04.6.md) \ No newline at end of file +- Next section: [Summary](04.6.md) From b824c2094a58bacc80450a8485f17e56957cbd52 Mon Sep 17 00:00:00 2001 From: Anchor Date: Sun, 14 Sep 2014 20:07:59 -0700 Subject: [PATCH 19/20] Fix grammar and typos for 04.6.md --- en/eBook/04.6.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/en/eBook/04.6.md b/en/eBook/04.6.md index faa94fe4..d30aed1d 100644 --- a/en/eBook/04.6.md +++ b/en/eBook/04.6.md @@ -1,8 +1,8 @@ # 4.6 Summary -In this chapter, we mainly learned how to process form data in Go through examples about user log in and file upload. We also understand that verify user data is extremely important for website security, and we used one section to talk about how to filter data with regular expression. +In this chapter, we mainly learned how to process form data in Go through several examples like logging in users and uploading files. We also emphasized that verifying user data is extremely important for website security, and we used one section to talk about how to filter data with regular expressions. -I hope you know more about communication between client and server side, which is client sends data to server, and server responds to client after processed data. +I hope that you now know more about the communication process between client and server. ## Links From 9e3d41243f6555dec279bc9d47dad56ddaf41c4b Mon Sep 17 00:00:00 2001 From: Anchor Date: Sun, 14 Sep 2014 20:47:36 -0700 Subject: [PATCH 20/20] Fix additional typos and grammatical errors --- en/eBook/01.3.md | 2 +- en/eBook/01.5.md | 2 +- en/eBook/02.0.md | 2 +- en/eBook/02.2.md | 14 +++++++------- en/eBook/02.3.md | 4 ++-- en/eBook/02.4.md | 2 +- en/eBook/02.6.md | 4 ++-- en/eBook/04.0.md | 2 +- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/en/eBook/01.3.md b/en/eBook/01.3.md index 60e8b037..7fb11eb0 100644 --- a/en/eBook/01.3.md +++ b/en/eBook/01.3.md @@ -53,7 +53,7 @@ We usually use `gofmt -w` instead of `go fmt`, the latter will not rewrite your ## go get -This command is for getting remote packages, it supports BitBucket, Github, Google Code, Launchpad so far. There are actually two things that happen after we executed this command. The first thing is to download the source code, then execute `go install`. Before you use this command, make sure you have installed all the related tools. +This command is for getting remote packages. It supports BitBucket, Github, Google Code and Launchpad so far. There are actually two things that happen after we execute this command. The first thing is to download the source code, then execute `go install`. Before you use this command, make sure you have installed all the related tools. BitBucket (Mercurial Git) Github (git) diff --git a/en/eBook/01.5.md b/en/eBook/01.5.md index adca77c2..6df9c420 100644 --- a/en/eBook/01.5.md +++ b/en/eBook/01.5.md @@ -1,6 +1,6 @@ # 1.5 Summary -In this chapter, we talked about how to install Go through using three different methods: including from source code, standard package and via third-party tools. Then we showed you how to configure the Go development environment, mainly covering how to setup your `$GOPATH`. After that, we introduced the steps in compilation and deployment of Go programs. We then covered Go commands, including the compile, install, format and test commands. Finally, there are many powerful tools to develop Go programs such as LiteIDE, Sublime Text, Vim, Emacs, Eclipse, IntelliJ IDEA, etc. You can choose any one you like exploring the world of Go. +In this chapter, we talked about how to install Go using three different methods including from source code, the standard package and via third-party tools. Then we showed you how to configure the Go development environment, mainly covering how to setup your `$GOPATH`. After that, we introduced some steps for compiling and deploying Go programs. We then covered Go commands, including the compile, install, format and test commands. Finally, there are many powerful tools to develop Go programs such as LiteIDE, Sublime Text, Vim, Emacs, Eclipse, IntelliJ IDEA, etc. You can choose any one you like exploring the world of Go. ## Links diff --git a/en/eBook/02.0.md b/en/eBook/02.0.md index 0cae98b6..4c5f468a 100644 --- a/en/eBook/02.0.md +++ b/en/eBook/02.0.md @@ -1,6 +1,6 @@ # 2 Go basic knowledge -Go is a compiled system programming language, and it belongs to the C-family. However, its compilation speed is much faster than other C-family languages. It has only 25 keywords..., even less than 26 English letters! Let's take a look at these keywords before we get started. +Go is a compiled system programming language, and it belongs to the C-family. However, its compilation speed is much faster than other C-family languages. It has only 25 keywords... even less than the 26 letters of the English alphabet! Let's take a look at these keywords before we get started. break default func interface select case defer go map struct diff --git a/en/eBook/02.2.md b/en/eBook/02.2.md index 0a13f419..20edfa6c 100644 --- a/en/eBook/02.2.md +++ b/en/eBook/02.2.md @@ -4,7 +4,7 @@ In this section, we are going to teach you how to define constants, variables wi ## Define variables -There are many forms of syntax that can use to define variables in Go. +There are many forms of syntax that can be used to define variables in Go. The keyword `var` is the basic form to define variables, notice that Go puts the variable type `after` the variable name. @@ -29,7 +29,7 @@ Define multiple variables with initial values. */ var vname1, vname2, vname3 type = v1, v2, v3 -Do you think it's too tedious to define variables use the way above? Don't worry because the Go team has found this to be aproblem. Therefore if you want to define variables with initial values, we can just omit the variable type, so the code will look like this instead: +Do you think that it's too tedious to define variables use the way above? Don't worry, because the Go team has also found this to be a problem. Therefore if you want to define variables with initial values, we can just omit the variable type, so the code will look like this instead: /* Define three variables with type "type", and initialize their values. @@ -51,7 +51,7 @@ Now it looks much better. Use `:=` to replace `var` and `type`, this is called a _, b := 34, 35 -If you don't use any variable that you defined in the program, the compiler will give you compile errors. Try to compile following code, and see what happens. +If you don't use variables that you've defined in your program, the compiler will give you compilation errors. Try to compile the following code and see what happens. package main @@ -93,7 +93,7 @@ In Go, we use `bool` to define a variable as boolean type, the value can only be ### Numerical types -Integer types includ both signed and unsigned integer types. Go has `int` and `uint` at the same time, they have same length, but specific length depends on your operating system. They use 32-bit in 32-bit operating systems, and 64-bit in 64-bit operating systems. Go also has types that have specific length including `rune`, `int8`, `int16`, `int32`, `int64`, `byte`, `uint8`, `uint16`, `uint32`, `uint64`. Note that `rune` is alias of `int32` and `byte` is alias of `uint8`. +Integer types include both signed and unsigned integer types. Go has `int` and `uint` at the same time, they have same length, but specific length depends on your operating system. They use 32-bit in 32-bit operating systems, and 64-bit in 64-bit operating systems. Go also has types that have specific length including `rune`, `int8`, `int16`, `int32`, `int64`, `byte`, `uint8`, `uint16`, `uint32`, `uint64`. Note that `rune` is alias of `int32` and `byte` is alias of `uint8`. One important thing you should know that you cannot assign values between these types, this operation will cause compile errors. @@ -107,7 +107,7 @@ Although int has a longer length than uint8, and has the same length as int32, y Float types have the `float32` and `float64` types and no type called `float`. The latter one is the default type if using brief statement. -That's all? No! Go support complex numbers as well. `complex128` (with a 64-bit real and 64-bit imaginary part) is the default type, if you need a smaller type, there is one called `complex64` (with a 32-bit real and 32-bit imaginary part). Its form is `RE+IMi`, where `RE` is real part and `IM` is imaginary part, the last `i` is imaginary number. There is a example of complex number. +That's all? No! Go supports complex numbers as well. `complex128` (with a 64-bit real and 64-bit imaginary part) is the default type, if you need a smaller type, there is one called `complex64` (with a 32-bit real and 32-bit imaginary part). Its form is `RE+IMi`, where `RE` is real part and `IM` is imaginary part, the last `i` is imaginary number. There is a example of complex number. var c complex64 = 5+5i //output: (5+5i) @@ -256,7 +256,7 @@ in `[n]type`, `n` is the length of the array, `type` is the type of its elements fmt.Printf("The first element is %d\n", arr[0]) // get element value, it returns 42 fmt.Printf("The last element is %d\n", arr[9]) //it returns default value of 10th element in this array, which is 0 in this case. -Because length is a part of the array type, `[3]int` and `[4]int` are different types, so we cannot change the length of arrays. When you use arrays as arguments, functions get their copies instead of references! If you want to use reference, you may want to use `slice`, which we'll talk about later. +Because length is a part of the array type, `[3]int` and `[4]int` are different types, so we cannot change the length of arrays. When you use arrays as arguments, functions get their copies instead of references! If you want to use references, you may want to use `slice`. We'll talk about later. It's possible to use `:=` when you define arrays. @@ -264,7 +264,7 @@ It's possible to use `:=` when you define arrays. b := [10]int{1, 2, 3} // define a int array with 10 elements, of which the first three are assigned. The rest of them use the default value 0. - c := [...]int{4, 5, 6} // use `…` to replace the length paramter and Go will calculate it for you. + c := [...]int{4, 5, 6} // use `…` to replace the length parameter and Go will calculate it for you. You may want to use arrays as arrays' elements. Let's see how to do this. diff --git a/en/eBook/02.3.md b/en/eBook/02.3.md index fe94fd8f..585e4c76 100644 --- a/en/eBook/02.3.md +++ b/en/eBook/02.3.md @@ -187,7 +187,7 @@ Use the `func` keyword to define a function. return value1, value2 } -We extrapolate the following information from the example above. +We can extrapolate the following information from the example above. - Use keyword `func` to define a function `funcName`. - Functions have zero, one or more than one arguments. The argument type comes after the argument name and arguments are separated by `,`. @@ -273,7 +273,7 @@ Go supports variable arguments, which means you can give an uncertain numbers of When we pass an argument to the function that was called, that function actually gets the copy of our variables so any change will not affect to the original variable. -Let's see one example to prove what i'm saying. +Let's see one example in order to prove what i'm saying. package main import "fmt" diff --git a/en/eBook/02.4.md b/en/eBook/02.4.md index 0e7542fa..ac01d584 100644 --- a/en/eBook/02.4.md +++ b/en/eBook/02.4.md @@ -88,7 +88,7 @@ Let's see a complete example. ### embedded fields in struct -I've just introduced to you how to define a struct with field names and type.s In fact, Go supports fields without names, but with types. We call these embedded fields. +I've just introduced to you how to define a struct with field names and type. In fact, Go supports fields without names, but with types. We call these embedded fields. When the embedded field is a struct, all the fields in that struct will implicitly be the fields in the struct in which it has been embdedded. diff --git a/en/eBook/02.6.md b/en/eBook/02.6.md index 3d75ea7b..310c545f 100644 --- a/en/eBook/02.6.md +++ b/en/eBook/02.6.md @@ -365,7 +365,7 @@ There are three steps involved when using reflect. First, we need to convert an t := reflect.TypeOf(i) // get meta-data in type i, and use t to get all elements v := reflect.ValueOf(i) // get actual value in type i, and use v to change its value -After that, we can convert the reflect types to get values that we need. +After that, we can convert the reflected types to get the values that we need. var x float64 = 3.4 v := reflect.ValueOf(x) @@ -373,7 +373,7 @@ After that, we can convert the reflect types to get values that we need. fmt.Println("kind is float64:", v.Kind() == reflect.Float64) fmt.Println("value:", v.Float()) -Finally, if we want to change values from reflect types, we need to make it modifiable. As discussed earlier, there is a difference between pass by value and pass by reference. The following code will not compile. +Finally, if we want to change the values of the reflected types, we need to make it modifiable. As discussed earlier, there is a difference between pass by value and pass by reference. The following code will not compile. var x float64 = 3.4 v := reflect.ValueOf(x) diff --git a/en/eBook/04.0.md b/en/eBook/04.0.md index a6cf694e..5c250877 100644 --- a/en/eBook/04.0.md +++ b/en/eBook/04.0.md @@ -1,6 +1,6 @@ # 4 User form -A user form is something that is very commonly used when we develop web applications. It provides the ability to communicate between clients and servers. You must be very familiar with forms if you are a web developer; if you are a C/C++ programmer, you may want to ask: what is a user form? +A user form is something that is very commonly used when developping web applications. It provides the ability to communicate between clients and servers. You must be very familiar with forms if you are a web developer; if you are a C/C++ programmer, you may want to ask: what is a user form? A form is an area that contains form elements. Users can input information into form elements like text boxes, drop down lists, radio buttons, check boxes, etc. We use the form tag `
` to define forms.