Merge pull request #832 from vCaesar/u12-pr
Update install Go and Add en/0.4.x.md syntax highlighting
This commit is contained in:
16
en/01.1.md
16
en/01.1.md
@@ -76,15 +76,15 @@ A 64-bit operating system will show the following:
|
||||
|
||||
### Mac
|
||||
|
||||
Go to the [download page](https://golang.org/dl/), choose `go1.4.2.darwin-386.pkg` (The later version has no 32-bit download.)for 32-bit systems and `go1.8.darwin-amd64.pkg` for 64-bit systems. Going all the way to the end by clicking "next", `~/go/bin` will be added to your system's $PATH after you finish the installation. Now open the terminal and type `go`. You should see the same output shown in figure 1.1.
|
||||
Go to the [download page](https://golang.org/dl/), choose `go1.4.2.darwin-386.pkg` (The later version has no 32-bit download.)for 32-bit systems and `go1.8.1.darwin-amd64.pkg` for 64-bit systems. Going all the way to the end by clicking "next", `~/go/bin` will be added to your system's $PATH after you finish the installation. Now open the terminal and type `go`. You should see the same output shown in figure 1.1.
|
||||
|
||||
### Linux
|
||||
|
||||
Go to the [download page](https://golang.org/dl/), choose `go1.8.linux-386.tar.gz` for 32-bit systems and `go1.8.linux-amd64.tar.gz` for 64-bit systems. Suppose you want to install Go in the `$GO_INSTALL_DIR` path. Uncompress the `tar.gz` to your chosen path using the command `tar zxvf go1.8.linux-amd64.tar.gz -C $GO_INSTALL_DIR`. Then set your $PATH with the following: `export PATH=$PATH:$GO_INSTALL_DIR/go/bin`. Now just open the terminal and type `go`. You should now see the same output displayed in figure 1.1.
|
||||
Go to the [download page](https://golang.org/dl/), choose `go1.8.1.linux-386.tar.gz` for 32-bit systems and `go1.8.1.linux-amd64.tar.gz` for 64-bit systems. Suppose you want to install Go in the `$GO_INSTALL_DIR` path. Uncompress the `tar.gz` to your chosen path using the command `tar zxvf go1.8.1.linux-amd64.tar.gz -C $GO_INSTALL_DIR`. Then set your $PATH with the following: `export PATH=$PATH:$GO_INSTALL_DIR/go/bin`. Now just open the terminal and type `go`. You should now see the same output displayed in figure 1.1.
|
||||
|
||||
### Windows
|
||||
|
||||
Go to the [download page](https://golang.org/dl/), choose `go1.8.windows-386.msi` for 32-bit systems and `go1.8.windows-amd64.msi` for 64-bit systems. Going all the way to the end by clicking "next", `c:/go/bin` will be added to `path`. Now just open a command line window and type `go`. You should now see the same output displayed in figure 1.1.
|
||||
Go to the [download page](https://golang.org/dl/), choose `go1.8.1.windows-386.msi` for 32-bit systems and `go1.8.1.windows-amd64.msi` for 64-bit systems. Going all the way to the end by clicking "next", `c:/go/bin` will be added to `path`. Now just open a command line window and type `go`. You should now see the same output displayed in figure 1.1.
|
||||
|
||||
## Use third-party tools
|
||||
|
||||
@@ -96,8 +96,8 @@ GVM is a Go multi-version control tool developed by a third-party, like rvm for
|
||||
|
||||
Then we install Go using the following commands:
|
||||
|
||||
gvm install go1.8
|
||||
gvm use go1.8
|
||||
gvm install go1.8.1
|
||||
gvm use go1.8.1
|
||||
|
||||
After the process has finished, you're all set.
|
||||
|
||||
@@ -112,8 +112,8 @@ Ubuntu is the most popular desktop release version of Linux. It uses `apt-get` t
|
||||
### wget
|
||||
```sh
|
||||
|
||||
wget https://storage.googleapis.com/golang/go1.8.linux-amd64.tar.gz
|
||||
sudo tar -xzf go1.8.linux-amd64.tar.gz -C /usr/local
|
||||
wget https://storage.googleapis.com/golang/go1.8.1.linux-amd64.tar.gz
|
||||
sudo tar -xzf go1.8.1.linux-amd64.tar.gz -C /usr/local
|
||||
|
||||
# Go environment
|
||||
export GOROOT=/usr/local/go
|
||||
@@ -121,7 +121,7 @@ export GOBIN=$GOROOT/bin
|
||||
export PATH=$PATH:$GOBIN
|
||||
export GOPATH=HOME/gopath
|
||||
```
|
||||
Starting from go 1.8,The GOPATH environment variable now has a default value if it is unset. It defaults to $HOME/go on Unix and %USERPROFILE%/go on Windows.
|
||||
Starting from go 1.8, The GOPATH environment variable now has a default value if it is unset. It defaults to $HOME/go on Unix and %USERPROFILE%/go on Windows.
|
||||
### Homebrew
|
||||
|
||||
Homebrew is a software management tool commonly used in Mac to manage packages. Just type the following commands to install Go.
|
||||
|
||||
103
en/04.1.md
103
en/04.1.md
@@ -1,71 +1,72 @@
|
||||
# 4.1 Process form inputs
|
||||
|
||||
Before we begin, let's take a look at a simple example of a typical user form, saved as `login.gtpl` in your project folder.
|
||||
|
||||
<html>
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<form action="/login" method="post">
|
||||
Username:<input type="text" name="username">
|
||||
Password:<input type="password" name="password">
|
||||
<input type="submit" value="Login">
|
||||
</form>
|
||||
<form action="/login" method="post">
|
||||
Username:<input type="text" name="username">
|
||||
Password:<input type="password" name="password">
|
||||
<input type="submit" value="Login">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
```
|
||||
This form will submit to `/login` on the server. After the user clicks the login button, the data will be sent to the `login` handler registered by the server router. Then we need to know whether it uses the POST method or GET.
|
||||
|
||||
This is easy to find out using the `http` package. Let's see how to handle the form data on the login page.
|
||||
|
||||
package main
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func sayhelloName(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm() //Parse url parameters passed, then parse the response packet for the POST body (request body)
|
||||
// attention: If you do not call ParseForm method, the following data can not be obtained form
|
||||
fmt.Println(r.Form) // print information on server side.
|
||||
fmt.Println("path", r.URL.Path)
|
||||
fmt.Println("scheme", r.URL.Scheme)
|
||||
fmt.Println(r.Form["url_long"])
|
||||
for k, v := range r.Form {
|
||||
fmt.Println("key:", k)
|
||||
fmt.Println("val:", strings.Join(v, ""))
|
||||
}
|
||||
fmt.Fprintf(w, "Hello astaxie!") // write data to response
|
||||
func sayhelloName(w http.ResponseWriter, r *http.Request) {
|
||||
r.ParseForm() //Parse url parameters passed, then parse the response packet for the POST body (request body)
|
||||
// attention: If you do not call ParseForm method, the following data can not be obtained form
|
||||
fmt.Println(r.Form) // print information on server side.
|
||||
fmt.Println("path", r.URL.Path)
|
||||
fmt.Println("scheme", r.URL.Scheme)
|
||||
fmt.Println(r.Form["url_long"])
|
||||
for k, v := range r.Form {
|
||||
fmt.Println("key:", k)
|
||||
fmt.Println("val:", strings.Join(v, ""))
|
||||
}
|
||||
fmt.Fprintf(w, "Hello astaxie!") // write data to response
|
||||
}
|
||||
|
||||
func login(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println("method:", r.Method) //get request method
|
||||
if r.Method == "GET" {
|
||||
t, _ := template.ParseFiles("login.gtpl")
|
||||
t.Execute(w, nil)
|
||||
} else {
|
||||
r.ParseForm()
|
||||
// logic part of log in
|
||||
fmt.Println("username:", r.Form["username"])
|
||||
fmt.Println("password:", r.Form["password"])
|
||||
}
|
||||
func login(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println("method:", r.Method) //get request method
|
||||
if r.Method == "GET" {
|
||||
t, _ := template.ParseFiles("login.gtpl")
|
||||
t.Execute(w, nil)
|
||||
} else {
|
||||
r.ParseForm()
|
||||
// logic part of log in
|
||||
fmt.Println("username:", r.Form["username"])
|
||||
fmt.Println("password:", r.Form["password"])
|
||||
}
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/", sayhelloName) // setting router rule
|
||||
http.HandleFunc("/login", login)
|
||||
err := http.ListenAndServe(":9090", nil) // setting listening port
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServe: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/", sayhelloName) // setting router rule
|
||||
http.HandleFunc("/login", login)
|
||||
err := http.ListenAndServe(":9090", nil) // setting listening port
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServe: ", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
Here we use `r.Method` to get the request method, and it returns an http verb -"GET", "POST", "PUT", etc.
|
||||
|
||||
In the `login` function, we use `r.Method` to check whether it's a login page or login processing logic. In other words, we check to see whether the user is simply opening the page, or trying to log in. Serve shows the page only when the request comes in via the GET method, and it executes the login logic when the request uses the POST method.
|
||||
@@ -87,7 +88,7 @@ Try changing the value of the action in the form `http://127.0.0.1:9090/login` t
|
||||
Figure 4.2 Server prints request data
|
||||
|
||||
The type of `request.Form` is `url.Value`. It saves data with the format `key=value`.
|
||||
|
||||
```Go
|
||||
v := url.Values{}
|
||||
v.Set("name", "Ava")
|
||||
v.Add("friend", "Jess")
|
||||
@@ -97,7 +98,7 @@ The type of `request.Form` is `url.Value`. It saves data with the format `key=va
|
||||
fmt.Println(v.Get("name"))
|
||||
fmt.Println(v.Get("friend"))
|
||||
fmt.Println(v["friend"])
|
||||
|
||||
```
|
||||
**Tips** Requests have the ability to access form data using the `FormValue()` method. For example, you can change `r.Form["username"]` to `r.FormValue("username")`, and Go calls `r.ParseForm` automatically. Notice that it returns the first value if there are arguments with the same name, and it returns an empty string if there is no such argument.
|
||||
|
||||
## Links
|
||||
|
||||
76
en/04.2.md
76
en/04.2.md
@@ -7,17 +7,17 @@ There are two ways of verifying form data that are in common use. The first is J
|
||||
## Required fields
|
||||
|
||||
Sometimes we require that users input some fields but they fail to complete the field. For example in the previous section when we required a username. You can use the `len` function to get the length of a field in order to ensure that users have entered something.
|
||||
|
||||
```Go
|
||||
if len(r.Form["username"][0])==0{
|
||||
// code for empty field
|
||||
}
|
||||
|
||||
```
|
||||
`r.Form` treats different form element types differently when they are blank. For empty textboxes, text areas and file uploads, it returns an empty string; for radio buttons and check boxes, it doesn't even create the corresponding items. Instead, you will get errors if you try to access it. Therefore, it's safer to use `r.Form.Get()` to get field values since it will always return empty if the value does not exist. On the other hand, `r.Form.Get()` can only get one field value at a time, so you need to use `r.Form` to get the map of values.
|
||||
|
||||
## Numbers
|
||||
|
||||
Sometimes you require numbers rather than other text for the field value. For example, let's say that you require the age of a user in integer form only, i.e 50 or 10, instead of "old enough" or "young man". If we require a positive number, we can convert the value to the `int` type first, then process it.
|
||||
|
||||
```Go
|
||||
getint,err:=strconv.Atoi(r.Form.Get("age"))
|
||||
if err!=nil{
|
||||
// error occurs when convert to number, it may not a number
|
||||
@@ -27,55 +27,55 @@ Sometimes you require numbers rather than other text for the field value. For ex
|
||||
if getint >100 {
|
||||
// too big
|
||||
}
|
||||
|
||||
```
|
||||
Another way to do this is by using regular expressions.
|
||||
|
||||
```Go
|
||||
if m, _ := regexp.MatchString("^[0-9]+$", r.Form.Get("age")); !m {
|
||||
return false
|
||||
}
|
||||
|
||||
```
|
||||
For high performance purposes, regular expressions are not efficient, however simple regular expressions are usually fast enough. If you are familiar with regular expressions, it's a very convenient way to verify data. Notice that Go uses [RE2](http://code.google.com/p/re2/wiki/Syntax), so all UTF-8 characters are supported.
|
||||
|
||||
## Chinese
|
||||
|
||||
Sometimes we need users to input their Chinese names and we have to verify that they all use Chinese rather than random characters. For Chinese verification, regular expressions are the only way.
|
||||
|
||||
if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", r.Form.Get("realname")); !m {
|
||||
return false
|
||||
}
|
||||
|
||||
```Go
|
||||
if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", r.Form.Get("realname")); !m {
|
||||
return false
|
||||
}
|
||||
```
|
||||
## English letters
|
||||
|
||||
Sometimes we need users to input only English letters. For example, we require someone's English name, like astaxie instead of asta谢. We can easily use regular expressions to perform our verification.
|
||||
|
||||
if m, _ := regexp.MatchString("^[a-zA-Z]+$", r.Form.Get("engname")); !m {
|
||||
return false
|
||||
}
|
||||
|
||||
```Go
|
||||
if m, _ := regexp.MatchString("^[a-zA-Z]+$", r.Form.Get("engname")); !m {
|
||||
return false
|
||||
}
|
||||
```
|
||||
## E-mail address
|
||||
|
||||
If you want to know whether users have entered valid E-mail addresses, you can use the following regular expression:
|
||||
|
||||
```Go
|
||||
if m, _ := regexp.MatchString(`^([\w\.\_]{2,10})@(\w{1,}).([a-z]{2,4})$`, r.Form.Get("email")); !m {
|
||||
fmt.Println("no")
|
||||
}else{
|
||||
fmt.Println("yes")
|
||||
}
|
||||
|
||||
```
|
||||
## Drop down list
|
||||
|
||||
Let's say we require an item from our drop down list, but instead we get a value fabricated by hackers. How do we prevent this from happening?
|
||||
|
||||
Suppose we have the following `<select>`:
|
||||
|
||||
```html
|
||||
<select name="fruit">
|
||||
<option value="apple">apple</option>
|
||||
<option value="pear">pear</option>
|
||||
<option value="banana">banana</option>
|
||||
</select>
|
||||
|
||||
```
|
||||
We can use the following strategy to sanitize our input:
|
||||
|
||||
```Go
|
||||
slice:=[]string{"apple","pear","banana"}
|
||||
|
||||
for _, v := range slice {
|
||||
@@ -84,18 +84,18 @@ We can use the following strategy to sanitize our input:
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
```
|
||||
All the functions I've shown above are in my open source project for operating on slices and maps: [https://github.com/astaxie/beeku](https://github.com/astaxie/beeku)
|
||||
|
||||
## Radio buttons
|
||||
|
||||
If we want to know whether the user is male or female, we may use a radio button, returning 1 for male and 2 for female. However, some little kid who just read his first book on HTTP, decides to send to you a 3. Will your program throw an exception? As you can see, we need to use the same method as we did for our drop down list to make sure that only expected values are returned by our radio button.
|
||||
|
||||
```html
|
||||
<input type="radio" name="gender" value="1">Male
|
||||
<input type="radio" name="gender" value="2">Female
|
||||
|
||||
```
|
||||
And we use the following code to validate the input:
|
||||
|
||||
```Go
|
||||
slice:=[]int{1,2}
|
||||
|
||||
for _, v := range slice {
|
||||
@@ -104,32 +104,32 @@ And we use the following code to validate the input:
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
||||
```
|
||||
## Check boxes
|
||||
|
||||
Suppose there are some check boxes for user interests, and that you don't want extraneous values here either. You can validate these ase follows:
|
||||
|
||||
```html
|
||||
<input type="checkbox" name="interest" value="football">Football
|
||||
<input type="checkbox" name="interest" value="basketball">Basketball
|
||||
<input type="checkbox" name="interest" value="tennis">Tennis
|
||||
|
||||
```
|
||||
In this case, the sanitization is a little bit different to validating the button and check box inputs since here we get a slice from the check boxes.
|
||||
```Go
|
||||
slice:=[]string{"football","basketball","tennis"}
|
||||
a:=Slice_diff(r.Form["interest"],slice)
|
||||
if a == nil{
|
||||
return true
|
||||
}
|
||||
|
||||
slice:=[]string{"football","basketball","tennis"}
|
||||
a:=Slice_diff(r.Form["interest"],slice)
|
||||
if a == nil{
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
return false
|
||||
```
|
||||
## Date and time
|
||||
|
||||
Suppose you want users to input valid dates or times. Go has the `time` package for converting year, month and day to their corresponding times. After that, it's easy to check it.
|
||||
|
||||
```Go
|
||||
t := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
|
||||
fmt.Printf("Go launched at %s\n", t.Local())
|
||||
|
||||
```
|
||||
After you have the time, you can use the `time` package for more operations, depending on your needs.
|
||||
|
||||
In this section, we've discussed some common methods of validating form data on the server side. I hope that you now understand more about data validation in Go, especially how to use regular expressions to your advantage.
|
||||
|
||||
34
en/04.3.md
34
en/04.3.md
@@ -16,11 +16,11 @@ So how can we do these two things in Go? Fortunately, the `html/template` packag
|
||||
- `func HTMLEscaper(args ...interface{}) string` returns a string after escaping from multiple arguments.
|
||||
|
||||
Let's change the example in section 4.1:
|
||||
|
||||
```Go
|
||||
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // print at server side
|
||||
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
|
||||
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // responded to clients
|
||||
|
||||
```
|
||||
If someone tries to input the username as `<script>alert()</script>`, we will see the following content in the browser:
|
||||
|
||||

|
||||
@@ -28,39 +28,39 @@ If someone tries to input the username as `<script>alert()</script>`, we will se
|
||||
Figure 4.3 JavaScript after escaped
|
||||
|
||||
Functions in the `html/template` package help you to escape all HTML tags. What if you just want to print `<script>alert()</script>` to browsers? You should use `text/template` instead.
|
||||
|
||||
```Go
|
||||
import "text/template"
|
||||
...
|
||||
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
|
||||
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
|
||||
|
||||
```
|
||||
Output:
|
||||
|
||||
Hello, <script>alert('you have been pwned')</script>!
|
||||
|
||||
```html
|
||||
Hello, <script>alert('you have been pwned')</script>!
|
||||
```
|
||||
Or you can use the `template.HTML` type :
|
||||
Variable content will not be escaped if its type is `template.HTML`.
|
||||
|
||||
```Go
|
||||
import "html/template"
|
||||
...
|
||||
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
|
||||
err = t.ExecuteTemplate(out, "T", template.HTML("<script>alert('you have been pwned')</script>"))
|
||||
|
||||
```
|
||||
Output:
|
||||
|
||||
Hello, <script>alert('you have been pwned')</script>!
|
||||
|
||||
```html
|
||||
Hello, <script>alert('you have been pwned')</script>!
|
||||
```
|
||||
One more example of escaping:
|
||||
|
||||
```Go
|
||||
import "html/template"
|
||||
...
|
||||
t, err := template.New("foo").Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)
|
||||
err = t.ExecuteTemplate(out, "T", "<script>alert('you have been pwned')</script>")
|
||||
|
||||
```
|
||||
Output:
|
||||
|
||||
Hello, <script>alert('you have been pwned')</script>!
|
||||
|
||||
```html
|
||||
Hello, <script>alert('you have been pwned')</script>!
|
||||
```
|
||||
## Links
|
||||
|
||||
- [Directory](preface.md)
|
||||
|
||||
54
en/04.4.md
54
en/04.4.md
@@ -5,7 +5,7 @@ I don't know if you've ever seen some blogs or BBS' that have more than one post
|
||||
The solution is to add a hidden field with a unique token to your form, and to always check this token before processing the incoming data. Also, if you are using Ajax to submit a form, use JavaScript to disable the submit button once the form has been submitted.
|
||||
|
||||
Let's improve the example from section 4.2:
|
||||
|
||||
```html
|
||||
<input type="checkbox" name="interest" value="football">Football
|
||||
<input type="checkbox" name="interest" value="basketball">Basketball
|
||||
<input type="checkbox" name="interest" value="tennis">Tennis
|
||||
@@ -13,34 +13,36 @@ Let's improve the example from section 4.2:
|
||||
Password:<input type="password" name="password">
|
||||
<input type="hidden" name="token" value="{{.}}">
|
||||
<input type="submit" value="Login">
|
||||
|
||||
```
|
||||
We use an MD5 hash (time stamp) to generate the token, and added it to both a hidden field on the client side form and a session cookie on the server side (Chapter 6). We can then use this token to check whether or not this form was submitted.
|
||||
```Go
|
||||
func login(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println("method:", r.Method) // get request method
|
||||
if r.Method == "GET" {
|
||||
crutime := time.Now().Unix()
|
||||
h := md5.New()
|
||||
io.WriteString(h, strconv.FormatInt(crutime, 10))
|
||||
token := fmt.Sprintf("%x", h.Sum(nil))
|
||||
|
||||
func login(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Println("method:", r.Method) // get request method
|
||||
if r.Method == "GET" {
|
||||
crutime := time.Now().Unix()
|
||||
h := md5.New()
|
||||
io.WriteString(h, strconv.FormatInt(crutime, 10))
|
||||
token := fmt.Sprintf("%x", h.Sum(nil))
|
||||
|
||||
t, _ := template.ParseFiles("login.gtpl")
|
||||
t.Execute(w, token)
|
||||
} else {
|
||||
// log in request
|
||||
r.ParseForm()
|
||||
token := r.Form.Get("token")
|
||||
if token != "" {
|
||||
// check token validity
|
||||
} else {
|
||||
// give error if no token
|
||||
}
|
||||
fmt.Println("username length:", len(r.Form["username"][0]))
|
||||
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // print in server side
|
||||
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
|
||||
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // respond to client
|
||||
}
|
||||
t, _ := template.ParseFiles("login.gtpl")
|
||||
t.Execute(w, token)
|
||||
} else {
|
||||
// log in request
|
||||
r.ParseForm()
|
||||
token := r.Form.Get("token")
|
||||
if token != "" {
|
||||
// check token validity
|
||||
} else {
|
||||
// give error if no token
|
||||
}
|
||||
fmt.Println("username length:", len(r.Form["username"][0]))
|
||||
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) // print in server side
|
||||
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
|
||||
template.HTMLEscape(w, []byte(r.Form.Get("username"))) // respond to client
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ text/plain Convert spaces to "+", but no transcoding for special characters.
|
||||
|
||||
Therefore, the HTML content of a file upload form should look like this:
|
||||
|
||||
```
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<title>Upload file</title>
|
||||
@@ -31,7 +31,7 @@ Therefore, the HTML content of a file upload form should look like this:
|
||||
|
||||
We need to add a function on the server side to handle this form.
|
||||
|
||||
```
|
||||
```Go
|
||||
http.HandleFunc("/upload", upload)
|
||||
|
||||
// upload logic
|
||||
@@ -78,7 +78,7 @@ We use three steps for uploading files as follows:
|
||||
|
||||
The file handler is the `multipart.FileHeader`. It uses the following struct:
|
||||
|
||||
```
|
||||
```Go
|
||||
type FileHeader struct {
|
||||
Filename string
|
||||
Header textproto.MIMEHeader
|
||||
@@ -94,7 +94,7 @@ Figure 4.5 Print information on server after receiving file.
|
||||
|
||||
I showed an example of using a form to a upload a file. We can impersonate a client form to upload files in Go as well.
|
||||
|
||||
```
|
||||
```Go
|
||||
package main
|
||||
|
||||
import (
|
||||
|
||||
23
zh/01.1.md
23
zh/01.1.md
@@ -79,7 +79,7 @@ Linux系统用户可通过在Terminal中执行命令`arch`(即`uname -m`)来查
|
||||
|
||||
### Mac 安装
|
||||
|
||||
访问[下载地址][downlink],32位系统下载go1.4.2.darwin-386-osx10.8.pkg(更新版已无32位下载),64位系统下载go1.8.darwin-amd64.pkg,双击下载文件,一路默认安装点击下一步,这个时候go已经安装到你的系统中,默认已经在PATH中增加了相应的`~/go/bin`,这个时候打开终端,输入`go`
|
||||
访问[下载地址][downlink],32位系统下载go1.4.2.darwin-386-osx10.8.pkg(更新的版本已无32位下载),64位系统下载go1.8.1.darwin-amd64.pkg,双击下载文件,一路默认安装点击下一步,这个时候go已经安装到你的系统中,默认已经在PATH中增加了相应的`~/go/bin`,这个时候打开终端,输入`go`
|
||||
|
||||
看到类似上面源码安装成功的图片说明已经安装成功
|
||||
|
||||
@@ -87,11 +87,11 @@ Linux系统用户可通过在Terminal中执行命令`arch`(即`uname -m`)来查
|
||||
|
||||
### Linux 安装
|
||||
|
||||
访问[下载地址][downlink],32位系统下载go1.8.linux-386.tar.gz,64位系统下载go1.8.linux-amd64.tar.gz,
|
||||
访问[下载地址][downlink],32位系统下载go1.8.1.linux-386.tar.gz,64位系统下载go1.8.1.linux-amd64.tar.gz,
|
||||
|
||||
假定你想要安装Go的目录为 `$GO_INSTALL_DIR`,后面替换为相应的目录路径。
|
||||
|
||||
解压缩`tar.gz`包到安装目录下:`tar zxvf go1.8.linux-amd64.tar.gz -C $GO_INSTALL_DIR`。
|
||||
解压缩`tar.gz`包到安装目录下:`tar zxvf go1.8.1.linux-amd64.tar.gz -C $GO_INSTALL_DIR`。
|
||||
|
||||
设置PATH,`export PATH=$PATH:$GO_INSTALL_DIR/go/bin`
|
||||
|
||||
@@ -125,11 +125,11 @@ gvm是第三方开发的Go多版本管理工具,类似ruby里面的rvm工具
|
||||
安装完成后我们就可以安装go了:
|
||||
```sh
|
||||
|
||||
gvm install go1.8
|
||||
gvm use go1.8
|
||||
gvm install go1.8.1
|
||||
gvm use go1.8.1
|
||||
```
|
||||
也可以使用下面的命令,省去每次调用gvm use的麻烦:
|
||||
gvm use go1.8 --default
|
||||
gvm use go1.8.1 --default
|
||||
|
||||
执行完上面的命令之后GOPATH、GOROOT等环境变量会自动设置好,这样就可以直接使用了。
|
||||
|
||||
@@ -145,8 +145,8 @@ Ubuntu是目前使用最多的Linux桌面系统,使用`apt-get`命令来管理
|
||||
### wget
|
||||
```sh
|
||||
|
||||
wget https://storage.googleapis.com/golang/go1.8.linux-amd64.tar.gz
|
||||
sudo tar -xzf go1.8.linux-amd64.tar.gz -C /usr/local
|
||||
wget https://storage.googleapis.com/golang/go1.8.1.linux-amd64.tar.gz
|
||||
sudo tar -xzf go1.8.1.linux-amd64.tar.gz -C /usr/local
|
||||
```
|
||||
|
||||
配置环境变量:
|
||||
@@ -169,14 +169,17 @@ export PATH=$PATH:$GOBIN
|
||||
export GOPATH=$HOME/gopath (可选设置)
|
||||
```
|
||||
|
||||
重新加载 profile 文件
|
||||
```sh
|
||||
source /etc/profile
|
||||
```
|
||||
### homebrew
|
||||
homebrew是Mac系统下面目前使用最多的管理软件的工具,目前已支持Go,可以通过命令直接安装Go,为了以后方便,应该把 `git` `mercurial` 也安装上:
|
||||
|
||||
1.安装homebrew
|
||||
|
||||
```sh
|
||||
|
||||
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
|
||||
```
|
||||
|
||||
2.安装go
|
||||
|
||||
Reference in New Issue
Block a user