Golang笔记:使用http包实现基础WebServer功能

文章目录

  • 目的
  • 监听请求并响应
  • 请求解析
  • 进行响应
  • 静态文件服务
  • 总结

目的

WebServer是一种非常常用的功能,Golang的高并发特性在处理此类工作中也有较大的优势,同时借助标准库中的 net/http 包可以非常快速的编写WebServer应用。这篇文章将简单记录下相关内容。

https://pkg.go.dev/net/http

Package http provides HTTP client and server implementations.

监听请求并响应

WebServer本质上来说很简单,主要可以为两步:

  • 监听某个端口号上收到的HTTP数据;
  • 根据收到的HTTP请求中的路径执行对应的操作;

下面是个简单的示例:

package main

import (
	"fmt"
	"log"
	"net/http"
	"time"
)

func hello(w http.ResponseWriter, r *http.Request) { //回调函数,回调函数将在协程中运行
	time.Sleep(4 * time.Second)
	fmt.Fprintf(w, "Hello, you've requested: %s\n", r.URL.Path) // 向客户端应答数据
}

func naisu(w http.ResponseWriter, r *http.Request) { //回调函数
	fmt.Fprintln(w, "Naisu 233!") // 向客户端应答数据
}

func main() {
	http.HandleFunc("/", hello)      // 设置路由地址与对应回调函数
	http.HandleFunc("/naisu", naisu) // 实际应用中通常根据需求设置多个路由地址与对应回调函数

	err := http.ListenAndServe(":80", nil) // 启动WebServer,监听80端口,可以在本机浏览器中通过 http://localhost:<端口号><路由地址> 进行访问(80端口可以省略:80)
	// err := http.ListenAndServe("0.0.0.0:80", nil) // 在本机所有网卡上进行监听,同网段下的设备可以通过 http://本机IP地址/ 进行访问
	if err != nil {
		log.Fatal("ListenAndServe: ", err)
	}
}

在这里插入图片描述

上面示例中核心涉及的就两个方法:

  • func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
    该方法用于设置路由和对应的回调函数;
  • func ListenAndServe(addr string, handler Handler) error
    该方法用于监听某个端口号,启动WebServer;
    该方法还有个变种 ListenAndServeTLS 用于启动HTTPS服务;

请求解析

上面的回调函数原型是 func(http.ResponseWriter, *http.Request) 包含了请求对象和返回的响应对象,实际操作中也主要就是根据请求的内容和业务逻辑进行响应。

下面例子中打印了请求对象中的一些内容:

package main

import (
	"fmt"
	"net/http"
)

func hello(w http.ResponseWriter, r *http.Request) {
	fmt.Println(r.Method)
	fmt.Println(r.URL)
	fmt.Println(r.Header) // 请求头,各个请求头字段以字典形式保存
	fmt.Println(r.Body)
	fmt.Println(r.ContentLength)
}

func main() {
	http.HandleFunc("/", hello)

	http.ListenAndServe(":80", nil)
}

在这里插入图片描述
上面演示中 /favicon.ico 是浏览器自己发起的请求。

更多使用方法可以查看官方文档中 Request 类型和相关的方法。

进行响应

进行响应主要就是设置响应头字段,设置状态码,写正文内容这些。

package main

import (
	"io"
	"net/http"
)

func hello(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Trailer", "AtEnd1, AtEnd2")                 // 设置(添加)响应头字段
	w.Header().Add("Trailer", "AtEnd3")                         // 添加响应头字段
	w.Header().Set("Content-Type", "text/plain; charset=utf-8") // 添加响应头字段
	w.WriteHeader(http.StatusOK)                                // 写状态码
	io.WriteString(w, "Hello Naisu.\n")                         // 响应body内容
	// 注意写头字段、状态码和body的顺序
}

func main() {
	http.HandleFunc("/", hello)

	http.ListenAndServe(":80", nil)
}

在这里插入图片描述

更多使用方法可以查看官方文档中 ResponseWriter 类型和相关的方法。

静态文件服务

对于WebServer来说静态文件服务是非常常用的功能。静态文件服务最常用的就是提供前端网页文件等,所以我们这里弦准备一个名为 index.html 文件,放在当前项目目录下,文件内容如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
    <h1 style="color: #4DD498;">Hello Naisu!</h1>
</body>
</html>

然后使用下面方式启动静态文件服务:

package main

import (
	"net/http"
)

