原文:https://golang.org/doc/articles/wiki/
应该有人翻译过了, 不过边翻译边学边做, 感觉还不错
介绍
在这个教程中包括了如下内容:
- 使用load与save方法创建一个数据结构
- 使用net/http包构建一个web应用程序
- 使用html/template包来处理HTML文件模板
- 使用regexp包验证用户输入
- 使用闭包
需要你具有:
- 编程经验
- 理解基本的web应用技术(HTTP, HTML)
- 一些UNIX/DOS命令行基础
开始上手
现在, 你需要一台FreeBSD, Linux, OSX或者Windows机器才能运行Go,在这里将会使用$来代表命令行输入
安装Go(查看 安装文档)
在你的GOPATH中为这个教程创建一个文件夹, 并且cd进入这个文件夹中
$ mkdir gowiki
$ cd gowiki
创建一个名字为wiki.go的文件, 用你最喜欢的编辑器打开这个文件, 然后在这个文件中添加如下内容
package main
import (
"fmt"
"io/ioutil"
)
在这里, 我们从Go标准库中导入了fmt和ioutil包, 稍后我们实现更多功能的时候, 我们会使用import导入更多的包
数据结构
让我们从定义一个数据结构开始学起, 一个Wiki页面由许多个网页组成, 每一个网页都有一个标题(title)和一个正文(body), 这里, 我们定义了一个Page
为一个结构, 并且有两个字段表示标题和正文.
type Page struct {
Title string
Body []byte
}
[]byte这个数据类型代表着"1比特
的切片".(查看 切片:使用方法与内部结构 获取更多有关切片的内容), 这个Body
元素是一个[]byte
而不是一个string
(字符串), 这是我们导入的io库中的内容, 如下所示.
这个Page
结构描述了一个页面的数据是怎么样存储在内存中的, 但是用文件存储呢? 我们可以在Page
中创建一个save
函数去指定这个文件的路径:
func (p *Page) save() error {
filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.Body, 0600)
}
这个函数的解释如下: "这是一个叫做save
的函数, 这个函数将指向Page
的指针p
作为其接收器, 它不需要任何参数, 然后return(返回)一个类型为error(错误)的值.
这个函数将会保存Page
的Body
为一个txt文件, 为了简单起见, 我们这里使用了Title
作为这个文件的名字.
这个save
函数之所以会return(返回)一个error
值是因为其WriteFile(一个将数据切片保存为文件的函数封装的标准库)的返回值就是error
, 这个save
函数返回了一个错误值的意思是如果在写入文件时出现任何错误, 就让应用程序来处理, 如果一切进展顺利, Page.save()
会return一个nil
(空指针, 接口, 或者一些其它的类型).
最后的八进制整数0600
, 作为第三个参数传递给WriteFile
, 指示了这个文件的权限, 0600
为只有当前用户拥有的read-write(读写)权限(详情请查看 Unix man page open(2)
)
除了保存页面, 我们还希望它加载页面:
func loadPage(title string) *Page {
filename := title + ".txt"
body, _ := ioutil.ReadFile(filename)
return &Page{Title: title, Body: body}
}
这个loadPage
函数使用title参数构造文件名, 读取文件内容, 并赋值给一个变量body
, 然后return一个指针, 指向用适当的title和body值构造的Page
函数可以返回多个值, 标准库函数io.ReadFile
会返回一个[]byte
和一个error
, 在loadPage
中, 错误还没有被处理, 由下划线(_)表示的"空标识符"用于丢弃错误返回值(本质上, 赋值为空)
但是如果ReadFile
遇到了错误怎么办? 举个例子, 这个文件也许不存在, 我们不应该忽略这类的错误, 那咱们就修改一下这个函数, 让它返回*Page
和error
.
func loadPage(title string) (*Page, error) {
filename := title + ".txt"
body, error := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return &Page{Title: title, Body: body}, nil
}
这个函数的使用者可以使用第二个参数做检查了, 如果是nil
那就代表着它正确的成功的加载了一个页面, 如果不是nil
, 这就会是一个由函数使用者处理的错误
在这里我们已经有了一个简单的数据结构和从文件保存加载的能力, 让我们写出一个main
函数来测试一下我们刚刚写的内容:
func main() {
p1 := &Page{Title: "TestPage", Body: []byte("This is a sample Page.")}
p1.save()
p2, _ := loadPage("TestPage")
fmt.Println(string(p2.Body))
}
在编译和执行代码之后, 目录下会有一个名字为TestPage.txt的文件, 这个文件包含了p1的内容, 然后将文件读入p2
, 最后将Body
元素输出到窗口中.
你可以使用如下命令来编译执行代码:
$ go build wiki.go
$ ./wiki
This is a sample Page
(如果你在使用Windows系统的话, 你必须输入"wiki
", 而没有"./", 来运行这个文件.)
如下是我们到现在所写的全部代码
//Copyright 2010 The Go Authors. All rights reserved.
//Use of this source code is governed by a BSD-style
//license that can be found in the LICENSE file.
// +build ignore
package main
import (
"fmt"
"io/ioutil"
)
type Page struct {
Title string
Body []byte
}
func (p *Page) save() error {
filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.Body, 0600)
}
func loadPage(title string) (*Page, error) {
filename := title + ".txt"
body, error := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return &Page{Title: title, Body: body}, nil
}
func main() {
p1 := &Page{Title: "TestPage", Body: []byte("This is a sample Page.")}
p1.save()
p2, _ := loadPage("TestPage")
fmt.Println(string(p2.Body))
}
介绍net/http包(插曲)
这里是一个完整的正常工作的简单web服务器代码:
// +build ignore
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWrite, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
}
这个main
函数从http.HandleFunc
开始, 这个函数告诉了http
包用handler
去处理所有到/
(网站根目录)下的网络请求
然后呼叫了http.ListenAndServe
, 指定了它应该监听任何接口上的8080端口(现在还不用担心传递的第二个参数nil
) 这个函数会一直阻止程序自我终止
ListenAndServe
总是return一个error, 它只在发生意外错误的时候返回, 我们为了记录下发生的错误, 会使用log.Fatal
.
handler
函数的类型为http.HandlerFunc
, 它需要http.ResponseWriter
和一个http.Request
作为它的参数.
http.ResponseWriter
值聚集了HTTP服务器的响应, 通过向其写入, 就可以将数据发送给HTTP客户端.
一个http.Request
就是一个数据结构, 这个数据结构表示这客户端的HTTP请求, r.URL.Path
就是请求的URL路径, 尾巴后面的[1:]得意思是"用请求的路径/之后所有的字符创建一个子Path的子切片"
如果你用浏览器访问如下网址:
http://localhost:8080/monkeys
这个程序就会在页面中呈现出:
Hi there, I love monkeys!
未完待续
98礼品网负责礼品代发、快递代发、拍A发B快递、礼品等服务。http://www.98lp.cn
感谢分享 biubiu 赞一个