代码片段 - Golang 实现简单的 Web 服务器

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

  下面一段代码,实现了最简单的 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 == ?" // 删除字段
		}
	}

	// 准备 SQL
	stmt, err := db.Prepare(sqlStmt)
	checkErr(err)
	defer stmt.Close()

	// 如果 data 为空,则删除用户,否则将 data 追加到数据库
	if len(userData.Text) > 0 {
		userData.Text = olddata + "\n" + userData.Text
	}

	// 执行 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)
	}
}

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

  上面的例子只是简陋的代码,帮助入门,更深入的内容,请学习《Go Web 编程》:

  https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/preface.md

------------------------------
时间: 2024-11-07 19:29:08

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

《Python入门》第一个Python Web程序——简单的Web服务器

上一篇讲了<Python入门>Windows 7下Python Web开发环境搭建笔记,接下来讲一下Python语言Web服务的具体实现:第一个Python Web程序--简单的Web服务器. 与其它Web后端语言不同,Python语言需要自己编写Web服务器. 如果你使用一些现有的框架的话,可以省略这一步: 如果你使用Python CGI编程的话,也可以省略这一步: 用Python建立最简单的web服务器 利用Python自带的包可以建立简单的web服务器.在DOS里cd到准备做服务器根目录

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

开篇:每当我们将开发好的ASP.NET网站部署到IIS服务器中,在浏览器正常浏览页面时,可曾想过Web服务器是怎么工作的,其原理是什么?“纸上得来终觉浅,绝知此事要躬行”,于是我们自己模拟一个简单的Web服务器来体会一下. 一.请求-处理-响应模型 1.1 基本过程介绍 每一个HTTP请求都会经历三个步凑:请求-处理-响应:每当我们在浏览器中输入一个URL时都会被封装为一个HTTP请求报文发送到Web服务器,而Web服务器则接收并解析HTTP请求报文,然后针对请求进行处理(返回指定的HTML页面

《Go语言入门》第一个Go语言Web程序——简单的Web服务器

概述 上一篇讲了 <Go语言入门>第一个Go语言程序--HelloWorld,接下来讲一下Go语言Web开发入门必修课:第一个Go语言Web程序--简单的Web服务器. 与其它Web后端语言不同,Go语言需要自己编写Web服务器. 有关本地环境的搭建与基础学习,请参考: <Go语言入门>如何在Windows下安装Go语言编程环境 Go语言Web应用:IBM的云平台Bluemix使用初体验--创建Go语言 Web 应用程序,添加并使用语言翻译服务 Web服务器代码 Google在ht

python搭建简单的web服务器

由于要做自动化和性能测试,工作中需要有一个能够控制返回消息数据的web服务器,所以用python初步实现了一个简单的web服务器,能够处理HTTP的请求(GET,POST,PUT),并完成响应.先简单说明下原理,python中实现web服务器大概分两个步骤: 1.      创建一个套接字,绑定到指定的IP和端口,保持监听 2.      创建一个handle类,当收到请求消息时,作出响应 主要使用的类有两个: HTTPServer:HTTP服务器的基类,提供了HTTP服务器的常用方法,创建服务

使用 Nodejs 搭建一个简单的Web服务器

使用Nodejs搭建Web服务器是学习Node.js比较全面的入门教程,因为要完成一个简单的Web服务器,你需要学习Nodejs中几个比较重要的模块,比如:http协议模块.文件系统.url解析模块.路径解析模块.以及301重定向问题,下面我们就简单讲一下如何来搭建一个简单的Web服务器. 作为一个Web服务器应具备以下几个功能: 1.能显示以.html/.htm结尾的Web页面 2.能直接打开以.js/.css/.json/.text结尾的文件内容 3.显示图片资源 4.自动下载以.apk/.

实验五(简单嵌入式WEB服务器实验)问题总结

实验五问题总结 问题链接:<信息安全系统设计基础>实验五实验报告 虽然将07_httpd文件中全部拷贝进了bc中,文件夹中拥有Makefile文件,但是还是无法通过make得到该文件夹中copy和httpd的可执行文件.解决:第一次是觉得Makefile文件中的PATH路径不对,将其改成了/home/bc/07_httpd存盘退出后发现还是无法执行,第二次我们直接使用gcc对其单步进行编译:armv4l-unknow-linux-gcc –E copy.c –o copy.iarmv4l-un

【重要】怎么自行搭建简单的web服务器

# -*- coding: utf-8 -*- #python 27 #xiaodeng #CGI模块 #怎么自行搭建简单的web服务器 #用途: #内网中,提供文件的共享服务非常有用,在cmd下启动运行服务器命令之后,其他电脑也是可以通过url访问的 #可以实现pdf.zip等压缩文件.exe.apk等软件的下载服务. ###搭建基本流程## #1.假定共享文件的目录为:/home/test,ip为#192.168.1.101 ''' 怎么查看本机IP? import socket mynam

如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1

原文:http://www.raywenderlich.com/2941/how-to-write-a-simple-phpmysql-web-service-for-an-ios-app 作为一个iPhone/iPad开发者,能够自己写一个简单的web服务器将是很有用的. 例如,你可能希望在软件启动时显示一些来自服务器的更新,或者在服务器端保存一些用户数据.除了你的想象力,没有什么能限制你了. 在第一篇中,我们将会一步一步的建立一个web服务器,基于promo code system(促销码系

信息安全系统设计基础实验五:简单嵌入式 WEB 服务器实验 (20135229,20135234)

北京电子科技学院(BESTI) 实     验    报     告 课程:信息安全系统设计                         班级:1352 姓名:马启扬 吕松鸿     学号:20135234 20135229 成绩:             指导教师:娄嘉鹏      实验日期:2015.11  实验密级:       预习程度:               实验时间:15:30—17:00  仪器组次:       必修/选修:必修        实验序号:05    实验