------------------------------

  下面一段代码,实现了最简单的 Web 服务器:

编译环境:
  Linux Mint 18 Cinnamon 64-bit
  Golang 1.7 ------------------------------ // main.go
package main import (
"fmt"
"log"
"net/http"
) // 处理主页请求
func index(w http.ResponseWriter, r *http.Request) {
// 向客户端写入内容
fmt.Fprintf(w, "Hello World!")
} func main() {
http.HandleFunc("/", index) //设置访问的路由
err := http.ListenAndServe(":9090", nil) //设置监听的端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
} ------------------------------   执行上面的程序之后,打开 Web 浏览器,在地址栏输入:127.0.0.1:9090 就可以访问这个服务器了。它只实现了最简单的单一页面的输出。   接下来我们让服务器接受客户端输入的数据,然后将其反馈给客户端。   首先,我们要向客户端写入一个表单页面,以便客户端有地方可以填写数据和提交数据。然后还需要在服务端添加一个页面处理函数,用来处理用户提交的数据。下面就开始实现这个功能。 ------------------------------ // main.go
package main import (
"fmt"
"log"
"net/http"
) // 向客户端写入这些数据,以便客户端可以填写文本并提交
var indexHTML = `<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>测试</title>
</head>
<body>
<form action="/page" method="post">
用户名:<br>
<input name="username" type="text"><br>
请输入文本:<br>
<textarea name="usertext"></textarea><br>
<input type="submit" value="提交">
</form>
</body>
</html>` // 用于将页面重定向到主页
var redirectHTML = `<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta http-equiv="Refresh" content="0; url={{.}}">
</head>
<body></body>
</html>` // 处理主页请求
func index(w http.ResponseWriter, r *http.Request) {
// 向客户端写入我们准备好的页面
fmt.Fprintf(w, indexHTML)
} // 处理客户端提交的数据
func page(w http.ResponseWriter, r *http.Request) {
// 我们规定必须通过 POST 提交数据
if r.Method == "POST" {
// 解析客户端请求的信息
if err := r.ParseForm(); err != nil {
log.Println(err)
}
// 获取客户端输入的内容
userName := r.Form.Get("username")
userText := r.Form.Get("usertext")
// 将内容反馈给客户端
fmt.Fprintf(w, "你好 %s,你输入的内容是:%s", userName, userText)
} else {
// 如果不是通过 POST 提交的数据,则将页面重定向到主页
fmt.Fprintf(w, redirectHTML)
}
} func main() {
http.HandleFunc("/", index) // 设置访问的路由
http.HandleFunc("/page", page) // 设置访问的路由
err := http.ListenAndServe(":9090", nil) // 设置监听的端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
} ------------------------------   到此,我们已经实现了客户端和服务端的自由交互,但是将“页面内容”和“逻辑代码”混在一起总是不好的,下我们把“页面内容”和“逻辑代码”分开存放。   在 views 目录中创建 3 个 html 文件用于存放主页、反馈页面、重定向页面,内容如下: ------------------------------ <!-- views/index.html -->
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>测试</title>
</head>
<body>
<form action="/page" method="post">
用户名:<br>
<input name="username" type="text"><br>
请输入文本:<br>
<textarea name="usertext"></textarea><br>
<input type="submit" value="提交">
</form>
</body>
</html> ------------------------------ <!-- views/page.html -->
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
</head>
<body>
<h3>你好 {{.Name}},你输入的内容是:</h3>
<pre>{{.Text}}</pre>
<p><a href="/">返回</a></p>
</body>
</html> ------------------------------ <!-- views/redirect.html -->
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<meta http-equiv="Refresh" content="0; url={{.}}">
</head>
<body></body>
</html> ------------------------------ main.go 的内容如下: ------------------------------ // main.go
package main import (
"html/template"
"log"
"net/http"
) func checkErr(err error) {
if err != nil {
log.Println(err)
}
} // 存放用户数据
type UserData struct {
Name string
Text string
} // 渲染页面并输出
func renderHTML(w http.ResponseWriter, file string, data interface{}) {
// 获取页面内容
t, err := template.New(file).ParseFiles("views/" + file)
checkErr(err)
// 将页面渲染后反馈给客户端
t.Execute(w, data)
} // 处理主页请求
func index(w http.ResponseWriter, r *http.Request) {
// 渲染页面并输出
renderHTML(w, "index.html", "no data")
} // 处理用户提交的数据
func page(w http.ResponseWriter, r *http.Request) {
// 我们规定必须通过 POST 提交数据
if r.Method == "POST" {
// 解析客户端请求的信息
if err := r.ParseForm(); err != nil {
log.Println("Handler:page:ParseForm: ", err)
} // 获取客户端输入的内容
u := UserData{}
u.Name = r.Form.Get("username")
u.Text = r.Form.Get("usertext") // 渲染页面并输出
renderHTML(w, "page.html", u)
} else {
// 如果不是通过 POST 提交的数据,则将页面重定向到主页
renderHTML(w, "redirect.html", "/")
}
} func main() {
http.HandleFunc("/", index) // 设置访问的路由
http.HandleFunc("/page", page) // 设置访问的路由
err := http.ListenAndServe(":9090", nil) // 设置监听的端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
} ------------------------------   一般在收到客户端数据后,我们都希望把它存储在服务器中,以便客户端随时可以读取,下面我们就来实现这个功能,将用户提交的数据存储到服务器的 SQLite 数据库中(SQLite 仅用于测试,实际站点推荐使用 MongoDb)。   当然需要 "github.com/mattn/go-sqlite3" 这个包和 SQLite 开发环境: 1、在 Linux Mint 的终端输入“go get github.com/mattn/go-sqlite3”获取包文件。 2、在 Linux Mint 的软件管理器中搜索“Golang-github-mattn-go-sqlite3-dev”并安装。 3、在 Linux Mint 的软件管理器中搜索“SQLiteman”并安装(可选),用于查看 SQLite 数据库。   开发环境搭建好后,下面就是数据库操作代码: ------------------------------
// main.go
package main import (
"database/sql"
"html/template"
"log"
"net/http" _ "github.com/mattn/go-sqlite3"
) func checkErr(err error) {
if err != nil {
log.Println(err)
}
} // 存放用户数据
type UserData struct {
Name string
Text string
} // 渲染页面并输出
func renderHTML(w http.ResponseWriter, file string, data interface{}) {
// 获取页面内容
t, err := template.New(file).ParseFiles("views/" + file)
checkErr(err)
// 将页面渲染后反馈给客户端
t.Execute(w, data)
} // 写入数据库(返回写入后的数据)
func writeData(userData *UserData) string {
// 打开数据库
db, err := sql.Open("sqlite3", "./data.db")
checkErr(err)
defer db.Close() // 如果数据表不存在则创建(如果存在则跳过)
db.Exec(`create table data (id integer not null primary key, name text, data string);`) var olddata string // 数据库中已存在的数据
var sqlStmt string // sql 内容 // 查询用户是否存在,同时读取用户数据
err = db.QueryRow("select data from data where name = ?", userData.Name).Scan(&olddata)
if err != nil { // 用户不存在
sqlStmt = "insert into data(data, name) values(?,?)" // 添加数据
} else { // 用户存在
sqlStmt = "update data set data = ? where name == ?" // 更新数据
// 如果 data 为空,则删除用户
if len(userData.Text) == 0 {
sqlStmt = "delete from data where data >= ? and name == ?" // 删除字段
} else {
// 否则将 data 追加到数据库
userData.Text = olddata + "\n" + userData.Text
}
} // 准备 SQL
stmt, err := db.Prepare(sqlStmt)
checkErr(err)
defer stmt.Close() // 执行 SQL
_, err = stmt.Exec(userData.Text, userData.Name)
checkErr(err)
return userData.Text
} // 处理主页请求
func index(w http.ResponseWriter, r *http.Request) {
// 渲染页面并输出
renderHTML(w, "index.html", "no data")
} // 处理用户提交的数据
func page(w http.ResponseWriter, r *http.Request) {
// 我们规定必须通过 POST 提交数据
if r.Method == "POST" {
// 解析客户端请求的信息
if err := r.ParseForm(); err != nil {
log.Println("Handler:page:ParseForm: ", err)
} // 获取客户端输入的内容
u := UserData{}
u.Name = r.Form.Get("username")
u.Text = r.Form.Get("usertext") // 写入数据库,同时获取处理后的数据
u.Text = writeData(&u) // 渲染页面并输出
renderHTML(w, "page.html", u)
} else {
// 如果不是通过 POST 提交的数据,则将页面重定向到主页
renderHTML(w, "redirect.html", "/")
}
} func main() {
http.HandleFunc("/", index) // 设置访问的路由
http.HandleFunc("/page", page) // 设置访问的路由
err := http.ListenAndServe(":9090", nil) // 设置监听的端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
} ------------------------------   上面的例子只是简陋的代码,帮助入门,更深入的内容,请自行学习。 ------------------------------

