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 分钟
文章目录:
- Web 的工作方式
- 用 Go 搭建一个最简单的 Web 服务
- 了解 Golang 运行 web 的原理
- 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
代码结构像这样 
在浏览器地址栏输入:
结果如下↓

加个后缀看看服务器输出了什么↓


在编写这个 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 服务的工作模式的流程如下图

具体流程大概是这样:
- 创建 Listen Socket,监听指定端口等待客户端请求发送过来
- Listen Socket 接受从客户端发送来的请求,建立 Connect,得到 Client Socket,接下来通过 Client Socket 与客户端通信(中转站)
- 处理客户端的请求,首先从 Client Socket 读取 HTTP 请求的协议头,查看是哪一种方法,如果是 POST 方法,还可能要读取客户端提交的数据,然后交给响应的 Handler 处理请求,handler 处理完之后准备好客户端需要的数据,通过 Client Socket 写给客户端
至此一次请求-响应过程结束
在整个过程中,我们需要了解下面三个问题:
- 如何监听端口?
- 如何接受客户端请求?
- 如何分配 Handler 处理客户端请求?
对 Go 而言,是通过叫 ListenAndServe 来处理这个事情的
底层细节是先初始化一个 server 对象,然后调用 net.Listen("tcp",addr),也就是底层使用了 TCP 协议搭建了一个服务,然后监听我们设置的端口
源码如下:



上面的源码也实现了 接受客户端请求 的功能,在上面代码执行了监控端口之后调用了 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 的信息返回到客户端。
流程如图↓

