Golang网络编程 实现简单的登录注册功能(无gin框架)

Golang网络编程 实现简单的登录注册功能

import必要的包
package main

import (
	"database/sql"  //mysql包
	"encoding/json" // 编码为json类型的字符串传输
	"fmt"           //格式化输入输出
	"io"            //输入输出流
	//"html/template" //go数据渲染到html页面
	"log"           //日志包
	"net/http"      //http包
	_ "github.com/go-sql-driver/mysql" //mysql驱动
)

大多数包可以在正确的路径下直接引入,但是MySQL驱动需要安装MySQL后引入(安装时我选择的server)

主调函数

我们先注册路由,登录和注册还有测试的路由时分开的,所以需要建立不同的路由"/x",并且对端口进行监听ListenAndServe()

func main() {
	mux := http.NewServeMux()             //定义新路由
	mux.HandleFunc("/login", Login)       // 登录路由
	mux.HandleFunc("/register", register) // 注册路由
	err := http.ListenAndServe(":5007", mux) //监听端口
	//可以登录http://localhost:5007/register?username=zwx&password=123 进行数据测试!
    //在命令行输入:curl "http://localhost:5007/register?username=zwx&password=123"
	if err != nil {
		log.Fatal("ListenAndServer:", err.Error())
	}
}
数据准备

和前端明确我们要传的是哪些内容:前端传给后端的变量名称(一致性)、后端发送给前端的json字符串键值

返回内容
//Result 从后端返回给前端的反馈字符内容(方便修改反馈的内容)
type Result struct {
	Msg string `json:"msg"`
}
传输变量
//Post 定义传输的数据类型及数据变量名称(一定要前后端统一)!
type Post struct {
	userName string //用户名
	userPwd  string //密码
}
实现登录注册功能的具体函数

由于我们需要先注册后登录,按照思维的顺序,我们先写注册的函数。

注册
前提设置

我们先在register函数的开始写上允许跨域和序列化json的请求头

	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")
处理前端传入的数据及数据库的操作
	r.ParseForm()                  //解析一定要执行,否则r.Form无法运行
	username := r.Form["username"] //解析传下来的username
	password := r.Form["password"] //解析传下来的password

	db, err := sql.Open("mysql", "sqlname:sqlpassword@/dbname?charset=utf8") //登录数据库
	if err != nil {
		fmt.Println("Fail to connect to mysql!") //连接数据库失败
		return
	}
	defer db.Close()                            //在返回前关闭资源
	fmt.Println("Succeed to connect to mysql!") //连接数据库成功

	var post Post                            
	post.userName = username[0]                 //每次取第一个值,所以加[0]
	post.userPwd = password[0]                  //每次取第一个值,所以加[0]

     _, err = db.Exec("INSERT INTO user(username,password)VALUES(?,?)", post.userName,      post.userPwd) //插入数据
把字符串反馈给前端

我们通常选择用json编码及解码字符串来实现前后端的“沟通”过程,golang直接调用encoding/json包中的json.Marshal()函数即可实现.json这样格式的数据就是我们的桥梁!

	//不论是否注册成功,都会对返回的文字进行编码(给用户反馈成功或失败等字符)
	if err != nil { //插入数据失败
		res := Result{Msg: "Fail to register"}
			jsonChar, jsonErr := json.Marshal(res) //编码返回信息
		if jsonErr != nil {                    //编码失败
			fmt.Println("Fail to encode!")
		} else {
            w.Write(jsonChar)
		}
	} else { //插入数据成功
		res := Result{Msg: "Succeed to register"}
		jsonChar, jsonErr := json.Marshal(res) //json格式化
		if jsonErr != nil {
			fmt.Println("Fail to encode!") //编码失败
		} else {
			w.Write(jsonChar)
		}
	}
登录

其实登录和注册函数的基本过程是一样的,所以说其代码几乎也不会又太大差别。需要注意的是在进行数据库操作时,我们不是写入数据了,我们需要对数据库的数据进行遍历搜索,一一与传入数据进行对比,存在数据且用户名和密码对应则说明登录成功,反之则登录失败。

前提设置
	w.Header().Set("Access-Control-Allow-Origin", "*")
	w.Header().Set("Content-Type", "application/json")
处理前端传入的数据及数据库的操作
	r.ParseForm()   
	username := r.Form["username"] 
	password := r.Form["password"] 

	db, err := sql.Open("mysql", "sqlname:sqlpasswor@/dbname?charset=utf8")
	if err != nil {
		fmt.Println("Fail to connect to mysql!")
		return
	}
	defer db.Close()                          
	fmt.Println("Succeed to connect to mysql!")

	var post Post
	post.userName = username[0]
	post.userPwd = password[0]

	var row *sql.Row
	row = db.QueryRow("select *from user where username=? and password=?", post.userName, post.userPwd) //检索数据
	err = row.Scan(&post.userName, &post.userPwd)  //遍历!!!   
