Go   发布时间:2022-04-09  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了使用Golang 搭建http web服务器大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

Golang在搭建web服务器方面的能力是毋庸置疑的。官方已经有提供net/Http包为搭建http服务器做准备。使用这个包能很简单地对web的路由,静态文件,模版,cookie等数据进行设置。至于这个包是否好用,这个就见仁见智了。你可以从net包开始封装一个web框架,当然也可以基于Http包封装一个web框架。但是不论你是打算怎么样做,了解基本的net/Http包一定是你借鉴的基础。

需求

我们要做两个简单的后台web系统。这个系统简单到只有两个页面:登陆和首页

1 登陆页面

登陆页面需要提交用户名和密码,将用户名和密码和MysqL数据库中的用户名密码比对达到验证的效果MysqL数据库的go语言驱动推荐使用myMysqLhttps://github.com/ziutek/mymysql)。

用户名密码正确的时候,需要在cookie中种下用户名和加密后的密钥来进行cookie认证。我们不对cookie设置ExpireTime,这样这个cookie的有效期就是浏览器打开到浏览器关闭的session期间。

另外,这个页面还需要加载一个js。提交用户名和密码的是由js进行ajax post命令进行查询的。

这个页面需要加载css,进行页面排版

2 首页

首页是非常简单,但它是一个动态页面。

首先右上角的”欢迎登陆, 管理员:yejianfeng“。这里的用户名yejianfeng是根据不同的用户会进行变化的。这里需要用到模版,我们又会用到了一个模版包html/template。这个包的作用就是加载模版。

其次这个页面也需要的是css,js(退出系统的删除cookie操作由js控制)

路由

分析下访问路径,会有几个文件:

/admin/index -- 首页

/login/index --登陆页显示

/ajax/login -- 登陆的ajax动作

/css/main.css -- 获取main的css文件

/js/login.js -- 获取登陆的js文件

