Go 语言入门很简单:net/http 包

简介: Go 语言提供功能丰富的 net/http,实现了基础的 HTTP 中的 client 和 server 功能。在这一篇文章也有介绍一个基础的 HelloWorld 应用。

引言

Go 语言提供功能丰富的 net/http,实现了基础的 HTTP 中的 clientserver 功能。在这一篇文章也有介绍一个基础的 HelloWorld 应用。


如果没看过,也可以使用下面的代码创建一个简易 HTTP 的 server 服务:

package main
import (
  "log"
  "net/http"
)
type Handler struct{}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  _, err := w.Write([]byte("Welcome to my Website!"))
  if err != nil {
    log.Println(err)
  }
}
func main() {
  log.Println(http.ListenAndServe("127.0.0.1:8080", &Handler{}))
}


http.ListenAndServe 的第一个参数是传入监听的地址,第二个参数是 http.Handle 接口实现者。该接口需要 ServeHTTP(w http.ResponseWriter, r *http.Request) 函数。这个函数将处理我们服务器上的所有请求。


第一个终端上使用 go run main.go 运行该服务器:

$ go run main.go 


然后打开另个一终端:

$ curl localhost:8080/
Welcome to my Website!
$ curl localhost:8080/hello
Welcome to my Website!


我们还可以配置服务器来处理特定的 URL,例如 /hello

package main
import (
  "log"
  "net/http"
)
type Handler struct{}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  _, err := w.Write([]byte("Welcome to my Website!"))
  if err != nil {
    log.Println(err)
  }
}
func main() {
  http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
    _, err := w.Write([]byte("Hello, world!"))
    if err != nil {
      log.Println(err)
    }
  })
  log.Println(http.ListenAndServe("127.0.0.1:8080", nil))
}


运行另一个终端,能看到如下结果::

$ curl localhost:8080/hello
Hello, world!
$ curl localhost:8080/
404 page not found


它是如何工作的?当我们调用 http.HandleFunc 时,路径和处理函数被添加到 net/http.DefaultServeMux 结构中,即包含所有这些。当我们调用特定的 URL 时,net/http.DefaultServeMux 用于查找特定的处理程序。如果未找到处理程序,将生成标准 404 响应。


标准路由对每个注册的 URL 实现唯一的纯 URL 比较。模式匹配,例如匹配 /hello/{page} 之类的表达式,其中页面参数在多个调用之间可能不同,这对于标准路由器是不可能的。要实现这一点,我们需要自己实现模式匹配或使用路由器库之一。

自定义路由

我们可以使用任何其他路由器,例如 gorilla/mux :一个强大的 HTTP 路由器和 URL 匹配器,用于构建 Go web 服务器 🦍。目前已经在 Github 收获 16.4 k 的 star,它支持模式匹配。

func main() {
  r := mux.NewRouter()
  r.HandleFunc("/products/{key}", ProductHandler)
  r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler)
  r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler)
  http.Handle("/", r)
}


接下来,在处理程序中,我们可以从 URL 中获取变量:

中间件

在标准 Web 服务中,不仅有处理程序的代码在每个请求上运行。还有一些通用代码执行一些通用工作——日志记录、统计信息抓取、授权检查等。这些通用代码称为中间件。


所谓中间件,就是连接上下级不同功能的函数或者软件,通常进行一些包裹函数的行为,为被包裹函数提供添加一些功能或行为。前文的 HandleFunc 就能把签名为 func(w http.ResponseWriter, r *http.Reqeust) 的函数包裹成 handler 。这个函数也算是中间件。


GO 标准库中没有明确的中间件实现。但是任何人都可以通过使用嵌套处理程序来实现类似的东西。让我们看一下日志中间件,它将每个请求的 URL 打印到控制台:

package main
import (
  "log"
  "net/http"
)
type LoggingMiddleware struct {
  handler http.Handler
}
func NewLoggingMiddleware(handler http.Handler) *LoggingMiddleware {
  return &LoggingMiddleware{
    handler: handler,
  }
}
func (l *LoggingMiddleware) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  log.Println(req.URL, "requested")
  l.handler.ServeHTTP(w, req)
}
type Handler struct{}
func (h *Handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  _, err := w.Write([]byte("hello"))
  if err != nil {
    log.Println(err)
  }
}
func main() {
  log.Println(http.ListenAndServe(":9090", NewLoggingMiddleware(&Handler{})))
}
$ curl localhost:8080/
hello
$ curl localhost:8080/hello
hello


