go web的简单实现

搭建

  go的标准库net/http提供了HTTP客户端和服务端的实现,本章参考《Go语言高并发与微服务实战》一书,对其goweb代码进行分析实践。
  该代码的主要目标是实现一个简单的http服务器,对通过浏览器传过来的数据进行解析并保存,并通过浏览器查询保存的数据。包括一个简单的html代码与go代码。
  html页面代码如下,将其保存为login.tpl文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login Test</title>
</head>
<body>
    <form action="/login" method="post">
        用户名:<input type="text" name="username">
        密码:<input type="password" name="password">
        <input type="submit" value="登录">
    </form>
</body>
</html>

  go代码如下,被命名为StoreTest.go,在该代码中有详细注释

package main

import (
	"encoding/json"
	"fmt"
	"html/template"
	"log"
	"net/http"
)

/**
 * @Description: 构建一个用户的结构体
 */
type UserS struct {
	Id       int
	Name     string
	Password string
}

// 模拟存储,以id为键,UserS为值
var UserById = make(map[int]*UserS)
// 用户名为键,同名的人组成的切片为值
var UserByName = make(map[string][]*UserS)

/**
 * @Description: 用于接收页面提交的表单数据
 * @param w ResponseWriter接口被HTTP处理器用于构造HTTP回复
 * @param r Request类型代表一个服务端接受到的或者客户端发送出去的HTTP请求
 */
func loginMemory(w http.ResponseWriter, r *http.Request) {
	// 打印页面请求方式
	fmt.Println("method: ", r.Method)
	if r.Method == "GET" {
		// ParseFiles方法解析filenames指定的文件里的模板定义并将解析结果与t关联。
		// 如果发生错误,会停止解析并返回nil,否则返回(t, nil)。至少要提供一个文件。
		t, _ := template.ParseFiles("login.tpl")
		// Execute方法将解析好的模板应用到data上,并将输出写入wr。
		// 如果执行时出现错误,会停止执行,但有可能已经写入wr部分数据。模板可以安全的并发执行
		log.Println(t.Execute(w, nil))
	} else {
		// ParseForm解析URL中的查询字符串,并将解析结果更新到r.Form字段
		_ = r.ParseForm()
		fmt.Println("username: ", r.Form["username"])
		fmt.Println("password: ", r.Form["password"])
		// 创建对应的结构体,这里将id固定为1
		user1 := UserS{1, r.Form.Get("username"), r.Form.Get("password")}
		if pwd := r.Form.Get("password"); pwd == "123456" {
			// 将该用户存储
			store(user1)
			// Fprintf根据format参数生成格式化的字符串并写入w。返回写入的字节数和遇到的任何错误
			// 即返回页面显示内容
			w.Header().Set("Content-Type","application/json")
			// 自定义头部
			w.Header().Set("X-Custom-Header","custom")
			// 写入状态码
			w.WriteHeader(201)
			// 将该结构体解析成json
			json,_ := json.Marshal(user1)
			// 写入用户
			w.Write(json)
			fmt.Fprintf(w, "欢迎登录,Hello %s!", r.Form.Get("username"))
		} else {
			fmt.Fprintf(w, "密码错误,请重新输入!")
		}
	}
}

/**
 * @Description: 存储用户信息
 * @param user 含有用户信息的结构体
 */
func store(user UserS) {
	UserById[user.Id] = &user
	UserByName[user.Name] = append(UserByName[user.Name], &user)
}

/**
 * @Description: 查询用户信息,这里都写死了,没有给出info页面所需要的表单
 * @param w ResponseWriter接口被HTTP处理器用于构造HTTP回复
 * @param r Request类型代表一个服务端接受到的或者客户端发送出去的HTTP请求
 */
func userInfo(w http.ResponseWriter, r *http.Request) {
	fmt.Println(UserById[1])
	r.ParseForm()
	// 遍历同名的人
	for _, user := range UserByName[r.Form.Get("username")] {
		fmt.Println(w, " %v", user)
	}
}

func main() {
	// HandleFunc注册一个处理器函数handler和对应的模式pattern(注册到DefaultServeMux)。
	// ServeMux的文档解释了模式的匹配机制。
	// 即将相对路径与对应处理方法绑定,就像java里的@RequestMapping注解,映射URL
	http.HandleFunc("/login", loginMemory)
	http.HandleFunc("/info", userInfo)
	// ListenAndServe监听TCP地址addr,并且会使用handler参数调用Serve函数处理接收到的连接。
	// handler参数一般会设为nil,此时会使用DefaultServeMux。
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

  两个文件的存放结构如下,go代码放在main包,login.tpl与main包是同级关系
在这里插入图片描述

一些函数作用

  为了方便大家,就把go标准库中文版的一些注释贴上来了

html/template包

  就是用于解析上述login.tpl文件的,不过中文注释方法名有误,注意一下就行。
在这里插入图片描述

net/http包

http.ResponseWriter,嵌套了Header
在这里插入图片描述
http.ResponseWriter里面的Header
在这里插入图片描述

http.Request,这个结构体字段太多了,可前往手册查阅
在这里插入图片描述
http.Request的ParseForm()方法
在这里插入图片描述
HandleFunc
在这里插入图片描述
ListenAndServe
在这里插入图片描述

fmt包

FPrintf()
在这里插入图片描述

运行

刚运行时,浏览器输入localhost:8080/login,界面是这样的
在这里插入图片描述
控制台界面是这样的
在这里插入图片描述
在表单提交数据后,密码错误时
在这里插入图片描述
在这里插入图片描述
密码正确时
在这里插入图片描述
在这里插入图片描述
然后在浏览器输入localhost:8080/info,因为并没有给浏览器返回数据,所以是空白的
在这里插入图片描述
控制台会出现
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值