前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >翻译golang官网文章Writing Web Applications

翻译golang官网文章Writing Web Applications

作者头像
NothAmor
发布2022-06-08 11:03:01
1680
发布2022-06-08 11:03:01
举报
文章被收录于专栏:欧尼酱茶馆欧尼酱茶馆

原文: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进入这个文件夹中

代码语言:javascript
复制
$ mkdir gowiki
$ cd gowiki

创建一个名字为wiki.go的文件, 用你最喜欢的编辑器打开这个文件, 然后在这个文件中添加如下内容

代码语言:javascript
复制
package main

import (
    "fmt"
    "io/ioutil"
)

在这里, 我们从Go标准库中导入了fmt和ioutil包, 稍后我们实现更多功能的时候, 我们会使用import导入更多的包

数据结构 让我们从定义一个数据结构开始学起, 一个Wiki页面由许多个网页组成, 每一个网页都有一个标题(title)和一个正文(body), 这里, 我们定义了一个Page为一个结构, 并且有两个字段表示标题和正文.

代码语言:javascript
复制
type Page struct {
    Title string
    Body []byte
}

[]byte这个数据类型代表着"1比特的切片".(查看 切片:使用方法与内部结构 获取更多有关切片的内容), 这个Body元素是一个[]byte而不是一个string(字符串), 这是我们导入的io库中的内容, 如下所示.

这个Page结构描述了一个页面的数据是怎么样存储在内存中的, 但是用文件存储呢? 我们可以在Page中创建一个save函数去指定这个文件的路径:

代码语言:javascript
复制
func (p *Page) save() error {
    filename := p.Title + ".txt"
    return ioutil.WriteFile(filename, p.Body, 0600)
}

这个函数的解释如下: "这是一个叫做save的函数, 这个函数将指向Page的指针p作为其接收器, 它不需要任何参数, 然后return(返回)一个类型为error(错误)的值.

这个函数将会保存PageBody为一个txt文件, 为了简单起见, 我们这里使用了Title作为这个文件的名字.

这个save函数之所以会return(返回)一个error值是因为其WriteFile(一个将数据切片保存为文件的函数封装的标准库)的返回值就是error, 这个save函数返回了一个错误值的意思是如果在写入文件时出现任何错误, 就让应用程序来处理, 如果一切进展顺利, Page.save()会return一个nil(空指针, 接口, 或者一些其它的类型).

最后的八进制整数0600, 作为第三个参数传递给WriteFile, 指示了这个文件的权限, 0600为只有当前用户拥有的read-write(读写)权限(详情请查看 Unix man page open(2))

除了保存页面, 我们还希望它加载页面:

代码语言:javascript
复制
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遇到了错误怎么办? 举个例子, 这个文件也许不存在, 我们不应该忽略这类的错误, 那咱们就修改一下这个函数, 让它返回*Pageerror.

代码语言:javascript
复制
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函数来测试一下我们刚刚写的内容:

代码语言:javascript
复制
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元素输出到窗口中.

你可以使用如下命令来编译执行代码:

代码语言:javascript
复制
$ go build wiki.go
$ ./wiki
This is a sample Page

(如果你在使用Windows系统的话, 你必须输入"wiki", 而没有"./", 来运行这个文件.)

如下是我们到现在所写的全部代码

代码语言:javascript
复制
//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服务器代码:

代码语言:javascript
复制
// +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的子切片"

如果你用浏览器访问如下网址:

代码语言:javascript
复制
http://localhost:8080/monkeys

这个程序就会在页面中呈现出:

代码语言:javascript
复制
Hi there, I love monkeys!

未完待续

原创的版权均归本人所有,任何人或团体、机构全部转载或者部分转载、摘录,请保留本博客链接或标注来源。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档