func main() {
	fs := http.FileServer(http.Dir("./"))       // 设置静态文件存放路径,可以使用绝对或相对路径
	http.Handle("/", http.StripPrefix("/", fs)) // 设置静态文件路由处理,通过 http://localhost/文件名 进行访问
	// http.Handle("/static/", http.StripPrefix("/static/", fs)) // 通过 http://localhost/static/文件名 进行访问
	// 设置静态文件存放路径根目录下的 index.html 文件可以不加文件名进行访问

	http.ListenAndServe(":80", nil)
}

在这里插入图片描述

当然只有一个文件的话也可以使用 func ServeFile(w ResponseWriter, r *Request, name string) 方法来处理,比如上面情况下也可以指定路径返回指定文件:

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, "index.html")
})

静态文件服务除了上面这样简单使用外,也可以进行定制,比如官方文档中的例子,过滤了设置的目录下所有文件名以 . 开头的文件:
https://pkg.go.dev/net/http#example-FileServer-DotFileHiding

总结

Golang使用标准库中的 net/http 来编写WebServer是比较简单的。更多教程可以参考下面链接:
https://gowebexamples.com/
https://github.com/astaxie/build-web-application-with-golang

实际工作中如果需求比较全面的话全部细节功能都从头实现的话就比较麻烦了。Golang有一个非常出名的用于Web开发的工具库Gorilla,实现了很多常用的功能:
https://www.gorillatoolkit.org/

对于更加复杂的项目也可以直接使用现成的框架。Gin是一个Golang的主流的轻量级Web框架,其官网和项目地址如下:
https://gin-gonic.com/
https://github.com/gin-gonic/gin

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/21380.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第02章 变量与运算符

一 关键字&#xff08;keyword&#xff09; 定义&#xff1a;被Java语言赋予了特殊含义&#xff0c;用做专门用途的字符串&#xff08;或单词&#xff09; HelloWorld案例中&#xff0c;出现的关键字有 class、public 、 static 、 void 等&#xff0c;这些单词已经被Java定义…

第1章 Nginx简介

基于 Nginx版本 1.14.2 &#xff0c;Tomcat版本 9.0.0 演示 第1章 Nginx简介 1.1 Nginx发展介绍 Nginx &#xff08;engine x&#xff09; 是一个高性能的Web服务器和反向代理服务器&#xff0c;也可以作为邮件代理服务器。 Nginx 特点是占有内存少&#xff0c;并发处理能力…

基于粒子群算法的微网经济优化调度——附Matalb代码

目录 摘要&#xff1a; 代码主要内容&#xff1a; 研究背景&#xff1a; 微电网模型&#xff1a; 粒子群算法&#xff1a; 运行结果&#xff1a; Matlab代码分享&#xff1a; 摘要&#xff1a; 提出了一种经济与环保相协调的微电网优化调度模型&#xff0c;针对光伏电池…

深度解析接口自动化框架封装项目:封装层级,关联调用,极限改进

目录 前言&#xff1a; 一、接口封装与封装层级 二、接口关联和数据准备 三、接口封装极限改进 四、代码示例 五、总结 前言&#xff1a; 接口自动化是软件测试领域中的一个重要环节&#xff0c;它可以自动化执行接口测试用例&#xff0c;快速发现和定位接口问题&#xf…

MyBatis中的别名机制

在我们使用MyBatis中的select语句时&#xff0c;需要指定resultType的值&#xff0c;即查询对象的类型&#xff0c;该值是对象的完整类名&#xff0c;看起来非常的繁琐&#xff0c;因此MyBatis中有了别名机制。 使用步骤 在mybatis-config.xml文件中添加< typeAliases >…

C语言进阶——字符函数和字符串函数(上)

重点&#xff1a; 重点介绍处理字符和字符串的库函数的使用和注意事项 1、求字符串长度 strlen 2、长度不受限制的字符串函数 strcpy strcat strcmp 1、函数介绍 1.1 strlen 函数原型&#xff1a;size_t strlen (const char *str); 1、字符串以‘\0’作为结束标志&#xff0…

如何把ipa文件(iOS安装包)安装到iPhone手机上? 附方法汇总

苹果APP安装包ipa如何安装在手机上&#xff1f;很多人不知道怎么把ipa文件安装到手机上&#xff0c;这里就整理了苹果APP安装到iOS设备上的方式&#xff0c;仅供参考 苹果APP安装包ipa如何安装在手机上&#xff1f;使用过苹果手机的人应该深有感触&#xff0c;那就是苹果APP安…

登录appuploader

登录appuploader 常规使用登录方法 双击appuploader.exe 启动appuploader 点击底部的未登录&#xff0c;弹出登录框 在登录框内输入apple开发者账号 如果没有apple开发者账号&#xff0c;只是普通的apple账号&#xff0c;请勾选上未支付688 然后软件会提示输入验证码&#…

【Spring/MySQL数据库系列】数据库事务的特点与隔离级别