把字符串反馈给前端
if err != nil {
		res := Result{Msg: "Fail to login"}    //数据库没有这个数据(登录失败)
		jsonChar, jsonErr := json.Marshal(res) //json格式化
		if jsonErr != nil {
			fmt.Println("Fail to encode!") //格式化失败
		} else {
			w.Write(jsonChar)
		}
	} else {
		res := Result{Msg: "Succeed to login"}
		jsonChar, jsonErr := json.Marshal(res) //json格式化
		if jsonErr != nil {
			fmt.Println("Fail to encode!") //格式化失败
		} else {
			w.Write(jsonChar)
		}
	}
MySQL数据库的简单操作

为了更直观的展示,给出下面几个截图:
展示数据库
新建数据库:
新建数据库
使用该数据库:
使用该数据库
新建表格(截图有误,看最后一次建立的)
新建表格
该数据库下的表格:
该数据库下的表格
展示该表格数据情况:
展示该表格
这里没有接入school这个数据库,所以用user数据库中的user表格来查询数据:
查询该表格内的数据

总结
关于前后端交互原理小结

先放出下面这副图,可以加强理解:
在这里插入图片描述

这个图很概括性地将前端请求,后端处理,并响应前端的过程描述 了出来,这也就是实现一个网站的基本思路,但在这个过程中,会遇到很多很多困难,分块去处理会更加高效!

后端代码的整洁性

我这次写出了代码并不整洁,可以从多个方面进行提升:

·调包的形式来写代码,比如数据准备、数据库操作等等代码单独放在一个包里,在需要的时候,用调包的方法来使用其中的数据或功能即可。

· 写反馈报错功能时占用了不少空间,导致循环判断较多时让思维有些混乱,最主要还不方便去修改内容。所以以后选择定义一个新的函数checkerr()来专门检测错误,比如:

func checkerr(err Err) {
	if err != nil {
		...
	}
}
前后端功能的交融

前后端同学分别写好了前后端分离的代码后,也可以单独运行了,但是存在一个问题就是如何交融起来?在我这里监听的端口及url是本地的(localhost:xxxx),通过请教其他同学,了解到了CSDN上本地局域网网站的发布&内网穿透的实现,这对我来说,是一个非常实用的方法!候选将自己的内网穿透为其对应的外网url地址,可以在外部访问。前端将自己写好的html发布,于是可以通过外部访问网址,找到其对应的文件。

目前还在尝试通过调用"html/template"包来实现从后端本地对网页进行渲染这一方法。

json交互时踩过的坑坑些

· 不要去返回一些莫名其妙奇奇怪怪的东西其实就是不要返回那些没有必要的内容,尽量保持返回信息的简洁性,否则前端处理起来会很麻烦,而且划重点,前端可能会解析不出来返回的json字符串~~,这就很惨,死得不明不白的~~。

· 本来我传给前端的字符串是这样的:

res := "Succeed to register"

前端同学:“xxx,你把要传给我的json字符串键值给我一下呢。”

我:“嗯???还要传键值?和map[]一样那种吗?”

一脸懵逼的我开始改自己的存储返回内容代码…

最终在结构体中存储要返回的值及变量名称,具体的情况如下呢:

type Result struct {
	Msg string `json:"msg"`
}

然后赋值就是用结构体的方法就OK!

res := Result{Msg: "Fail to login"}
//传前端的话,感觉用下面的方式也很清爽
w.Write(jsonChar)
err := json.NewEncoder(w).Encode(res)//这样也行,但是不方便取jsonChar这个处理值
//下面的方式就不适用了,直接写到网页页面上去了=^=
io.WriteString(w,string(jsonChar))

然后,键在、值也在,多好…

学会使用浏览器提供的F12控制台

我最常用的几栏就是这三个:
在这里插入图片描述

console检查运行时发生的错误,sources检查html哪行代码出现了报错,network用来看看后端反馈到网页的信息情况如何…具体的实践还需要慢慢积累。

路径问题要门当户对

把包的路径找对才能正确高效地使用,不然,就是疯狂报错“can not import xxx” 一片红催人泪下!当时刚开始写的时候,自己连github.com这个包在哪里都没有看见,找不到只能说自己没细心看准路径了。

最重要的事情占三行

把原理搞清楚再开始逐步推进代码!!!

把原理搞清楚再开始逐步推进代码!!!

把原理搞清楚再开始逐步推进代码!!!

简短的结束语

嗯,总结差不多就这样,代码质量也不高,实现的功能也只是初步的,一切都只是起点,遇到太多问题了,解决了一些,遗留了一些,抽空好好学学《计算机网络》,认真总结每一次的实践,积累得越来越多就好。最后上一幅图纪念大一第一次上手参与的网页,以后会写出更强大的后端代码的。
在这里插入图片描述

​ 2020.3.1(其实该2.29写,有点遗憾~)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr.zwX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值