Go HTTP 编程 | 01 - 使用 http 包创建 Web 服务器

简介: Go HTTP 编程 | 01 - 使用 http 包创建 Web 服务器

一、Go 的 HTTP 标准库 net/http

Go 已经拥有成熟的 HTTP 标准库 net/http,即使不使用 Go 的 Web 框架如 Gin、Iris 等也可以快速的搭建起一个可以运行的 Web 服务,同时这个标准库可以对 Web 路由、静态文件、模板和cookie 等数据进行处理,事实上这些 Web 框架也都是基于 net/http 标准库来构建的。

使用 net/http 建立 Web 服务器

首先创建一个请求处理函数 sayHelloHandler,该函数接收一个 http.ResponseWriter 和 一个请求指针 *http.Request 作为参数,通过对请求中数据的提取之后写入指定的信息到 http.ResponseWriter 中。

在 main 函数中通过 http.HandleFunc 定义一个路由并将该路由与 sayHelloHandler 函数映射,然后通过 http.ListenAndServe 监听端口。

运行 main.go 文件,一个简单的 Web 服务器就运行起来了。

package main
// filename main.go
//noinspection ALL
import (
   "fmt"
   "log"
   "net/http"
   "strings"
)
//noinspection ALL
func main(){
   http.HandleFunc("/", sayHelloName)
   err := http.ListenAndServe(":9000", nil)
   if err != nil {
      log.Fatal("ListenAndServer: ", err)
   }
}
func sayHelloHandler(w http.ResponseWriter, r *http.Request){
   r.ParseForm() // 解析参数,默认是不会解析的
   fmt.Println(r.Form) // 输出
   fmt.Println("path", r.URL.Path)
   fmt.Print("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.Fprint(w, "Hello, Go HTTP")
}
复制代码

在浏览器中输入 http://localhost:9000/

image.png

控制台打印出的详细信息

image.png

net/http 运行机制

net/http 运行流程:

  1. 创建 Listen Socket 监听指定端口,等待客户端请求
  2. Listen Socket 接收客户端请求,得到 Client Socket,服务端通过 Clent Socket 与客户端进行通信
  3. 处理客户端请求,首先从 Client Socket 读取 HTTP 请求的信息,包括请求头和请求体,然后交给相应的 handler 函数处理,handler 处理完成后将数据通过 Client Socket 写给客户端。

image.png

整个过程我们需要了解三个问题:

  • net/http 是如何监听端口的?
  • net/http 是如何接收客户端请求的?
  • net/http 是如何分配 handler 的?

查看源码,点击 main.go 文件中 http.ListenAndServe(":9000", nil)ListenAndServe 函数,来到源码,再次点击 3222 行的 ListenAndServe

image.png

再次点击 2968 行的 Serve 函数:

image.png

image.png

Serve(l net.Listener) 函数就是处理接收客户端的请求信息。该函数中的 for 循环首先通过 net.Listener 接收请求 rw, err := l.Accept()for 循环之后又创建了一个 Conn,最后单独开了一个 goroutine go c.serve(connCtx);用户的每一次请求都是在一个单独的 goroutine 中执行的,不会相互影响。

点击 go c.serve(connCtx) 中的 serve(connCtx) 方法,在该方法中的第 1891 行通过 c.readRequest(ctx) 来解析请求:

image.png

然后在第 1966 行,根据请求解析结果通过 serverHandler{c.server}.ServeHTTP(w, w.req) 分配了一个 handler

image.png

点击查看 ServeHTTP 源码:

image.png

这里获取了一个 handler,调用 ListenAndServe 函数的时候传递的参数为 nil,因此这里默认分配了一个 DefaultServeMux 作为 handler。其实 DefaultServeMux 就是一个路由器,它用来匹配 URL 跳转到其响应的 handler 函数。

上述代码中 http.HandleFunc("/", sayHelloName) 就已经定义了路由规则,当请求为 / 时,路由就会转到 sayHelloName 方法,DefaultServeMux 就会调用 ServeHTTP 方法,则这个方法内部其实就是调用 sayHelloName 方法,然后将返回结果写入到 response 中,最后返回给客户端。

整个处理流程如下:

image.png


相关文章
|
1天前
|
PHP Android开发
android通过http上传文件,服务器端用php写(原创)
android通过http上传文件,服务器端用php写(原创)
|
1天前
|
Java 关系型数据库 MySQL
保姆级教程——将springboot项目部署到阿里云服务器包含环境配置(小白包会)
本文档详细介绍了将SpringBoot项目部署到阿里云服务器的步骤。首先,通过Xshell连接服务器,使用公网IP地址。接着,下载JDK的Linux版本,使用XFTP上传并解压,配置环境变量。然后,安装MySQL 5.7,包括下载YUM源、安装、启动服务以及修改root密码和开启远程访问。最后,将SpringBoot项目打包成jar,上传至服务器,使用`java -jar`命令运行,通过`nohup`确保服务持续运行。配置安全组以允许远程访问。
|
9天前
|
Java
如何解决使用若依前后端分离打包部署到服务器上后主包无法找到从包中的文件的问题?如何在 Java 代码中访问 jar 包中的资源文件?
如何解决使用若依前后端分离打包部署到服务器上后主包无法找到从包中的文件的问题?如何在 Java 代码中访问 jar 包中的资源文件?
43 0
|
10天前
|
安全 测试技术 Go
Golang深入浅出之-Go语言单元测试与基准测试:testing包详解
【4月更文挑战第27天】Go语言的`testing`包是单元测试和基准测试的核心,简化了测试流程并鼓励编写高质量测试代码。本文介绍了测试文件命名规范、常用断言方法,以及如何进行基准测试。同时,讨论了测试中常见的问题,如状态干扰、并发同步、依赖外部服务和测试覆盖率低,并提出了相应的避免策略,包括使用`t.Cleanup`、`t.Parallel()`、模拟对象和检查覆盖率。良好的测试实践能提升代码质量和项目稳定性。
16 1
|
10天前
|
安全 Go
Golang深入浅出之-Go语言标准库中的文件读写:io/ioutil包
【4月更文挑战第27天】Go语言的`io/ioutil`包提供简单文件读写,适合小文件操作。本文聚焦`ReadFile`和`WriteFile`函数,讨论错误处理、文件权限、大文件处理和编码问题。避免错误的关键在于检查错误、设置合适权限、采用流式读写及处理编码。遵循这些最佳实践能提升代码稳定性。
20 0
|
10天前
|
中间件 Go
【Go语言专栏】使用Go语言编写HTTP服务器
【4月更文挑战第30天】本文介绍了如何使用Go语言创建基本的HTTP服务器,包括设置路由、处理请求和响应。首先确保安装了Go环境,然后引入`net/http`包,定义路由和处理器函数。处理器函数接收`http.ResponseWriter`和`*http.Request`参数,用于发送响应和处理请求。使用`http.ListenAndServe`启动服务器,并可通过中间件增强功能。文章还提及了处理复杂请求、查询参数和POST数据的方法,以及使用第三方库如Gin和Echo扩展功能。通过本文,读者可掌握Go语言编写HTTP服务器的基础知识。
|
10天前
|
缓存 编译器 Go
【Go语言专栏】理解Go语言的包管理机制
【4月更文挑战第30天】Go语言包管理是构建可维护应用的关键,从基本概念如包导入、初始化到版本管理和依赖管理,再到Go Modules的引入,简化了过程。包的可见性规则和社区生态也至关重要。理解并掌握这些机制对于编写高质量Go代码具有决定性影响。随着Go语言的持续发展,包管理将更加强大易用。
|
11天前
|
安全 Unix Go
Golang深入浅出之-Go语言中的时间与日期处理:time包详解
【4月更文挑战第26天】Go语言的`time`包提供处理日期和时间的功能,包括`time.Time`类型、时间戳、格式化与解析。本文讨论了核心概念、常见问题(如时区处理、格式字符串混淆、超时控制和并发安全)及解决方法。推荐使用`time.LoadLocation`管理时区,熟悉时间格式规则,用`context`精确控制超时,并注意并发安全。文中通过代码示例展示了如何获取格式化时间、计算时间差以及创建定时任务。学习和应用这些知识可提高程序的健壮性和准确性。
27 2
|
11天前
|
XML JSON Go
Golang深入浅出之-XML处理在Go语言中的实现:encoding/xml包
【4月更文挑战第26天】Go语言的`encoding/xml`库提供XML处理,包括序列化和反序列化。本文讨论了XML处理的基础,如`xml.Marshal`和`xml.Unmarshal`函数,以及常见问题和易错点,如标签命名、结构体嵌套、omitempty标签和命名空间。建议遵循标签命名规则,正确处理嵌套和属性,谨慎使用omitempty,以及理解并有效利用命名空间。文中还给出了基础示例和处理XML属性的代码示例,帮助读者掌握XML处理技巧。
22 1
Golang深入浅出之-XML处理在Go语言中的实现:encoding/xml包
|
11天前
|
弹性计算 监控 Shell
监控HTTP 服务器的状态
【4月更文挑战第29天】
10 0