⭐️前面的话⭐️ 本文已经收录到《Spring框架全家桶系列》专栏&#xff0c;本文将介绍有关数据库事务的特点以及隔离级别。 &#x1f4d2;博客主页&#xff1a;未见花闻的博客主页 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4…

【C++ STL】 趣学stackqueuepriority_queue【对话情景版】

文章目录 &#x1f4cd;前言C STL 之 stack&queue基础知识及其模拟实现&#x1f4cd;容器适配器&#x1f388;什么是适配器&#xff1f;&#x1f388;STL标准库中stack和queue的底层结构&#x1f388;deque的简单介绍(了解)&#x1f4cc;deque的原理介绍&#x1f4cc;deque…

Python学习27:存款买房(A)

描述‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬ 你刚刚大学毕业&#xff0c;…

基于Hebb学习的深度学习方法总结

基于Hebb学习的深度学习方法总结 0 引言1 前置知识1.1 Hebb学习规则1.2 Delta学习规则 2 SoftHebb学习算法2.1 WTA(Winner Take All)2.2 SoftHebb2.3 多层Hebb网络2.4 Hebb学习的性能测评 3 参考文献 0 引言 总所周知&#xff0c;反向传播算法&#xff08;back-propagating, B…

图神经网络:(大型图的有关处理)在Pumbed数据集上动手实现图神经网络

文章说明&#xff1a; 1)参考资料&#xff1a;PYG官方文档。超链。 2)博主水平不高&#xff0c;如有错误还望批评指正。 3)我在百度网盘上传了这篇文章的jupyter notebook和有关文献。超链。提取码8848。 文章目录 Pumed数据集文献阅读继续实验 Pumed数据集 导库 from torch_…

不会Elasticsearch标准查询语句,如何分析数仓数据?

1 Elasticsearch的查询语句 ES中提供了一种强大的检索数据方式,这种检索方式称之为Query DSL,Query DSL是利用Rest API传递JSON格式的请求体(Request Body)数据与ES进行交互&#xff0c;这种方式的丰富查询语法让ES检索变得更强大&#xff0c;更简洁。 1.1 查询预发 # GET /…

案例分享|地弹现象导致DCDC电源芯片工作不正常

很多读者都应该听过地弹&#xff0c;但是实际遇到的地弹的问题应该很少。本案例就是一个DCDC电源芯片的案例。 1. 问题描述 如下图1 &#xff0c;产品其中一个供电是12V转3.3V的电路&#xff0c;产品发货50K左右以后&#xff0c;大约有1%的产品无法启动&#xff0c;经过解耦定…

【C++】深入剖析C++11新特性

目录 一、C11简介 二、统一的列表初始化 1.&#xff5b;&#xff5d;初始化 2.std::initializer_list 三、声明 1.auto 2.decltype 3.nullptr 四、范围for 五、final和oberride 六、STL中一些变化 1.array 2.forward_list 3.unordered_map和unordered_set 七、右…

Python入门(十一)while循环(一)

while循环&#xff08;一&#xff09; 1.简介2.使用while循环3.让用户选择何时退出4.使用标志5.使用break退出循环6.在循环中使用continue7.避免无限循环 作者&#xff1a;xiou 1.简介 for循环用于针对集合中的每个元素都执行一个代码块&#xff0c;而while循环则不断运行&am…

虚幻引擎4利用粒子系统实现物体轨迹描绘

虚幻引擎4利用粒子系统实现物体轨迹描绘 目录 虚幻引擎4利用粒子系统实现物体轨迹描绘前言粒子系统利用粒子系统实现物体轨迹描绘创建粒子系统将粒子系统的产生位置绑定到运动物体上 小结 前言 由于在物体运动时&#xff0c;想要观察其总的运动轨迹&#xff0c;以便对其控制做…

CANoe-如何在Trace窗口显示SYN和FIN报文、同一条以太网报文在Trace窗口中的多条显示

1、如何在Trace窗口显示SYN和FIN报文 当我们使用CANoe实现TCP通信时,希望在Trace窗口直观显示报文的类型:SYN、ACK、FIN。显然Trace窗口也是支持这样的功能的。但很多时候由于一些人为的不正确的设置和配置,造成无法显示。 如果想解析出SYN报文,首先在Trace窗口选择正确的…

java注解

Target({ElementType.METHOD, ElementType.TYPE}) 注解的适用范围&#xff0c;可以用在什么地方&#xff0c;超过这个作用范围,编译的时候就会报错 值说明ElementType.METHOD用于描述方法ElementType.TYPE用于描述类、接口(包括注解类型) 或enum声明ElementType.LOCAL_VARIAB…