总结
到这里我们对 Go 的 Web 服务工作原理有了基本的了解,下一节我们会继续去学习 Go 的 http 包,详细解剖以下里面的内容,了解其中的流程
关于 Golang 基础部分 以及 计算机网络部分读者可以参阅我的往期 blog
Goalng:基础复习一遍过
漫谈计算机网络:网络层 ------ 重点:IP协议与互联网路由选择协议
以上
看完记得留下一个
Go For Web:一篇文章带你用 Go 搭建一个最简单的 Web 服务、了解 Golang 运行 web 的原理的更多相关文章
- 一篇文章带你使用Typescript封装一个Vue组件
一.搭建项目以及初始化配置 vue create ts_vue_btn 这里使用了vue CLI3自定义选择的服务,我选择了ts.stylus等工具.然后创建完项目之后,进入项目.使用快捷命令code ...
- 一篇文章带你了解轻量级Web服务器——Nginx简单入门
一篇文章带你了解轻量级Web服务器--Nginx简单入门 Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件代理服务器 在本篇中我们会简单介绍Nginx的特点,安装,相关指令使用以及配置信 ...
- 一篇文章带你掌握主流基础框架——Spring
一篇文章带你掌握主流基础框架--Spring 这篇文章中我们将会介绍Spring的框架以及本体内容,包括核心容器,注解开发,AOP以及事务等内容 那么简单说明一下Spring的必要性: Spring技 ...
- 一篇文章带你掌握主流服务层框架——SpringMVC
一篇文章带你掌握主流服务层框架--SpringMVC 在之前的文章中我们已经学习了Spring的基本内容,SpringMVC隶属于Spring的一部分内容 但由于SpringMVC完全针对于服务层使用 ...
- 一篇文章带你掌握主流办公框架——SpringBoot
一篇文章带你掌握主流办公框架--SpringBoot 在之前的文章中我们已经学习了SSM的全部内容以及相关整合 SSM是Spring的产品,主要用来简化开发,但我们现在所介绍的这款框架--Spring ...
- MYSQL(基本篇)——一篇文章带你走进MYSQL的奇妙世界
MYSQL(基本篇)--一篇文章带你走进MYSQL的奇妙世界 MYSQL算是我们程序员必不可少的一份求职工具了 无论在什么岗位,我们都可以看到应聘要求上所书写的"精通MYSQL等数据库及优化 ...
- MYSQL(进阶篇)——一篇文章带你深入掌握MYSQL
MYSQL(进阶篇)--一篇文章带你深入掌握MYSQL 我们在上篇文章中已经学习了MYSQL的基本语法和概念 在这篇文章中我们将讲解底层结构和一些新的语法帮助你更好的运用MYSQL 温馨提醒:该文章大 ...
- 一篇文章带你掌握主流数据库框架——MyBatis
一篇文章带你掌握主流数据库框架--MyBatis MyBatis 是一款优秀的持久层框架,它支持自定义 SQL.存储过程以及高级映射. 在之前的文章中我们学习了MYSQL和JDBC,但是这些东西远远不 ...
- 一篇文章带你掌握MyBatis简化框架——MyBatisPlus
一篇文章带你掌握MyBatis简化框架--MyBatisPlus 我们在前面的文章中已经学习了目前开发所需的主流框架 类似于我们所学习的SpringBoot框架用于简化Spring开发,我们的国人大大 ...
- 一篇文章带你了解网页框架——Vue简单入门
一篇文章带你了解网页框架--Vue简单入门 这篇文章将会介绍我们前端入门级别的框架--Vue的简单使用 如果你以后想从事后端程序员,又想要稍微了解前端框架知识,那么这篇文章或许可以给你带来帮助 温馨提 ...
随机推荐
- JAVA设计模式及其设计原则
设计模式: 设计模式是一套被反复使用的.多数人知晓的.经过分类编目的.代码设计经验的总结. 单例模式:在一个jvm虚拟机,要创建的对象控制成独一份:举例:统计单台虚拟机内的用户在线数 package ...
- gulp技术:自动化构建工具
作用:压缩css.js.img,合并文件,改名字,编译sass,拷贝 使用步骤: 1.安装node环境,下一步,下一步,安装C盘: 2.在你的根目录下,在地址栏输入cmd回车: 3.检测node和np ...
- 2003031126-石升福-python数据分析第三周作业
项目 Numpy 博客名称 2003031126-石升福-python数据分析第三周作业 课程班级博客链接 https://edu.cnblogs.com/campus/pexy/20sj 作业链接 ...
- PS将多个图片合并成长图
1.将所有图片拖到ps里面排好序.这里图层需要倒序,合成长图上面的图片要在图层的下面.图层倒序的方法:图层→排列→反向. 2.设置画布大小.假设18张图片,每个图片的高度是1448像素,则设置画布的高 ...
- 关于Centos7Th 初始化的一些概述
- 概述 Q:为什么要初始化,什么是初始化? A:一般初始化是根据的后期要部署的业务环境来定制的,新装的系统其自带的软件不够支撑各种开发环境或者运维工作:需要部署和设置对应的安全环境.开发/运维软件. ...
- ABP vNext微服务架构详细教程——项目部署
1. 基础配置 在之前的文章中,我们已经配置了Kubernetes集群并安装了管理工具Kubesphere,文章地址为:https://mp.weixin.qq.com/s/MgpdMv5A-fYxN ...
- curl: (35) SSL connect error的错误
1.先升级nss (Network Security Service, 网络安全服务) yum update nss如果没有nss,则需要安装nss服务 yum install nss 2.更新/安装 ...
- xlwings读取一整个excel文件xlsx的第一sheet到pandas.DataFrame的方法
为什么不用:pd.read_excel ? 因为 pd 使用 openpyxl 读取excel文件,有时候xlsx文件是由ApachIO产生的读取进去会出错,换个方式,用xlwings(基于pywin ...
- 初始化时使window 全屏 且显示任务栏 wpf
void IniWindowFullScreemAndDisplayTaskbar() { this.Width = SystemParameters.FullPrimaryScreenWidth; ...
- Java方法-什么是方法
Java方法-什么是方法 package com.andy.base.Andy.operator.method; public class Demo01 { //main方法 public stati ...