在net/http包中,动态文件的路由和静态文件的路由是分开的,动态文件使用http.HandleFunc进行设置静态文件就需要使用到http.FileServer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package main
import (
"net/http"
)
func main() {
http.Handle( "/css/" ,http.FileServer(http.Dir( "template" )))
"/js/" )))
http.HandleFunc( "/admin/" "/login/" "/ajax/" "/" http.ListenAndServe( ":8888"
}

这里的http.FileServer(http.Dir("template"))的路径是怎么算的要注意下了。相对路径都是从当前执行路径路径下开始算的,这里设置的路径树是这样:

关于http.HandleFunc如果不理解请参考我的上一篇文章

http://www.cnblogs.com/yjf512/archive/2012/08/22/2650873.html

处理器

这里需要定制4个handler对应相应的一级路径。我们将这些个handler都放入到route.go文件

页面404处理器

main中的逻辑是当/admin/ /login/ /ajax/都不符合路径的时候就进入404页面处理器NotFoundHandler

12
func NotFoundHandler(w http.ResponseWriter,r *http.request) {
if r.URl.Path == {
http.Redirect(w,r, "/login/index" :1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,http.StatusFound)
}
t,err := template.ParseFiles( "template/html/404.html" )
(err != nil) {
log.Println(err)
}
t.Execute(w,nil)
这段逻辑是很清晰的:如果路径是"/" 即访问路径是http://192.168.100.166:8888/的时候,访问会跳转到登陆页面,否则当访问路径不满足制定的路由,读取404模版,显示404

强烈推荐使用template.ParseFile模版文件解析

template包中也提供了Parse这类直接在代码中写上模版的函数。使用起来,你会发现这类函数远没有ParseFile好用,原因很明显,如果你把模版写在代码中,一旦模版需要进行小细节的修改,也需要重新编译。并且我们使用模版的目的就是将显示逻辑和业务逻辑分离,Parse会导致整个代码是不可维护!

当然有人会虑到效率问题,一个是读取文件一个是直接读取内存。但是我觉得这点效率差别用户根本不会察觉到,牺牲极小的性能保证工程性是很值得的。

ParseFile中的路径问题也是很容易犯的问题。这里的填写相对路径,则文件是从当前执行的路径开始算。

比如这个路径,执行bin/webdemo,template/html/404.html就对应/go/gopath/template/html/404.html

这一步后续动作是在template/html文件夹中创建404.html页面

登陆页面处理器

17
18
func loginHandler(w http.ResponseWriter,monospace!important; min-height:auto!important">pathInfo := Strings.Trim(r.URl.Path,monospace!important; min-height:auto!important">)
parts := Strings.Split(pathInfo,monospace!important; min-height:auto!important">)
var action = ""
len(parts) > 1 {
action = Strings.title(parts[1]) + "Action"
}
login := &loginController{}
controller := reflect.ValueOf(login)
@H_19_148@method := controller.MethodByName(action)
!method.IsValid() {
@H_398_154@method = controller.MethodByName(Strings.title( "index" ) + "Action" )
}
requestValue := reflect.ValueOf(r)
responseValue := reflect.ValueOf(w)
@H_592_174@method.Call([]reflect.Value{responseValue,requestvalue})
根据MVC思想,对具体的逻辑内容使用不同的Controller,这里定义了一个loginController,使用reflect将pathInfo映射成为controller中的方法

这样做的好处显而易见:

1 清晰的文件逻辑。不同的一级目录分配到不同的控制器,不同的控制器中有不同的方法处理。这些控制器放在一个独立的文件中,目录结构清晰干净。

2 路由和业务逻辑分开。 main中的http.HandleFunc处理一级路由,route处理二级路由,controller处理业务逻辑,每个单元分开处理。

好了,下面需要定义loginContrller,我们另外起一个文件loginController.go

"html/template"
type loginController struct {
}
func ( this *loginController)IndexAction(w http.ResponseWriter,r *http.request) {
"template/html/login/index.html" )
(err != nil) {
log.Println(err)
}
:1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,nil)
下面需要创建template/html/login/index.html

这个文件中包含mian.css,jquery.js,base.js。 创建这些css和js。具体的css和js内容请看github源码

js中的逻辑是这样写的:当login表单提交的时候,会调用/ajax/login进行验证操作,下面就开始写ajax的处理器

ajax处理器

route中的ajaxHandler和loginHandler是大同小异,这里就忽略不说了,具体说一下ajaxController

18
19
20
21
22
23
24
25
@H_214_262@ 26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@H_851_301@ 41
@H_696_293@ 42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
"github.com/ziutek/myMysqL/autorc"
_ "github.com/ziutek/myMysqL/thrsafe"
"encoding/json"
)
type Result {
Ret int
Reason String
Data interface {}
type ajaxController {
}
*ajacController)LoginAction(w http.ResponseWriter,r *http.request) {
w.Header().Set( "content-type" "application/json" )
err := r.ParseForm()
err != nil {
OutputJson(w,monospace!important; min-height:auto!important; color:blue!important">"参数错误" :1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,nil)
@H_616_430@ return
}
admin_name := r.FormValue( "admin_name" )
admin_password := r.FormValue( "admin_password" )
admin_name == "" || admin_password == {
number31 index30 alt2" style="BACkground-color:rgb(244,nil)
return
}
db := MysqL.New( "tcp" "192.168.199.128" "root" "test" "webdemo" )
err := db.Connect(); err != nil {
"数据库操作失败" :1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,nil)
return
}
defer db.Close()
rows,res,err := db.Query( "SELEct * from webdemo_admin where admin_name = '%s'" :1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,admin_Name)
err != nil {
:1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,nil)
return
}
name := res.Map( )
admin_password_db := rows[0].Str(Name)
@H_616_543@
admin_password_db != admin_password {
"密码输入错误" :1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,nil)
return
}
// 存入cookie,使用COokie存储
expiration := time.Unix(1,0)
cookie := http.Cookie{name: String" style="white-space:pre-wrap; border:0px!important; bottom:auto!important; float:none!important; height:auto!important; left:auto!important; line-height:1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,Value: rows[0].Str(res.Map( )),Path: }
http.SetCookie(w,&cookiE)
"操作成功" :1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,nil)
return
}
func OutputJson(w http.ResponseWriter,ret int :1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,reason String :1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,i {}) {
out := &Result{ret,reason,i}
b,err := json.Marshal( )
@H_77_618@ err != nil {
return
}
w.Write(b)
这段代码有几个地方可以看看:

如何设置header:

w.Header().Set("content-type","application/json")

如何解析参数:

err := r.ParseForm()

admin_name := r.FormValue("admin_name")

如何连接数据库

db := MysqL.New("tcp","","192.168.199.128","root","test","webdemo")

当然这里得需要有个数据库和数据表,建表建表sql文件在github上能看到

create table webdemo_admin

(

admin_id int not null auto_increment,

admin_NAME VARCHAR(32) not null,sans-serif; font-size:14px"> admin_password varchar(32) NOT NULL,sans-serif; font-size:14px"> priMary key(admin_id)

);

如何设置cookie

cookie := http.Cookie{name: "admin_name",Value: rows[0].Str(res.Map("admin_name")),Path: "/"}

http.SetCookie(w,&cookiE)

主页处理器

adminHandler的逻辑比其他Handler多的一个是需获取cookie

cookie,err := r.Cookie("admin_name")

并且在传递给controller的时候需要将admin_name传递进去

21
func adminHandler(w http.ResponseWriter,0)!important">// 获取cookie
cookie,err := r.Cookie( err != nil || cookie.Value == {
number5 index4 alt2" style="BACkground-color:rgb(244,http.StatusFound)
}
)
admin := &adminController{}
controller := reflect.ValueOf(admin)
@H_398_154@method := controller.MethodByName(action)
!method.IsValid() {
)
}
requestValue := reflect.ValueOf(r)
responseValue := reflect.ValueOf(w)
userValue := reflect.ValueOf(cookie.value)
:1.8em!important; margin:0px!important; outline:0px!important; overflow:visible!important; padding:0px!important; position:static!important; right:auto!important; top:auto!important; vertical-align:baseline!important; width:auto!important; font-family:Consolas,requestValue,Uservalue})
其他的部分都是一样的了。

