• Go For Web:一篇文章带你用 Go 搭建一个最简单的 Web 服务、了解 Golang 运行 web 的原理


    前言:

    本文作为解决如何通过 Golang 来编写 Web 应用这个问题的前瞻,对 Golang 中的 Web 基础部分进行一个简单的介绍。目前 Go 拥有成熟的 Http 处理包,所以我们去编写一个做任何事情的动态 Web 程序应该是很轻松的,接下来我们就去学习了解一些关于 Web 的相关基础,了解一些概念,以及 Golang 是如何运行一个 Web 程序的。
    文章预计分为四个部分逐步更新
    2023-04-13 星期四 一更 全文共计约 3800 字 阅读大约花费 5 分钟
    2023-04-14 星期五 二更(两篇) 全文共计约 2000 字 阅读大概花费 4 分钟
    2023-04-14 星期五 三更 全文共计约 2000 字 阅读大概花费 5 分钟


    文章目录:

    1. Web 的工作方式
    2. 用 Go 搭建一个最简单的 Web 服务
    3. 了解 Golang 运行 web 的原理
    4. Golang http 包详解(源码剖析)

    正文:

    用 Go 搭建一个最简单的 Web 服务

    在前面一节我们介绍了 Web 的工作方式,知道了 Web 是基于 HTTP 协议的一个服务, Go 语言里面提供了一个完善的 net/http 包,通过 http 包可以很方便的就搭建起来一个可以运行的 Web 服务。使用这个包也能很简单地对 Web 的路由、静态文件、模板、Cookie 等数据进行设置和操作。

    • http 包建立 Web 服务器

    先贴个go代码👇

    点击查看代码
    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    	"strings"
    )
    
    //处理函数
    func sayhelloName(w http.ResponseWriter, r *http.Request) {
    	r.ParseForm() // 解析参数,默认不会解析
    	fmt.Println(r.Form)// 以下这些信息是输出到服务端的打印信息:请求表单form、路径path、格式scheme
    	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.Fprintln(w, "Hello astaxie!") // 输出到客户端
    }
    
    func main() {
    	http.HandleFunc("/", sayhelloName) // 设置访问的路由
    	err := http.ListenAndServe(":9090", nil) // 设置监听的端口
    	if err != nil {
    		log.Fatal("ListenAndServe:", err)
    	}
    }

    go build + go run

    代码结构像这样 image

    在浏览器地址栏输入:

    http://localhost:9090

    结果如下↓
    image
    加个后缀看看服务器输出了什么↓
    image
    image

    在编写这个 Web 服务器的过程中,我们只调用了 http 包中的两个函数——ListenAndServe、HandleFunc
    我们编写的 sayhelloName 其实是我们写的一个逻辑(处理)函数 (Handler),类似于 php 里的控制层(controller)函数
    同时,golang还拥有 类似 python 这样的动态语言的特性,所以写 Web 应用很方便
    而且这个 Web 服务内部有支持高并发的特性,之后我们会仔细讲解。

    下面让我们看看 Go 的 Web 服务的工作方式
    看看Go 如何使得 Web 工作

    了解 Golang 运行 web 的原理

    首先我们先了解一下 Web 工作方式的几个概念
    以下是几个服务器端的概念

    • Request:用户请求的信息,用啦解析用户的请求信息,包括 post、get、cookie、url 等信息
    • Response:服务器需要反馈给客户端的响应信息
    • Conn:用户的每次请求连接(connect)
    • Handler:处理请求和生成返回信息的处理逻辑

    分析 http 包运行机制

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

    具体流程大概是这样:

    1. 创建 Listen Socket,监听指定端口等待客户端请求发送过来
    2. Listen Socket 接受从客户端发送来的请求,建立 Connect,得到 Client Socket,接下来通过 Client Socket 与客户端通信(中转站)
    3. 处理客户端的请求,首先从 Client Socket 读取 HTTP 请求的协议头,查看是哪一种方法,如果是 POST 方法,还可能要读取客户端提交的数据,然后交给响应的 Handler 处理请求,handler 处理完之后准备好客户端需要的数据,通过 Client Socket 写给客户端
      至此一次请求-响应过程结束

    在整个过程中,我们需要了解下面三个问题:

    • 如何监听端口?
    • 如何接受客户端请求?
    • 如何分配 Handler 处理客户端请求?

    对 Go 而言,是通过叫 ListenAndServe 来处理这个事情的
    底层细节是先初始化一个 server 对象,然后调用 net.Listen("tcp",addr),也就是底层使用了 TCP 协议搭建了一个服务,然后监听我们设置的端口
    源码如下:
    image
    image
    image

    上面的源码也实现了 接受客户端请求 的功能,在上面代码执行了监控端口之后调用了 srv.Serve(net.Listener),这个函数就是处理接受客户端的请求信息。在这个函数中 有一个 for {},里面首先通过 Listener 接受请求I.Accept(),其次创建了一个 Conn c,err := srv.newConn(rw)最后单独开了一个 goroutine go c.server() 把这个请求的数据当作参数扔给 conn 去服务。这里就体现了高并发,用户的每一次请求都是在一个新的 goroutine 去服务,互相不影响。

    那么最后一个问题,如何分配 handler 去处理请求的呢?
    conn 首先会解析 request :c.readRequest(),然后获取相应的 handler :handler := c.server.Handler 也就是我们调用 ListenAndServe 时候的第二个参数err := http.ListenAndServe(":9090", nil) 这里是 nil 也就是 空,默认会获取 handler = DefaultServeMux
    那么这个变量用来做什么呢?其实他就是一个路由器,用它来匹配 url 跳转到其相应的 handle 函数,我们之前调用代码的第一句就调用了 http.HandleFunc("/", sayhelloName) ,这个就是注册了请求 / 的路由规则,当我们 请求的 url 为 “/” 时,路由就会转到 sayhelloName 这个处理函数,DefaultServeMux 会调用 ServeHttp 方法,而这个方法内部其实就是调用 sayhelloName 本身,最后通过 response 的信息返回到客户端。

    流程如图↓
    image

    总结

    到这里我们对 Go 的 Web 服务工作原理有了基本的了解,下一节我们会继续去学习 Go 的 http 包,详细解剖以下里面的内容,了解其中的流程

    关于 Golang 基础部分 以及 计算机网络部分读者可以参阅我的往期 blog👇
    Goalng:基础复习一遍过

    漫谈计算机网络:网络层 ------ 重点:IP协议与互联网路由选择协议

    以上

    看完记得留下一个👍


    __EOF__

  • 本文作者: slowlydance2me
  • 本文链接: https://www.cnblogs.com/slowlydance2me/p/17315966.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    【JavaScript数据结构与算法】二、队列 及leetcode实战
    高考学计算机专业的小白指南,一些比较实用的软件,快速入手计算机
    REACT
    centos7下mongodb安装及开启副本
    玩转堆排序以及Topk问题——【数据结构】
    IntelliJ IDEA中构建Spring Boot的项目
    Java代码审计——WebGoat XML外部实体注入(XXE)
    基于JavaSwing开发MP3音乐播放器系统 课程设计 大作业源码 毕业设计
    相机平面与工作平面带夹角下的坐标换算
    babylon.js gltf scene hierarchy
  • 原文地址:https://www.cnblogs.com/slowlydance2me/p/17315966.html