GoLang--Web开发学习

Web工作方式

一个Web服务器一般通过HTTP 协议与客户端进行通信,即用户访问的浏览器等界面

Web服务器的工作原理可以归纳为

  • 客户机通过TCP/IP协议建立到服务器的TCP连接
  • 客户端向服务器发送HTTP协议请求包,请求服务器里的资源文档
  • 服务器向客户机发送HTTP协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理“动态内容”,并将处理得到的数据返回给客户端
  • 客户机与服务器断开。由客户端解释HTML文档,在客户端屏幕上渲染图形结果

一般服务器和客户端一次请求则获得一次链接,在服务器发送应答消息后和客户端的连接就断开了,在下一次请求时才重新建立连接

 

Go搭建一个Web服务器

通过编写一个web.go代码,建立一个服务器,在9090端口监听http请求,实现代码如下

package main

import (
	"fmt"
	"net/http"
	"strings"
	"log"
)

func sayhelloName(w http.ResponseWriter, r *http.Request) {
	r.ParseForm()  //解析参数,默认是不会解析的
	fmt.Println(r.Form)  //这些信息是输出到服务器端的打印信息
	fmt.Println("path", r.URL.Path)
	fmt.Println("scheme", r.URL.Scheme)
	fmt.Println(r.Form["url_long"])
	for k, v := range r.Form {
		fmt.Println("key:", k)
		fmt.Println("val:", strings.Join(v, ""))
	}
	fmt.Fprintf(w, "Hello astaxie!") //这个写入到w的是输出到客户端的
}

func main() {
	http.HandleFunc("/", sayhelloName) //设置访问的路由
	err := http.ListenAndServe(":9090", nil) //设置监听的端口
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

执行go build指令后,会出现一个exe文件,在终端运行该exe文件可以打开服务器,通过本地http请求访问浏览器http://localhost:9090,可以看到界面显示如下结果,即已经成功建立连接

更换一个地址:http://localhost:9090/?url_long=111&url_long=222,可以看到服务器的map出现了url_long字段值为我们输入地址的111和222,相应的key和value值也被修改

 

Go如何使得Web工作

Go实现Web服务工作模式的流程图如下

图中的几个单词解释如下

Request:用户请求的信息,用来解析用户的请求信息,包括post、get、cookie、url等信息

Response:服务器需要反馈给客户端的信息

Connect:用户的每次请求链接

Handler:处理请求和生成返回信息的处理逻辑

要使GO能完成Web的请求和响应工作,只需要依据以下http协议的执行流程即可

  1. 创建Listen Socket, 监听指定的端口, 等待客户端请求到来。

  2. Listen Socket接受客户端的请求, 得到Client Socket, 接下来通过Client Socket与客户端通信。

  3. 处理客户端的请求, 首先从Client Socket读取HTTP请求的协议头, 如果是POST方法, 还可能要读取客户端提交的数据, 然后交给相应的handler处理请求, handler处理完毕准备好客户端需要的数据, 通过Client Socket写给客户端。

根据之前编写的代码可知,在go语言封装好的net/http包中包含web访问的一系列函数,其中http监听端口的创建只需要调用http.ListenAndServe函数即可创建监听端口并处理接收客户端的请求信息

该函数实际上是Listen和Serve函数的结合,底层的实现是初始化一个server对象,然后调用了net.Listen("tcp", addr),也就是底层用TCP协议搭建了一个服务,然后监控我们设置的端口,之后调用srv.Serve(net.Listener)函数处理接收客户端的请求信息,创建了一个Conn连接并单开了一个goroutline进行请求接受,具体流程示意图如下

Go的http包

Go的http有两个核心功能:Conn、ServeMux

Conn的goroutine

Go为了实现高并发和高性能, 使用了goroutines来处理Conn的读写事件, 这样每个请求都能保持独立,相互不会阻塞,可以高效的响应网络事件。这是Go高效的保证。客户端的每次请求都会创建一个Conn,这个Conn里面保存了该次请求的信息,然后再传递到对应的handler,该handler中便可以读取到相应的header信息,这样保证了每个请求的独立性。

ServeMux的自定义

在创建conn.server的时候,内部调用了http包默认的路由器,通过路由器把本次请求的信息传递到了后端的处理函数,这个http包自带的路由器就是SerVeMux,他的源码结构定义如下

type ServeMux struct {
	mu sync.RWMutex   //锁,由于请求涉及到并发处理,因此这里需要一个锁机制
	m  map[string]muxEntry  // 路由规则,一个string对应一个mux实体,这里的string就是注册的路由表达式
	hosts bool // 是否在任意的规则中带有host信息
}

通过以下代码可以创建一个简单路由器,通过路由器访问9090端口

package main

import (
	"fmt"
	"net/http"
)

type MyMux struct {
}

func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path == "/" {
		sayhelloName(w, r)
		return
	}
	http.NotFound(w, r)
	return
}

func sayhelloName(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello myroute!")
}

func main() {
	mux := &MyMux{}
	http.ListenAndServe(":9090", mux)
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值