翻译进度
7
分块数量
2
参与人数

19.4. 用户界面:Web 网页前端

这是一篇社区协同翻译的文章,你可以点击右边区块信息里的『改进』按钮向译者提交改进建议。

[ 本章节的代码可以在 goto_v1\main.go 中找到 ]

我们还没有编写我们程序启动所必须的功能。如在 C 、 C++ 、 Java 中,这是(总是) main() 函数。例如,我们可以使用下面命令在 8080 端口上启动一个本地的 web 服务器: http.ListenAndServe(":8080", nil)

( web 服务器的功能来自 http 包,我们已经在 章节 15 深入讨论过了)。 web 服务器在一个无限循环中监听传入的请求,但是我们还必须去定义该服务器如何去响应这些请求。我们通过使用 HandleFunc 函数来创建所谓的 HTTP 处理程序来完成此操作,示例代码:

BroQiang 翻译于 6个月前

http.HandleFunc("/add", Add)

我们说每一个 /add 结束的请求都会调用一个 Add 函数(还没有定义)。

我们的程序将有两个 HTTP 处理器:

  • Redirect, 重定向短网址的请求,以及

  • Add,处理新提交的 URLs 。

示例图:

file

我们最小的 main() 可能看起来像这样:


func main() {

    http.HandleFunc("/", Redirect)

    http.HandleFunc("/add", Add)

    http.ListenAndServe(":8080", nil)

}
BroQiang 翻译于 6个月前

请求 /add 将被 Add 处理器处理;所有的其他请求将被 Redirect 处理器处理。处理器函数从一个传入的请求(一个 *http. Request 变量)获取信息,并且将他们的响应写入一个 http.ResponseWriter 类型的变量 w 中。

我们的 Add 函数必须做什么?

i)读取长 URL,即: 通过 r.FormValue("url") ,从一个 HTTP 请求包含的 html 表单读取。

ii) 在 store (译者注: NewURLStore() 返回的变量) 上使用我们的 Put 方法将它保存。

iii) 发送相应的短 URL 给用户

每个需求在代码行中的翻译:


func Add(w http.ResponseWriter, r *http.Request) {

    url := r.FormValue("url")

    key := store.Put(url)

    fmt.Fprintf(w, "http://localhost:8080/%s", key)

}
BroQiang 翻译于 6个月前

fmt 包的 Fprintf 函数用来在包含 %s 的字符串中替换 key,然后将这个字符串作为响应发送回客户端。

请注意: Fprintf 写入一个 ResponseWriter,其实 Fprintf 能写入任何实现了 io.Writer() 的数据结构体,这意味着它实现了一个 Write() 方法。io.Writer() 是 Go 中的一个接口,并且我们看到,通过接口的使用,Fprintf 是非常的通用,它能写入很多不同的东西。在 Go 中,接口的使用是无处不在的,它使代码变得更加通用( 参见 章节 11 )。

但是我们仍然需要一个表单,我们可以再次使用 Fprintf 显示一个表单,这次给 w 写入一个常量。当没有提供 url 的时候,我们修改 Add 去显示一个 HTML 表单:


func Add(w http.ResponseWriter, r *http.Request) {

    url := r.FormValue("url")

    if url == "" {

        fmt.Fprint(w, AddForm)

        return

    }

    key := store.Put(url)

    fmt.Fprintf(w, "http://localhost:8080/%s", key)

}

const AddForm = `

<form method="POST" action="/add">

URL: <input type="text" name="url">

<input type="submit" value="Add">

</form>

`
BroQiang 翻译于 6个月前

在这种情况下,我们发送一个常量字符串 AddForm 给客户端,这实际上是创建了一个需要包含一个 form 表单的 html,form 中有一个 url 的 input 字段、一个提交按钮,当推送时将发送一个 /add 结尾的请求。所以 Add 处理器函数再次被调用,现在从文本字段获取了一个值。(`` 在制作一个原始的字符串时使用, 否则像往常一样将字符串括在 " " 中)。

Redirect 函数在 HTTP 请求路径中找到 key(短 URL 的 key 是请求路径去除第一个字符,在 Go 中可以这样去写 [1:] ; 如 请求 /abc , key 将是 abc ),通过 store 的 Get 函数取出相应的长 URL ,然后向用户发送一个 HTTP 重定向。如果 URL 没有找到,发送一个 404 "Not Found" 错误:


func Redirect(w http.ResponseWriter, r *http.Request) {

    key := r.URL.Path[1:]

    url := store.Get(key)

    if url == "" {

        http.NotFound(w, r)

        return

    }

    http.Redirect(w, r, url, http.StatusFound)

}
BroQiang 翻译于 6个月前

(http.NotFound 和 http.Redirect 是发送常见 HTTP 响应的助手函数)

现在我们已经完成了 goto_v1 所有代码。

译者注: 因为 Go 从 1.5 版本开始已经实现 自举(Bootstrapping) ,所以下面的编译方式已经无法使用,个人觉得也就没有必要看了。Linux 下直接在源码所在目录执行 go build 就可以编译源码,默认会生成一个和目录名称相同的可执行文件(个人觉得 Windows 和 macOS 下应该一样,不过没有环境无法测试,请自行尝试或查看其他文档)。
PS: 下面的环境无法尝试,全部都是字面翻译,不一定准确……

编译并运行:

可执行文件在下载的示例文件中,如果你愿意,你可以直接跳过本节并立即测试。带有 3 个 go 源文件的目录中还有一个 MakeFile 文件,通过它们可以应用和链接应用程序,只需要这样做:

  • 适用于Linux、OS X: 从目录中打开一个终端窗口或者直接在 LiteIDE 的项目中构建

  • 适用于 Windows :通过启动 MINGW 环境开始,所有程序、 MinGW 、 MinGW Shell (参见 章节 2.5 ),在命令行窗口输入 type:make 并进入:

    源文件被编译并链接到一个 native .exe

结果是一个可执行程序: Linux/OS X 中是 goto 、 Windows 中是 goto.exe

要运行它并启动 web 服务器,执行:

  • 适用于 Linux, OS X : 执行 ./goto 命令

  • 适用于 Windows : 从 GoIde 启动程序 (如果Windows防火墙阻止启动程序:设置允许此程序)
BroQiang 翻译于 6个月前

测试程序:

打开一个浏览器并请求下面的 URL:

http://localhost:8080/add

在这开始我们的添加处理函数。 表单中还没有任何url变量,所以响应的是 html 格式的请求输入:

file

添加一个你想要变短的长网址,例如:http://golang.org/pkg/bufio/#Writer ,并且按下 Add 按钮。应用程序为你制作了一个 短 URL 并打印出来,例如: http://localhost:8080/2

file

复制并粘贴这个 URL 到你的浏览器的地址栏中,然后访问它。它会执行一个重定向,并显示长 URL 的页面。

file

版本2 --- 添加持久化存储

第 2 版的代码在 goto_v2 中( 在 章节 19.5 讨论 ),可以在 code_examples\ chapter_19\goto_v2 目录中找到它。

BroQiang 翻译于 6个月前

本文章首发在 GolangCaff
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

参与译者:2
讨论数量: 1
发起讨论


skyLee
HTML 浏览器显示的是实体,不知为何?
0 个点赞 | 0 个回复 | 问答