当前位置: 首页 > news >正文

Go语言写Web 应用程序

介绍

涵盖内容:
  • 为载入和保存方法创建一个数据结构体
  • 引用http包来创建一个web应用
  • 引用template包来处理HTML模板
  • 引用regexp包来验证用户的输入
  • 引用 闭包操作
可能涉及到的知识:
  • 设计经验
  • 明白基础的web技术(HTTP,HTML)
  • 一些UNIX命令行知识

从这里开始

你要有一个可以运行Go语言的计算机或虚拟机,怎么样安装Go,请参考安装Go教程。首先创建一个目录,在目录下创建一个wiki.go文件,用你喜欢的编辑器打开并输入以下内容:
package main

import (
"fmt"
"io/ioutil"
"os"
)


这fmt,ioutil和os都是go语言的标准库,一会我将增加其他方法和更多的包。
数据结构
让我们声明一个数据结构,这个结构主要包含两个字段,一个是标题,一个是内容。
type Page struct {
Title string
Body []byte
}


接下来,我们给Page 这个结构体写个保存方法,代码如下:
func (p *Page) save() os.Error {
filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.Body, 0600)
}


这个方法的签名是:接收一个Page结构体指针,返回一个os.Error错误。
在一下的代码中还是用了http包和模板包,具体内容参考具体代码,再这里就不详细贴出来了。下面是模板内容,把他们放到wiki.go同一目录下。

编辑页面 模板eidt.html

<h1>Editing {{.Title |html}}</h1>

<form action="/save/{{.Title |html}}" method="POST">
<div><textarea name="body" rows="20" cols="80">{{printf "%s" .Body |html}}</textarea></div>
<div><input type="submit" value="Save"></div>
</form>


查看页面模板view.html

<h1>{{.Title |html}}</h1>

<p>[<a href="/edit/{{.Title |html}}">edit</a>]</p>

<div>{{printf "%s" .Body |html}}</div>

完整代码:wiki.go

package main

import (
"http"
"io/ioutil"
"os"
"regexp"
"template"
)

type Page struct {
Title string
Body []byte
}

func (p *Page) save() os.Error {
filename := p.Title + ".txt"
return ioutil.WriteFile(filename, p.Body, 0600)
}

func loadPage(title string) (*Page, os.Error) {
filename := title + ".txt"
body, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return &Page{Title: title, Body: body}, nil
}

func viewHandler(w http.ResponseWriter, r *http.Request, title string) {
p, err := loadPage(title)
if err != nil {
http.Redirect(w, r, "/edit/"+title, http.StatusFound)
return
}
renderTemplate(w, "view", p)
}

func editHandler(w http.ResponseWriter, r *http.Request, title string) {
p, err := loadPage(title)
if err != nil {
p = &Page{Title: title}
}
renderTemplate(w, "edit", p)
}

func saveHandler(w http.ResponseWriter, r *http.Request, title string) {
body := r.FormValue("body")
p := &Page{Title: title, Body: []byte(body)}
err := p.save()
if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError)
return
}
http.Redirect(w, r, "/view/"+title, http.StatusFound)
}

var templates = make(map[string]*template.Template)

func init() {
for _, tmpl := range []string{"edit", "view"} {
t := template.Must(template.ParseFile(tmpl + ".html"))
templates[tmpl] = t
}
}

func renderTemplate(w http.ResponseWriter, tmpl string, p *Page) {
err := templates[tmpl].Execute(w, p)
if err != nil {
http.Error(w, err.String(), http.StatusInternalServerError)
}
}

const lenPath = len("/view/")

var titleValidator = regexp.MustCompile("^[a-zA-Z0-9]+$")

func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
title := r.URL.Path[lenPath:]
if !titleValidator.MatchString(title) {
http.NotFound(w, r)
return
}
fn(w, r, title)
}
}

func main() {
http.HandleFunc("/view/", makeHandler(viewHandler))
http.HandleFunc("/edit/", makeHandler(editHandler))
http.HandleFunc("/save/", makeHandler(saveHandler))
http.ListenAndServe(":8080", nil)
}
 
  

运行测试:

$ 8g wiki.go
$ 8l wiki.8
$ ./8.out
在地址栏输入地址:http://localhost:8080/view/aNewPage

效果图:

相关文章:

  • 注册表操作技巧及键值类型的判断
  • 迎接“云”时代的全面到来
  • QMenu,QT的菜单添加
  • Android开发基本篇(二)
  • Java的主要特性?
  • 为WP7添加动态Tile
  • [zz]Linux性能测试工具Lmbench介绍和使用说明
  • ACL配置
  • Ubuntu下使用虚拟机安装xp系统
  • [转]一个老工程师给年轻人的忠告
  • Oracle官网提供的虚拟机下载,方便测试和开发环境
  • CentOS6.2配置php-cgi错误解决办法
  • 对不含数据源的DataGridView实现自定义排序
  • 明晰单元测试
  • XNA游戏:手势触控
  • CODING 缺陷管理功能正式开始公测
  • macOS 中 shell 创建文件夹及文件并 VS Code 打开
  • Median of Two Sorted Arrays
  • spark本地环境的搭建到运行第一个spark程序
  • swift基础之_对象 实例方法 对象方法。
  • Vue.js源码(2):初探List Rendering
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • 编写符合Python风格的对象
  • 警报:线上事故之CountDownLatch的威力
  • 蓝海存储开关机注意事项总结
  • 使用 QuickBI 搭建酷炫可视化分析
  • 试着探索高并发下的系统架构面貌
  • 温故知新之javascript面向对象
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 责任链模式的两种实现
  • 【干货分享】dos命令大全
  • Nginx实现动静分离
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • # Java NIO(一)FileChannel
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • (Forward) Music Player: From UI Proposal to Code
  • (二开)Flink 修改源码拓展 SQL 语法
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (十一)c52学习之旅-动态数码管
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .Net Redis的秒杀Dome和异步执行
  • .NET版Word处理控件Aspose.words功能演示:在ASP.NET MVC中创建MS Word编辑器
  • .Net的DataSet直接与SQL2005交互
  • .NET企业级应用架构设计系列之技术选型
  • .NET企业级应用架构设计系列之开场白
  • .NET实现之(自动更新)
  • .php结尾的域名,【php】php正则截取url中域名后的内容
  • @Autowired @Resource @Qualifier的区别
  • [ vulhub漏洞复现篇 ] Grafana任意文件读取漏洞CVE-2021-43798