Skip to content

Latest commit

 

History

History
90 lines (63 loc) · 6.02 KB

16.A-WebServer.md

File metadata and controls

90 lines (63 loc) · 6.02 KB

A web server

Let's finish with a complete Go program, a web server. This one is actually a kind of web re-server. Google provides a service at chart.apis.google.com that does automatic formatting of data into charts and graphs. It's hard to use interactively, though, because you need to put the data into the URL as a query. The program here provides a nicer interface to one form of data: given a short piece of text, it calls on the chart server to produce a QR code, a matrix of boxes that encode the text. That image can be grabbed with your cell phone's camera and interpreted as, for instance, a URL, saving you typing the URL into the phone's tiny keyboard.

让我们用一个完整的 Go 程序——Web Server,来结束整个 effective 之旅。事实上,这是一个改进版 Web 服务器。谷歌在 chart.apis.google.com 上提供了一种自动将数据转化为图表和图像的服务。但其交互性却有些差强人意,你需要手动将数据粘贴到 url 才能进行查询。本程序为表单数据提供了更加友好的接口:给定一小段文本,它调用 chat server 来产生一个二维码——一种将文本编码后的矩阵。这个二维码可以被手机的摄像头捕获并解释,例如,解释成 URL,这样就能避免在手机小键盘上键入整个 URL。

Here's the complete program. An explanation follows.

下面是整个程序代码,稍后将逐一解释:

package main

import (
    "flag"
    "html/template"
    "log"
    "net/http"
)

var addr = flag.String("addr", ":1718", "http service address") // Q=17, R=18

var templ = template.Must(template.New("qr").Parse(templateStr))

func main() {
    flag.Parse()
    http.Handle("/", http.HandlerFunc(QR))
    err := http.ListenAndServe(*addr, nil)
    if err != nil {
        log.Fatal("ListenAndServe:", err)
    }
}

func QR(w http.ResponseWriter, req *http.Request) {
    templ.Execute(w, req.FormValue("s"))
}

const templateStr = `
<html>
<head>
<title>QR Link Generator</title>
</head>
<body>
{{if .}}
<img src="http://chart.apis.google.com/chart?chs=300x300&cht=qr&choe=UTF-8&chl={{.}}" />
<br>
{{.}}
<br>
<br>
{{end}}
<form action="/" name=f method="GET">
    <input maxLength=1024 size=70 name=s value="" title="Text to QR Encode">
    <input type=submit value="Show QR" name=qr>
</form>
</body>
</html>
`

The pieces up to main should be easy to follow. The one flag sets a default HTTP port for our server. The template variable templ is where the fun happens. It builds an HTML template that will be executed by the server to display the page; more about that in a moment.

main 函数之前的内容比较容易理解,flag 设置 HTTP Server 的地址端口,包括默认值。模板变量 templ 才是有趣之处,它构建一个 HTML 模板,并且由 Server 执行后显示,详情我们稍后解释。

The main function parses the flags and, using the mechanism we talked about above, binds the function QR to the root path for the server. Then http.ListenAndServe is called to start the server; it blocks while the server runs.

main 函数解析 flag,并使用我们曾谈及的机制将 QR 函数绑定到 Server 的根路径上。http.ListenAndServe 被调用从而启动 HTTP Server,该函数在 server 运行期间将一直阻塞。

译注:ListenAndServe 事实上是阻塞在一个无限循环的 Accept 之上,当有 http 请求到达时,会启用新的 goroutine 来处理请求,ListenAndServe 则会回到 Accept 来等待新的请求。万不可理解为 http.ListenAndServe 一直阻塞。

QR just receives the request, which contains form data, and executes the template on the data in the form value named s.

QR 函数接收到包含表单数据的请求后,会基于表单中的名为 s 的数据项来执行模板。

The template package html/template is powerful; this program just touches on its capabilities. In essence, it rewrites a piece of HTML text on the fly by substituting elements derived from data items passed to templ.Execute, in this case the form value. Within the template text (templateStr), double-brace-delimited pieces denote template actions. The piece from {{if .}} to {{end}} executes only if the value of the current data item, called . (dot), is non-empty. That is, when the string is empty, this piece of the template is suppressed.

模板包 html/template 非常强大,本例所触及的仅其冰山一角。本质上,它是在程序运行期间将 HTML 中的元素替换为传递给 templ.Execute 的数据,本例中为表单的数据。模板文本中(templateStr),双大括号包裹的内容意为模板行为。从 {{if .}}{{end}} 的片段仅在当前数据项的值(.)不为空时执行。也就是说,当字符串为空时,这个片段不被执行。

The two snippets {{.}} say to show the data presented to the template—the query string—on the web page. The HTML template package automatically provides appropriate escaping so the text is safe to display.

两处 {{.}} 意为在 web 页面上显示提供给模板的数据,这里指查询字符串。HTML 模板包会自动处理字符串中的转义,从而使文本安全展示。

The rest of the template string is just the HTML to show when the page loads. If this is too quick an explanation, see the documentation for the template package for a more thorough discussion.

模板中剩余内容只是在页面加载时 HTML 要显示的东西。对于模板相关内容,受篇幅所限,只能言简意赅地释其二三,未尽之处请参阅 documentation

And there you have it: a useful web server in a few lines of code plus some data-driven HTML text. Go is powerful enough to make a lot happen in a few lines.

恭喜你,成功了:几行代码加一点数据驱动的 HTML 文本便搞定了一个行之有效的 web 服务器。Go 是个卓有成效的语言,几行代码就可以造就一个世界。

示例展示