代码片段 - Golang 实现简单的 Web 服务器的更多相关文章

  1. 使用 Nodejs 搭建简单的Web服务器

    使用Nodejs搭建Web服务器是学习Node.js比较全面的入门教程,因为要完成一个简单的Web服务器,你需要学习Nodejs中几个比较重要的模块,比如:http协议模块.文件系统.url解析模块. ...

  2. 20145216 20145330 《信息安全系统设计基础》 实验五 简单嵌入式WEB 服务器实验

    20145216 20145330 <信息安全系统设计基础> 实验五 简单嵌入式WEB 服务器实验 实验报告封面 实验步骤 1.阅读理解源码 进入/arm2410cl/exp/basic/ ...

  3. 自己动手模拟开发一个简单的Web服务器

    开篇:每当我们将开发好的ASP.NET网站部署到IIS服务器中,在浏览器正常浏览页面时,可曾想过Web服务器是怎么工作的,其原理是什么?“纸上得来终觉浅,绝知此事要躬行”,于是我们自己模拟一个简单的W ...

  4. 深入剖析tomcat之一个简单的web服务器

    这个简单的web服务器包含三个类 HttpServer Request Response 在应用程序的入口点,也就是静态main函数中,创建一个HttpServer实例,然后调用其await()方法. ...

  5. 20145210 20145226 《信息安全系统设计基础》实验五 简单嵌入式WEB服务器实验

    20145210 20145226 <信息安全系统设计基础>实验五 简单嵌入式WEB服务器实验 结对伙伴:20145226 夏艺华 实验报告封面 实验目的与要求 · 掌握在ARM开发板实现 ...

  6. 用node.js实现简单的web服务器

    node.js实现web服务器还是比较简单的,我了解node.js是从<node入门>开始的,如果你不了解node.js也可以看看! 我根据那书一步一步的练习完了,也的确大概了解了node ...

  7. 实验5 简单嵌入式WEB服务器实验 实验报告 20135303 20135326

    北京电子科技学院(BESTI) 实     验    报     告 课程:信息安全系统设计基础                班级:  1353 姓名:20135303 魏昊卿 学号:2013532 ...

  8. [置顶] 在Ubuntu下实现一个简单的Web服务器

    要求: 实现一个简单的Web服务器,当服务器启动时要读取配置文件的路径.如果浏览器请求的文件是可执行的则称为CGI程序,服务器并不是将这个文件发给浏览器,而是在服务器端执行这个程序,将它的标准输出发给 ...

  9. Tomcat剖析(一):一个简单的Web服务器

    Tomcat剖析(一):一个简单的Web服务器 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三):连接器 ...