它对应的Controller的Action是

14
type User
{
UserName String
}
type adminController {
*adminController)IndexAction(w http.ResponseWriter,r *http.request,user ) {
"template/html/admin/index.html" (err != nil) {
log.Println(err)
}
number13 index12 alt2" style="BACkground-color:rgb(244,&User{user})
这里就将user传递出去给admin/index模版

模版内部使用{{.UserNamE}}进行参数显示

后记

至此,这个基本的webdemo就完成了。启动服务之后,就会在8888端口开启了web服务。

当然,这个web服务还有许多东西可以优化,个人信息验证,公共模板的提炼使用,数据库的密码使用密文等。但是这个例子中已经用到了搭建web服务器最基本的几个技能了。

本图文内容来源于网友网络收集整理提供,作为学习参使用,版权属于原作者。
@H_772_791@

使用Golang 搭建http web服务器

大佬教程官方1群(满)
大佬教程官方2群(满)
大佬教程官方3群
大佬教程官方4群

猜你在找的Go相关文章

方法和接收者 Go语言中的方法(Method)是一种作用于特定类型变量的函数。这种特定类型变量叫做接收者(Receiver)。接收者的概念就类似于其他语言中的this或者 self。 Go 语言中同时
函数是组织好的、可重复使用的、用于执行指定任务的代码块。 Go语言中支持函数、匿名函数和闭包,并且函数在Go语言中属于“一等公民”。 函数定义 Go语言中定义函数使用func关键字,具体格式如下: f
面向对象的三大特征: 封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式 继承:使得子类具有父类的属性和方法或者重新定义、追加属性和方法等 多态:不同对象中同种行为的不同实现方式 Go并不是一个纯
在工程化的开发项目中,Go语言的源码复用是建立在包(package)基础之上的。 包(package)是多个Go源码的集合,是一种高级的代码复用方案,Go语言提供了很多内置包,如fmt、os、io等。
为什么要学 Go 性能优越感;Go 极其地快,其性能与 Java 或 C++相似。在使用中,Go 一般比 Python 要快 30 倍; 序列化/去序列化、排序和聚合中表现优异; 开发者效率较高;多种
什么是反射 官方关于反射定义: Reflection in compuTing is the ability of a program to examine its own structure, pa
因为数组的长度是固定的并且数组长度属于类型的一部分,所以数组有很多的局限性。 func arraySum(x [3]int) int{ sum := 0 for _, v := range x{ su
接口(interface)定义了一个对象的行为规范,只定义规范不实现,由具体的对象来实现规范的细节。 接口类型 在Go语言中接口(interface)是一种类型,一种抽象的类型。 interface是

使用Golang 搭建http web服务器

微信公众号搜 "程序精选"关注

大佬总结

以上是大佬教程为你收集整理的使用Golang 搭建http web服务器全部内容,希望文章能够帮你解决使用Golang 搭建http web服务器所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:golanghttpweb使用搭建服务器
猜你在找的Go相关文章
其他相关热搜词更多
phpJavaPython程序员load如何string使用参数jquery开发安装listlinuxiosandroid工具javascriptcap