如何在Go中制作HTTP服务器
引言
许多开发人员至少会花一些时间创建服务器,以便在互联网上分发内容。HTTP (Hypertext Transfer Protocol,超文本传输协议)提供了大部分这些内容,无论是请求一张猫的图片还是请求加载你正在阅读的教程。Go标准库为创建HTTP服务器以提供web内容或向这些服务器发出HTTP请求提供内置支持。
在本教程中,您将使用Go的标准库创建一个HTTP服务器,然后扩展服务器以从请求的查询字符串、请求体和表单数据中读取数据。你还需要更新程序,用自己的HTTP头和状态码响应请求。
设置项目
在Go中,标准库中的net/http
包提供了大多数HTTP功能,而其余的网络通信由net
包提供。net/http
包不仅包含发出HTTP请求的能力,还提供了一个HTTP服务器,您可以使用它来处理这些请求。
在本节中,您将创建一个程序,它使用’ HTTP . listenandserve '函数来启动一个HTTP服务器,以响应请求路径/
和/hello
。然后,扩展该程序,在同一个程序中运行多个HTTP服务器。
不过,在编写代码之前,需要先创建程序的目录。许多开发人员将他们的项目放在一个目录中,以保持项目的组织。在本教程中,你将使用一个名为projects
的目录。
首先,创建projects
目录并导航到它:
mkdir projects
cd projects
接下来,创建项目目录并导航到该目录。在这种情况下,使用httpserver
目录:
mkdir httpserver
cd httpserver
现在你已经创建了你的程序目录,并且你在httpserver
目录下,你可以开始实现你的HTTP服务器了。
监听请求并提供响应
一个Go HTTP服务器包括两个主要组件:侦听来自HTTP客户端的请求的服务器和一个或多个将响应这些请求的请求处理程序。在本节中,你将从使用http.HandleFunc
函数来告诉服务器调用哪个函数来处理对服务器的请求开始。然后,你将使用http.ListenAndServe
函数来启动服务器,并告诉它监听新的HTTP请求,然后使用你设置的处理程序函数来处理它们。
现在,在你创建的httpserver
目录中,使用nano
或者你最喜欢的编辑器,打开main.go
文件:
nano main.go
在main.go
文件中,你将创建两个函数,getRoot
和getHello
,作为你的处理函数。然后,你将创建一个main
函数,并使用http.HandleFunc
函数来设置你的请求处理程序,方法是将/
路径传递给getRoot
函数,将/hello
路径传递给getHello
函数。一旦你设置了你的处理程序,调用http.ListenAndServe
函数来启动服务器并监听请求。
将以下代码添加到该文件中,启动程序并设置处理程序:
main.go
package mainimport ("errors""fmt""io""net/http""os"
)func getRoot(w http.ResponseWriter, r *http.Request) {fmt.Printf("got / request\n")io.WriteString(w, "This is my website!\n")
}
func getHello(w http.ResponseWriter, r *http.Request) {fmt.Printf("got /hello request\n")io.WriteString(w, "Hello, HTTP!\n")
}
在这第一段代码中,你为Go程序设置了package
, import
程序所需的包,并创建了两个函数:getRoot
函数和getHello
函数。这两个函数都有相同的函数签名,它们接受相同的参数:http.ResponseWriter
值和*http.Request
值。这个函数签名用于HTTP处理程序函数,定义为’ http.HandlerFunc '。当向服务器发出请求时,它使用正在发出的请求的信息设置这两个值,然后使用这些值调用处理程序函数。
在http.HandlerFunc
中,http.ResponseWriter
值(在您的处理程序中名为w
)用于控制将响应信息写回发出请求的客户端,例如响应体或状态码。然后,*http.Request
值(在处理程序中名为r
)用于获取进入服务器的请求的信息,例如在POST
请求情况下发送的请求体或有关发出请求的客户端的信息。
现在,在你的两个HTTP处理程序中,你使用fmt.Printf
来打印处理程序函数的请求,然后使用http.ResponseWriter
向响应体发送一些文本。http.ResponseWriter
是一个io.Writer
,这意味着你可以使用任何能够写入该接口的东西来写入响应主体。在本例中,你使用io.WriteString
函数将响应写入body。
现在,通过启动main
函数来继续创建程序:
main.go
...
func main() {http.HandleFunc("/", getRoot)http.HandleFunc("/hello", getHello)err := http.ListenAndServe(":3333", nil)
...
在main
函数中,你有两次对http.HandleFunc
函数的调用。对该函数的每次调用都会为默认的服务器多路复用器中的特定请求路径设置一个处理程序函数。服务器多路复用器是一个http.Handler
,它能够查看请求路径并调用与该路径相关联的给定处理程序函数。所以,在你的程序中,你告诉默认的服务器多路复用器,当有人请求/
路径时调用getRoot
函数,当有人请求/hello
路径时调用getHello
函数。
一旦处理程序设置好了,你就可以调用http.ListenAndServe
函数,它会告诉全局HTTP服务器使用可选的http.Handler
在特定端口上监听传入的请求。在你的程序中,你告诉服务器监听":3333"
。通过冒号前不指定IP地址,服务器将监听与计算机关联的每个IP地址,并且监听端口为3333
。[网络端口](https://en.wikipedia.org/wiki/Port_(computer_networking),如这里的’ 3333 ',是一台计算机同时有许多程序相互通信的一种方式。每个程序都使用自己的端口,因此当客户端连接到特定的端口时,计算机就知道要把它发送到哪个程序。如果你只想允许连接到localhost
,即IP地址为127.0.0.1
的主机名,你可以改为127.0.0.1:3333
。
你的http.ListenAndServe
函数也为http.Handler
参数传递了一个nil
值。这告诉ListenAndServe
函数,你想使用默认的服务器多路复用器,而不是你设置的那个。
ListenAndServe
是一个阻塞调用,这意味着你的程序在ListenAndServe
结束运行之前不会继续运行。然而,ListenAndServe
在你的程序结束运行或者HTTP服务器被告知关闭之前不会结束运行。即使ListenAndServe
阻塞了,而且你的程序没有包含关闭服务器的方法,但包含错误处理仍然很重要,因为调用ListenAndServe
可能会失败。因此,将错误处理添加到main
函数的ListenAndServe
中,如下所示:
main.go
...func main() {...err := http.ListenAndServe(":3333", nil)if errors.Is(err, http.ErrServerClosed) {fmt.Printf("server closed\n")} else if err != nil {fmt.Printf("error starting server: %s\n", err)os.Exit(1)<^>}
}
你要检查的第一个错误是’ http.ErrServerClosed ',它会在服务器被告知关闭或关闭时返回。这通常是一个意料之中的错误,因为你需要自己关闭服务器,但它也可以用来在输出中显示服务器停止的原因。在第二个错误检查中,检查是否有其他错误。如果发生这种情况,它会将错误打印到屏幕上,然后使用os.Exit
函数退出程序,错误代码为1
。
在运行程序时,你可能会看到的一个错误是address already in use
错误。当ListenAndServe
无法监听你提供的地址或端口时,这个错误可能会返回,因为另一个程序已经在使用它。有时,如果端口是常用的,而你计算机上的另一个程序正在使用它,就会发生这种情况,但如果你多次运行自己程序的多个副本,也会发生这种情况。如果你在学习本教程时看到这个错误,请确保在再次运行程序之前已经停止了上一步的程序。
**注意:**如果你看到address already in use
错误,并且你没有运行你的程序的另一个副本,这可能意味着其他程序正在使用它。如果发生这种情况,无论你在哪里看到本教程中提到的3333
,将其更改为高于1024且低于65535的另一个数字,例如3334
,然后重试。如果仍然看到错误,你可能需要继续寻找没有被使用的端口。一旦你找到一个可以工作的端口,就使用它来执行本教程中的所有命令。
现在你的代码已经准备好了,保存你的main.go
文件并使用go run
运行你的程序。与您可能编写的其他Go程序不同,此程序不会立即自己退出。运行程序后,继续执行下面的命令:
go run main.go
由于程序仍在终端中运行,因此需要打开第二个终端与服务器交互。当你看到命令或输出与下面的命令相同的颜色时,意味着要在第二个终端中运行它。
在第二个终端中,使用curl程序向HTTP服务器发出HTTP请求。curl
是一个默认安装在许多系统上的实用工具,它可以向各种类型的服务器发出请求。在本教程中,你将使用它来发起HTTP请求。你的服务器在你计算机的3333
端口上监听连接,所以你需要在同一个端口上向localhost
发起请求:
curl http://localhost:3333
OutputThis is my website!
在输出中,你会看到This is my website!
,因为你访问了HTTP服务器上的/
路径。
现在,在相同的终端中,向相同的主机和端口发出请求,但在curl
命令的末尾添加/hello
路径:
curl http://localhost:3333/hello
OutputHello, HTTP!
这次你会看到Hello, HTTP!
返回getHello
函数的响应。
如果回到运行HTTP服务器函数的终端,现在会看到服务器输出的两行内容。一个用于/
请求,另一个用于/hello
请求:
Outputgot / request
got /hello request
因为
相关文章:
如何在Go中制作HTTP服务器
引言 许多开发人员至少会花一些时间创建服务器,以便在互联网上分发内容。HTTP (Hypertext Transfer Protocol,超文本传输协议)提供了大部分这些内容,无论是请求一张猫的图片还是请求加载你正在阅读的教程。Go标准库为创建HTTP服务器以提供web内容或向这些服务器发出HTTP请求…...

Linux笔记---系统信息
🍎个人博客:个人主页 🏆个人专栏:Linux学习 ⛳️ 功不唐捐,玉汝于成 目录 前言 命令 1. uname - 显示系统信息 2. hostname - 显示或设置系统主机名 3. top - 显示系统资源使用情况 4. df - 显示磁盘空间使用情…...
最新版android stuido加上namespace
每个 Android 模块都有一个命名空间,此命名空间用作其生成的 命名空间由模块的 build.gradle 文件中的 namespace 属性定义,如以下代码段所示。namespace 最初会设为您在创建项目时选择的软件包名称。 Kotlin Groovy android {namespace "com.ex…...
Wireshark基础及捕获技巧
第一章:Wireshark基础及捕获技巧 1.1 Wireshark基础知识回顾 1.2 高级捕获技巧:过滤器和捕获选项 1.3 Wireshark与其他抓包工具的比较 第二章:网络协议分析 2.1 网络协议分析:TCP、UDP、ICMP等 2.2 高级协议分析:HTTP…...

Windows下Navicat15.0连接Oracle11g报ORA-28547解决
目录 背景 一、相关环境 1、操作系统 2、Navicat版本 3、ORACLE连接 4、默认连接 二、问题分析 1、默认dll配置 三、修改配置 1、下载匹配的client 2、替换相应目录 总结 背景 最近在项目中需要使用Oracle数据库,当前很多应用系统的数据都存储在MySQL或者Pos…...

21 Vue3中使用v-for遍历对象数组
概述 使用v-for遍历对象数组在真实的开发中也属于非常常见的用法,需要重点掌握。 因为目前流行的是前后端分离开发,在前后端分离开发中,最常需要处理的就是对象数组类型的数据了。 比如,将员工信息渲染到表格中。 这节课我们就…...
深入理解Java自定义异常与全局异常处理 @RestControllerAdvice
异常主要是包括编译时的异常和运行时的异常。编译时的异常可以通过捕获异常获取,运行时候的异常主要是通过代码规范,或者测试。 Spring Boot提供了两种异常处理方式来统一处理和维护异常信息。 第一种方式是使用RestControllerAdvice注解与ExceptionHand…...

h5页面跳转微信小程序(最简单的方法|URL Scheme)
文章目录 导文实现获取 URL Scheme加密 URL Scheme获取方式拼接参数 明文 URL Scheme获取方式 实际项目展示:频率限制注意事项开放范围示例代码包 导文 H5页面跳转微信小程序的需求是普遍存在的。由于微信小程序是一种只能在微信内部访问的应用程序,而H5…...

智能优化算法应用:基于非洲秃鹫算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于非洲秃鹫算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于非洲秃鹫算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.非洲秃鹫算法4.实验参数设定5.算法结果6.…...

持续集成交付CICD:Jenkins使用GitLab共享库实现前端项目镜像构建
目录 一、实验 1. GitLab修改项目文件与Harbor环境确认 2.Jenkins使用GitLab共享库实现前端项目镜像构建 3.优化CI流水线封装Harbor账户密码 4.Jenkins再次使用GitLab共享库实现前端项目镜像构建 一、实验 1. GitLab修改项目文件与Harbor环境确认 (1…...
SQL server 数据库 SQL语句高级用法
1、表的高级查询 use student select * from stuinfo1 -- 使用 in 的子查询 select * from stuinfo where stu_age in ( select stu_age from stuinfo where cla_id 12345 ) select * from stuinfo where stu_age in ( 19 , 20 , 21 , 25 , 23 , 1…...

wavlink 路由器 多处前台RCE漏洞复现
0x01 产品简介 WAVLINK是中国睿因科技(WAVLINK)公司开发的一款路由器。 0x02 漏洞概述 WAVLINK路由器mesh.cgi、nightled.cgi、live-api.cgi等接口处存在命令执行漏洞,攻击者可通过该漏洞获取服务器权限。包含型号WN530HG4、WN531G3、WN572HG3、WN535G3、WN575A4等。 0x…...

互联网中的商品超卖问题及其解决方案:Java中Redis结合UUID的应用
前言 在设计商品下单和库存扣减,你一定遇到过这样的问题,库存扣减为0了,可是消费者还能下单,并将订单信息保存到了数据库里,针对商品超卖问题,作此篇以解决。 随着互联网商业的飞速发展,商品超…...

mysql:查看线程缓存中的线程数量
使用命令show global status like Threads_cached;可以查看线程缓存中的线程数量。 例如,查询线程缓存中的线程数量如下: 然后启动应用程序,使用连接,查询如下: 由查询结果可以看到,线程缓存中的线程数量…...

线性表,也是Java中数组的知识点!
线性表定义: 由n (n≥0)个数据特性相同的元素构成的有限序列称为线性表,(n0)的时候被称为空表。 线性表的顺序表示 线性表的顺序存储又被称为顺序表 优点 无需为表示表中元素之间的逻辑关系而增加额外的存储空间可以随意读取任意位置的元素 缺点 插入…...

java使用面向对象实现图书管理系统
꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好,我是xiaoxie.希望你看完之后,有不足之处请多多谅解,让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …...

2023 英特尔On技术创新大会直播 |我感受到的“芯”魅力
文章目录 每日一句正能量前言AI时代,云与PC结合为用户带来更好体验全新处理器,首次引入针对人工智能加速的NPU大模型时代,软硬结合带来更好训练成果后记 每日一句正能量 成长是一条必走的路路上我们伤痛在所难免。 前言 在2023年的英特尔On技…...

Atium Designer 23 全新功能-丝印制备,解决DFM问题
进行PCB设计时需要养成良好的设计习惯,才能保证后期的生产效果。例如整板上需要保证丝印跟阻焊的间距规则避免产生丝印重叠造成的PCB制造设计(DFM)问题。丝印重叠阻焊的影响有如下: 1)PCB板后期打样,一般是…...

Nginx快速入门:安装目录结构详解及核心配置解读(二)
0. 引言 上节我们讲解了nginx的应用场景和安装,本节继续针对nginx的各个目录文件进行讲解,让大家更加深入的认识nginx。并通过一个实操案例,带大家来实际认知nginx的核心配置 1. nginx安装目录结构 首先nginx的默认安装目录为:…...
测试TensorFlow/PyTorch的GPU版本是否启用
文章目录 1. Pytorch测试代码2. TensorFlow测试代码 后续遇到好的会不断更新。。。 1. Pytorch测试代码 import torch def gpu_is_available():print(\nGPU details:)print(f gpu_is_available : , torch.cuda.is_available())print(f cuda_device_count : , t…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...

Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...

WPF八大法则:告别模态窗口卡顿
⚙️ 核心问题:阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程,导致后续逻辑无法执行: var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题:…...

实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...
Spring Security 认证流程——补充
一、认证流程概述 Spring Security 的认证流程基于 过滤器链(Filter Chain),核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤: 用户提交登录请求拦…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...

消息队列系统设计与实践全解析
文章目录 🚀 消息队列系统设计与实践全解析🔍 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡💡 权衡决策框架 1.3 运维复杂度评估🔧 运维成本降低策略 🏗️ 二、典型架构设计2.1 分布式事务最终一致…...