在对我们服务器的每个请求中,我们现在可以在控制台中看到以下数据:

$ go run main.go
2022/04/27 23:44:18 / requested
2022/04/27 23:44:23 /hello requested


很多游戏的 Go Web 库如 echogin 可以显着地帮助实现中间件。此外,许多库已经涵盖了最流行的中间件任务。

HTTP 客户端

net/http 包中有一个 Client 结构,它负责 HTTP 客户端请求:


package main
import (  "fmt"  "io/ioutil"  "log"  "net/http")
func main() {
  client := http.Client{}
  resp, err := client.Get("https://bing.com/")  if err != nil {    log.Fatal(err)  }
  buf, err := ioutil.ReadAll(resp.Body)  resp.Body.Close()  if err != nil {    log.Fatal(err)  }
  fmt.Println(string(buf))}

复制代

package main
import (
  "fmt"
  "io/ioutil"
  "log"
  "net/http"
)
func main() {
  client := http.Client{}
  resp, err := client.Get("https://bing.com/")
  if err != nil {
    log.Fatal(err)
  }
  buf, err := ioutil.ReadAll(resp.Body)
  resp.Body.Close()
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(string(buf))
}


运行结果会返回该网页的内容:


网络异常,图片无法展示
|

总结

Go 语言 net/http 涵盖了 HTTP 客户端和服务器实现。支持客户端 Get、Head、Post 和 PostForm 发出 HTTP(或 HTTPS)请求,正因为这些强大的基础功能,所以 Go Web 编程也能够占据一席之地,更多 HTTP 的知识可以跟着官方文档学。最近也发现了一个简易 HTTP 和 REST 客户端的 resty 项目,目前 star 6k,打算学习一波。下一篇文章见~

相关文章
|
2月前
|
前端开发 JavaScript 安全
入门Vue+.NET 8 Web Api记录(一)
入门Vue+.NET 8 Web Api记录(一)
93 4
|
2天前
|
Java 网络架构 Kotlin
kotlin+springboot入门级别教程,教你如何用kotlin和springboot搭建http
本文是一个入门级教程,介绍了如何使用Kotlin和Spring Boot搭建HTTP服务,并强调了Kotlin的空安全性特性。
18 7
kotlin+springboot入门级别教程,教你如何用kotlin和springboot搭建http
|
1月前
|
SQL 关系型数据库 数据库
七天.NET 8操作SQLite入门到实战详细教程(选型、开发、发布、部署)
七天.NET 8操作SQLite入门到实战详细教程(选型、开发、发布、部署)
|
1月前
|
开发框架 .NET Java
C#/.NET/.NET Core自学入门指南
C#/.NET/.NET Core自学入门指南
|
2月前
|
开发框架 前端开发 .NET
七天.NET 8操作SQLite入门到实战 - (3)第七天Blazor学生管理页面编写和接口对接
七天.NET 8操作SQLite入门到实战 - (3)第七天Blazor学生管理页面编写和接口对接
|
2月前
|
JavaScript 前端开发 Java
【Azure 环境】各种语言版本或命令,发送HTTP/HTTPS的请求合集
【Azure 环境】各种语言版本或命令,发送HTTP/HTTPS的请求合集
|
3月前
|
缓存 程序员 开发者
HTTP状态码大全:如何读懂服务器的语言?
大家好,我是小米,今天我们来聊聊HTTP协议中的GET和POST请求。它们在数据传输方式、安全性和应用场景上有不同特点。本文将详细解析它们的区别和特点,帮助你更好地理解和运用这两种请求方式。让我们一起学习吧!
46 1
|
3月前
|
Go
Go中 net/http 使用
Go中 net/http 使用
19 0
|
4月前
|
Linux Windows
Jmeter设置中文语言和配置https
Jmeter设置中文语言和配置https
106 0
Jmeter设置中文语言和配置https
|
4月前
|
存储 IDE C#
C#入门:在JetBrains Rider中创建.Net Framework控制台应用程序,输出“Hello, World!”
C#入门:在JetBrains Rider中创建.Net Framework控制台应用程序,输出“Hello, World!”
436 0

热门文章

最新文章