讨论网络概念、HTTP通信和进程管理。
full lessons here👇:
https://programmerscareer.com/zh-cn/golang-basic-skill/
由AI生成,可能有错误,仅供参考
Topic:0.1基本网络理解
从基础开始学习通常会使学习过程更加有效率。即使你已经熟悉相关主题,快速复习也可以帮助巩固你的理解。
计算机网络由多个电脑组成,这些电脑彼此连接,以共享资源和数据为目的。
常见的计算机网络类型包括:
- 局域网(LAN):一个小范围内的网络。通常限于一个单独的建筑物,例如家、办公室或一组建筑物。
- 广域网(WAN):跨越大物理距离的一种网络。互联网是一个 WAN。
基本网络协议理解也非常重要。协议是一组规则,它 dictate 数据如何在网络上传输。
Internet Protocol(IP)、Transmission Control Protocol(TCP)和 User Datagram Protocol(UDP)是你必须了解的基本协议。
在 Go 中,‘net’ 包提供了一般网络 I/O 接口,包括 TCP/IP、UDP、域名解析和 Unix 域套接字。
这些网络概念将成为我们深入探讨 Go 处理 HTTP 通信和管理进程时的基础。
Topic:0.2 Go 的 net 包介绍
Go 的标准库提供了 HTTP 的优秀支持。‘net/http’ 包提供了构建 HTTP 客户端和服务器的功能。但是在 dive 到 HTTP 之前,我们需要了解 ‘net’ 包。
‘net’ 包在 Go 中提供了一般网络 I/O 接口,包括 TCP/IP、UDP、域名解析和 Unix 域套接字。
让我们快速浏览一下 ‘net’ 包中的一些函数,这些函数我们将使用:
- Dial: Dial 函数连接到指定网络上的地址。
1 | conn, err := net.Dial("tcp", "golang.org:80") |
- Listen: Listen 声明在本地网络上。您将使用这个来创建一个服务器,监听 incoming 连接。
1 | ln, err := net.Listen("tcp", ":8080") |
- Accept: 并且这是如何等待和返回下一个连接到监听器的。
1 | conn, err := ln.Accept() |
不要担心如果第一次看起来很混乱。在下一节中,我们将深入探讨这些函数,并在代码和示例中实际使用它们。
Topic:0.3 HTTP 介绍
HTTP 是 Hypertext Transfer Protocol 的缩写,这是 Web 上数据交换的基础。HTTP 是全球范围内用于传输超文本的协议。
HTTP 的关键特点包括:
- 无状态性: HTTP 无状态,意味着每个客户端请求都是独立的。服务器和客户端不保留数据之间的数据。
- 媒体独立性: 只要客户端可以解释数据,就可以发送任何类型的媒体文件。
HTTP 作为客户端和服务器之间的一个请求-响应协议,包括浏览器、移动应用程序和其他服务器是 HTTP 客户端的一些例子。每当一个 HTTP 请求被客户端提出时,服务器将以 HTTP 响应回应。
在 Go 中,创建一个 HTTP 服务器变得轻松,因为标准 ‘net/http’ 包提供了 ListenAndServe 函数。
我们也可以使用 ‘http.Client’、‘http.NewRequest’ 和 ‘http.Do’ 命令来发送 HTTP 请求。
Go 提供了一种非常强大的 http 包,它提供了所有必要的工具来运行 HTTP 服务器或发送客户端 HTTP 请求。我们将在下一节中探讨 Go 的 ‘http’ 包,并实际使用代码和示例。
1.1 HTTP Client
Go 的 net/http
包提供了发送 HTTP 请求的方法。在本节中,我们将介绍发送 GET 请求的基本知识,这是 HTTP 请求的一种常见类型。
以下是一个基本示例,演示如何发送 GET 请求:
1 | package main |
在这个示例中,我们使用 http.Get
函数向提供的 URL 发送 GET 请求,并返回响应和错误。
resp.Body
中包含服务器对请求的响应。ioutil.ReadAll
函数从响应体中读取所有数据。然后,我们将响应体打印到控制台。
defer resp.Body.Close()
行是关键的一部分。这确保了网络连接在函数完成后关闭,而不是立即关闭。这是一种良好的实践,因为重复使用连接池可以提高性能。
我希望您对我们的 HTTP 客户端课程的开始感到有帮助。请记住,实践是有益处的,因此请尝试编写一个 GET 请求以熟悉过程。
1.2 HTTP 服务器
在 Go 中,我们可以使用 net/http
包构建一个强大的 web 服务器。我们可以创建 RESTful 服务、静态文件服务、动态路由等。为了这个课程的 sake,让我们专注于创建一个简单的 web 服务器。
以下是一个基本示例,演示如何创建一个简单的 web 服务器:
1 | package main |
在这个示例中,我们使用 http.HandleFunc
函数将请求路由到处理函数中,然后使用 http.ListenAndServe
函数监听指定端口直到程序被终止。
实际上,服务器通常不用于发送“Hello, World”消息,而是用于发送动态内容,这些内容根据特定的情况或参数而变化。
为了illustrate 这,我们将查看一个简单的示例,演示如何处理 HTTP POST 请求。
1 | // Global variable to simulate a database. |
代码创建一个表单,询问名称。当您提交表单时,它将向 /submit
发送 POST 请求。这请求处理程序从 POST 数据中检索名称并存储。
1.3 Go 中的 Context 包
Go 中的 Context 包通常用于处理可能需要取消或超时的任务。并发编程在 Go 中的一个常见主题是管理长期和短期的 worker 任务。在一些场景中,例如处理数据流或自动化任务,这些任务可能会持续很久甚至 indefinitely。
Context 包提供了一种标准化的接口来定义父-子关系之间的关系,并传播截止日期、取消信号和其他信息,以便有效地处理任务。
让我们看看如何使用 Context:
1 | package main |
在这个示例中,我们初始化了一个新的背景上下文 ctx
,然后创建了一个自动取消的上下文使用 context.WithTimeout(ctx, 3*time.Second)
。cancel 函数由 context.WithTimeout
返回,并使用 defer
来确保资源被正确地清理。
1.4 Go 中的进程
在计算世界中,一进程是一个正在执行的计算机程序实例。它包含了程序代码和当前活动。在 Go 中,可以使用 os/exec
包来启动一个进程。
以下是一个简单示例:
1 | package main |
在这个示例中:
exec.Command("ls")
准备了一条命令来执行。这就像在终端中输入ls
命令,但是它还没有真正地运行。cmd.Output()
实际上运行了命令,并等待它完成。它返回标准输出和一个 Go 的内置接口类型error
。
这个程序将打印当前目录的内容,类似于 Unix-based 系统中的 ls
命令。
Go 提供了一组强大的工具来管理进程。在简单的术语中,进程管理在任何语言中都涉及到跟踪和控制我们启动的进程。这就是关于知道程序的状态。
Topic 1.5: Go 中的信号
在操作系统中,信号是一种软件中断,它将被送到进程。进程可以使用这些信号来触发某些行为。例如,当程序在终端窗口中运行时,按下 ctrl+c 将发送一个中断信号,通常会导致程序终止。
在 Go 中,我们可以使用 os/signal
包来决定当我们的程序接收到信号时该做什么。这可以允许我们优雅地停止一个程序,并执行任何可能需要的清理操作。
示例
1 | package main |
在这个程序中
- 我们首先创建一个信号通道。
- 使用
signal.Notify
将 incoming signals relay 到通道中。我们特别关心SIGINT
(由按下 ctrl+c 发送)和SIGTERM
(对程序的终止请求)。 - 当接收到信号时,它将被打印出来,然后“true”将被发送到 done 通道,以表示我们准备退出。
这样,我们可以优雅地处理中断,通过保存进度、释放资源、完成重要操作或询问用户确认前退出。
Topic 1.6: Go 中的干净退出
在任何结构良好的程序中总是需要释放程序消耗的资源,这些资源可能包括打开的文件、数据库连接、网络连接或分配的内存。Go 提供了 defer
语句,帮助我们自动管理这些资源。
defer 语句的关键思想
defer
语句允许我们延迟执行一个函数直到包含它的函数返回,无论如何返回。
考虑以下常见情况
我们打开一个文件,执行一些操作,然后关闭它:
1 | func main() { |
现在,让我们假设在文件操作中出现错误,我们从函数返回。这样,Close 函数将永远不会被调用,从而导致文件描述符泄露。这是 defer
可以发挥作用的地方:
1 | func main() { |
在修订版本中
f.Close()
将在每次函数返回时执行,无论如何返回。这确保我们不会留下任何资源悬挂。
1.7 Review and Practice
让我们快速回顾一下:
- HTTP Client:我们学习了使用 Go 的标准库
net/http
发送 HTTP 请求,并了解如何获取和发送数据。 - HTTP Server:我们探索了设计 HTTP 服务器并处理 incoming 请求的方法。
- Context in Go:我们了解了使用 context 包来管理长时间运行的进程。
- Processes in Go:我们学习了在 Go 中创建和管理进程的方法。
- Signals in Go:我们探索了如何处理系统信号以实现应用程序的优雅关闭。
- Clean Exit in Go:我们学习了资源清理在应用程序终止前,并且您了解了
defer
关键字。
现在,让我们将这些知识付诸实践,完成以下练习:
- 在 Go 中创建一个监听 8080 端口的 HTTP 服务器,并响应
/ping
路由返回Pong!
。 - 在 Go 中创建一个发送 GET 请求到 API 端口的 HTTP 客户端。
- 编写一个无限循环的 Go 函数,但在接收到关闭信号 (
SIGINT
或SIGTERM
)时优雅地退出。 - 开发一个简单的 Go 脚本,打开文件、写入内容,并确保文件即使在写入操作中出现错误也能被正确关闭。
如果您在解决这些练习或需要澄清我们所学的知识,请不要犹豫地问。
1.8 Assessments
了解自己的情况是改进的关键。为此,我们准备了一组独特的问题让您回答。一些可能会很难,但我们确信您可以处理它们。
问题:
- 请编写一个 REST API 在 Go 中。这 API 包括一个获取用户数据的 GET 端口。描述如何设计这个端口。
- 如何在 Go 中处理长时间运行的 HTTP 请求超时?
- 假设您的 Go 应用程序中有一个需要在某些条件下停止的长时间 Goroutine。如何设计代码以优雅地停止该 Goroutine?
- 如果您的 Go 应用程序接收到
SIGKILL
信号,可以您处理这种信号吗? - 您的 Go 应用程序打开了一个文件。但是由于某些意外错误,应用程序 panic 了。如何确保在应用程序退出前文件被正确关闭?
请您认真思考每个问题,并提供深思熟虑的答案。记住,这不是速度的问题,而是概念理解和详细性的问题!
English post: https://programmerscareer.com/1go-basic-15/
作者:Wesley Wei – Twitter Wesley Wei – Medium
注意:本文为作者原创,转载请注明出处。
评论