随机推荐

  1. 如何开启php报错

    今天碰到一个很二的问题,安装了php网站之后,发现nginx一直无法解析到index.php文件,显示为空白,从后台的日志来看是500错误,但是同目录下的phpinfo.php却可以正常解析.想来应该 ...

  2. mediawiki 的使用 2

    要想外部电脑能访问你的网站,网站部署好后,在LocalSettings.php 里将这句 $wgServer = "http://localhost"; 改成 $wgServer ...

  3. 第三百二十七天 how can I 坚持

    都没心情学习了,睡觉.太失败了.  好了,你赢了,最怕女人不说话了,我妈一生气就不说话,有点怕我妈,你想删就把我删了吧,我不怪你. 给你个善意的建议,任何事情都要有度,过犹而不及,你是属于那种比较听家 ...

  4. Primitive Objects

    [Primitive Objects] Unity can work with 3D models of any shape that can be created with modelling so ...

  5. python知识点 2014-07-09

    迭代协议: 类实现方法__next__,则可以使用for.while来实现迭代 使用iter或者next实现手工迭代: L = [1,2,3] I = iter(L) print(I.next()) ...

  6. hdu 4289 Control(最小割 + 拆点)

    http://acm.hdu.edu.cn/showproblem.php?pid=4289 Control Time Limit: 2000/1000 MS (Java/Others)    Mem ...

  7. 深入理解inode与软硬链接

    一.inode是什么? 理解inode,要从文件储存说起. 文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector).每个扇区储存512字节(相当于0.5KB). 操作系统 ...

  8. URAL 2068 Game of Nuts (博弈)

    题意:给定 n 堆石子,每次一个人把它们分成三堆都是奇数的,谁先不能分,谁输. 析:因为每堆都是奇数,那么最后肯定都是要分成1的,那么就把不是1的全加和,然后判断奇偶就OK了. 代码如下: #prag ...

  9. 谈Android四大组件之Service篇

    Service简介 Service是Android系统中的四大组件之一,它是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序.Service必须在AndroidManifest.xml中声明 ...

  10. c++中从一段字符串中提取数字

    采用标准输入输出: 输入:12&3 34*133^3131   13031* 输出:12 3 34 133 3131 13031 思路,先将整个输入存进一个字符串,再解析字符串,这样运行速度会 ...