这是我参与8月更文挑战的第7天,活动详情查看: 8月更文挑战
Web 应用程序是一种可以通过 Web 访问的应用程序,Web 程序的最大好处是用户很容易访问应用程序,用户只需要有浏览器即可,不需要再安装其他软件。Web 应用对于身处互联网时代的我们来说太普遍。无论哪一种语言,只要它能够开发出与人类交互的软件,它就必然会支持 Web 应用开发。 本系列文章将会介绍 Go Web 的应用与实践。欢迎关注。
前面一篇文章,我们介绍了 Go Web 的流程框架 gin,Golang 提供的 net/http 库已经很不错了,对于 http 的协议的实现非常好,基于此再造框架,也不会是难事,因此生态中出现了很多框架,如 Gin、gorilla/mux、Echo 等。
本文将会介绍服务端存储相关的内容。Web 服务端需要持久化部分客户端的数据,包括文件、内存和数据库等存储介质。下面我们将介绍基于内存的存储实现。
内存存储
首先介绍的是基于内存的存储。在 Go 语言中将相关的数据信息存储在内存中,可以使用数组、切片、映射和结构等数据结构的方式。
我们在之前登录的示例基础上,将登录的用户信息存储在内存中,并增加一个接口,返回指定用户名的用户信息。代码如下:
package main
import (
"fmt"
"html/template"
"log"
"net/http"
)
type User struct {
Id int
Name string
Password string
}
var UserById = make(map[int]*User)
var UserByName = make(map[string][]*User)
func loginMemory(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) //获取请求的方法
if r.Method == "GET" {
t, _ := template.ParseFiles("login.tpl")
log.Println(t.Execute(w, nil))
} else {
//请求的是登录数据,那么执行登录的逻辑判断
_ = r.ParseForm()
fmt.Println("username:", r.Form["username"])
fmt.Println("password:", r.Form["password"])
user1 := User{1, r.Form.Get("username"), r.Form.Get("password")}
store(user1)
if pwd := r.Form.Get("password"); pwd == "123456" { // 验证密码是否正确
fmt.Fprintf(w, "欢迎登陆,Hello %s!", r.Form.Get("username")) //这个写入到w的是输出到客户端的
} else {
fmt.Fprintf(w, "密码错误,请重新输入!")
}
}
}
func store(user User) { // 存储用户信息
UserById[user.Id] = &user // 按照 id 存储
UserByName[user.Name] = append(UserByName[user.Name], &user) // 按照用户名存储
}
func userInfo(w http.ResponseWriter, r *http.Request) {
fmt.Println(UserById[1])
r.ParseForm()
for _, user := range UserByName[r.Form.Get("username")] {
fmt.Fprintf(w," %v",user ) //根据表单的用户名查询相应的记录
}
}
func main() {
http.HandleFunc("/login", loginMemory) //设置访问的路由
http.HandleFunc("/info", userInfo) // 访问用户信息
err := http.ListenAndServe(":8080", nil) //设置监听的端口
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
登录的结果与之前相同,然后我们访问 /info 接口,得到如下的结果:
可以看到,返回的内容为我们在登录时输入的信息。分析以上的代码实现,我们在程序的开头定义了全局变量:
var UserById = make(map[int]*User)
var UserByName = make(map[string][]*User)
分别用来存储 Id-User 与 Name-User 的映射,UserById 会将帖子的唯一 Id 映射至指向帖子的指针,而 UserByName 则会将用户名映射至一个切片,这个切片可以包含多个指向用户的指针。这两个变量映射指向的是 User 的指针,因此可以确保无论是通过哪种方式来获取 User 信息,得到的都是相同的 User,而不是同一 User 的不同副本。 store 方法用于存储用户信息。获取用户信息时,根据指定的用户名,返回对应的用户信息。
小结
本文主要介绍了 Go 服务端基于内存实现存储的方式,比较简单。与其他语言不太一样,Go 没有内置的驱动支持任何的数据库,但是 Go 定义了database/sql 接口,用户可以基于驱动接口开发相应数据库的驱动。这样做有一个好处,只要是按照标准接口开发的代码, 以后需要迁移数据库时,不需要任何修改。那么 Go 都定义了哪些标准接口呢?下篇文章将会具体介绍。
阅读最新文章,关注公众号:aoho求索