01 Go Web基础_20240728 课程笔记

news2024/11/17 23:59:29

概述

如果您没有Golang的基础,应该学习如下前置课程。
在这里插入图片描述

基础不好的同学每节课的代码最好配合视频进行阅读和学习,如果基础比较扎实,则阅读本教程巩固一下相关知识点即可,遇到不会的知识点再看视频。

视频课程

最近发现越来越多的公司在用Golang了,所以精心整理了一套视频教程给大家,这个是其中的第3部,后续还会有很多。

视频已经录制完成,完整目录截图如下:
在这里插入图片描述

课程目录

  • 01 第一个Web程序.mp4
  • 02 默认的多路复用器.mp4
  • 03 自定义多路复用器.mp4
  • 04 配置读写超时时间.mp4
  • 05 httprouter库的介绍和安装.mp4
  • 06 httprouter的第一个使用案例.mp4
  • 07 使用httprouter提取路径参数.mp4
  • 08 复现浏览器跨域的问题.mp4
  • 09 使用httprouter分发二级域名.mp4
  • 10 使用httprouter挂载静态文件目录.mp4
  • 11 使用httprouter进行全局异常捕获.mp4
  • 12 将httprouter的代码下载到本地.mp4
  • 13 使用本地化的httprouter.mp4
  • 14 给本地化的httprouter打标签.mp4
  • 15 使用指定标签的本地化httprouter.mp4
  • 16 带参数的自定义处理器.mp4
  • 17 获取请求信息.mp4

每节课的代码

01 第一个Web程序.mp4

package main

import (
	"fmt"
	"net/http"
)

func hello(w http.ResponseWriter, req *http.Request) {
	fmt.Fprintf(w, "hello world!")
}

func main() {
	server := &http.Server{
		Addr: "0.0.0.0:8888",
	}
	http.HandleFunc("/", hello)
	server.ListenAndServe()
}

02 默认的多路复用器.mp4

package main

import (
	"fmt"
	"net/http"
)

// 定义多个处理器
type handle1 struct{}
type handle2 struct{}

func (h *handle1) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "handle1")
}
func (h *handle2) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "handle2")
}

func main() {
	server := &http.Server{
		Addr:    "0.0.0.0:8888",
		Handler: nil, // 表示使用默认的多路复用器DefaultServerMux
	}

	// http.Handle 调用多路复用器的DefaultServerMux.Handle() 方法
	http.Handle("/handle1", &handle1{})
	http.Handle("/handle2", &handle2{})

	server.ListenAndServe()
}

03 自定义多路复用器.mp4

package main

import (
	"fmt"
	"net/http"
)

// 定义多个处理器
type handle1 struct{}
type handle2 struct{}

func (h *handle1) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "handle1")
}
func (h *handle2) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "handle2")
}

func main() {
	// 自定义多路复用器
	mux := http.NewServeMux()
	mux.Handle("/handle1", &handle1{})
	mux.Handle("/handle2", &handle2{})

	server := &http.Server{
		Addr:    "0.0.0.0:8888",
		Handler: mux, // 表示使用默认的多路复用器DefaultServerMux
	}

	server.ListenAndServe()
}

04 配置读写超时时间.mp4

package main

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

// 定义多个处理器
type handle1 struct{}
type handle2 struct{}

func (h *handle1) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	time.Sleep(6 * time.Second)
	fmt.Fprintf(w, "handle1")
}
func (h *handle2) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "handle2")
}

func main() {
	// 自定义多路复用器
	mux := http.NewServeMux()
	mux.Handle("/handle1", &handle1{})
	mux.Handle("/handle2", &handle2{})

	server := &http.Server{
		Addr:         "0.0.0.0:8888",
		Handler:      mux, // 表示使用默认的多路复用器DefaultServerMux
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 5 * time.Second,
	}

	server.ListenAndServe()
}

05 httprouter库的介绍和安装.mp4

06 httprouter的第一个使用案例.mp4

package main

import (
	"fmt"
	"github.com/julienschmidt/httprouter"
	"net/http"
	"time"
)

func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	fmt.Fprint(w, "Welcome!\n")
}
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
}

func main() {
	router := httprouter.New()
	router.GET("/", Index)
	router.GET("/hello/:name", Hello)

	server := &http.Server{
		Addr:         "0.0.0.0:8888",
		Handler:      router,
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 5 * time.Second,
	}

	server.ListenAndServe()
}

07 使用httprouter提取路径参数.mp4

package main

import (
	"fmt"
	"github.com/julienschmidt/httprouter"
	"net/http"
	"time"
)

func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	fmt.Fprint(w, "Welcome!\n")
}
func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
	fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
}

func main() {
	router := httprouter.New()
	router.GET("/", Index)
	router.GET("/hello/:name", Hello)

	server := &http.Server{
		Addr:         "0.0.0.0:8888",
		Handler:      router,
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 5 * time.Second,
	}

	server.ListenAndServe()
}

08 复现浏览器跨域的问题.mp4

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    // const axios = require('axios');

    // 向给定ID的用户发起请求
    axios.get('http://127.0.0.1:8888/')
        .then(function (response) {
            // 处理成功情况
            console.log(response);
        })
        .catch(function (error) {
            // 处理错误情况
            console.log(error);
        })
        .finally(function () {
            // 总是会执行
        });
</script>
</body>
</html>

09 使用httprouter分发二级域名.mp4

package main

import (
	"github.com/julienschmidt/httprouter"
	"log"
	"net/http"
)

// HostMap 域名映射字典
type HostMap map[string]http.Handler

func (hs HostMap) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	//根据域名获取对应的Handler路由,然后调用处理(分发机制)
	if handler := hs[r.Host]; handler != nil {
		handler.ServeHTTP(w, r)
	} else {
		http.Error(w, "Forbidden", 403)
	}
}

func main() {
	userRouter := httprouter.New()
	userRouter.GET("/", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
		w.Write([]byte("sub1"))
	})

	dataRouter := httprouter.New()
	dataRouter.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		w.Write([]byte("sub2"))
	})

	//分别用于处理不同的二级域名
	hs := make(HostMap)
	hs["sub1.localhost:8888"] = userRouter
	hs["sub2.localhost:8888"] = dataRouter

	log.Fatal(http.ListenAndServe(":8888", hs))
}

10 使用httprouter挂载静态文件目录.mp4

package main

import (
	"github.com/julienschmidt/httprouter"
	"log"
	"net/http"
)

func main() {
	router := httprouter.New()
	router.ServeFiles("/static/*filepath", http.Dir("c01_hello"))

	log.Fatal(http.ListenAndServe(":8888", router))
}

11 使用httprouter进行全局异常捕获.mp4

package main

import (
	"fmt"
	"github.com/julienschmidt/httprouter"
	"log"
	"net/http"
)

func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	panic("error")
}

func main() {
	router := httprouter.New()
	router.GET("/", Index)

	// 全局异常捕获
	router.PanicHandler = func(w http.ResponseWriter, r *http.Request, v interface{}) {
		w.WriteHeader(http.StatusInternalServerError)
		fmt.Fprintf(w, "全局异常捕获:%v", v)
	}

	log.Fatal(http.ListenAndServe(":8888", router))
}

12 将httprouter的代码下载到本地.mp4

13 使用本地化的httprouter.mp4

package main

import (
	"fmt"
	"github.com/zhangdapeng520/zdpgo_httprouter"
	"net/http"
	"time"
)

func Index(w http.ResponseWriter, r *http.Request, _ zdpgo_httprouter.Params) {
	fmt.Fprint(w, "Welcome!\n")
}

func main() {
	router := zdpgo_httprouter.New()
	router.GET("/", Index)

	server := &http.Server{
		Addr:         "0.0.0.0:8888",
		Handler:      router,
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 5 * time.Second,
	}

	server.ListenAndServe()
}

14 给本地化的httprouter打标签.mp4

15 使用指定标签的本地化httprouter.mp4

16 带参数的自定义处理器.mp4

package main

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

type HelloHandler struct {
	Name string
}

func (h HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %s!", h.Name)
}

func main() {
	mux := http.NewServeMux()
	mux.Handle("/", HelloHandler{"张三"})

	server := &http.Server{
		Addr:         "0.0.0.0:8888",
		Handler:      mux,
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 5 * time.Second,
	}

	server.ListenAndServe()
}

17 获取请求信息.mp4

package main

import (
	"fmt"
	"net/http"
	"strings"
)

func request(w http.ResponseWriter, r *http.Request) {
	fmt.Println("HTTP方法 method", r.Method)
	fmt.Println("RequestURI是被客户端发送到服务端的请求的请求行中未修改的请求URI RequestURI:", r.RequestURI)

	// URL类型,下方分别列出URL的各成员
	fmt.Println("URL_path", r.URL.Path)
	fmt.Println("URL_RawQuery", r.URL.RawQuery)
	fmt.Println("URL_Fragment", r.URL.Fragment)

	// 协议版本
	fmt.Println("proto", r.Proto)
	fmt.Println("protomajor", r.ProtoMajor)
	fmt.Println("protominor", r.ProtoMinor)

	// HTTP请求的头域
	for k, v := range r.Header {
		for _, vv := range v {
			fmt.Println("header key:" + k + "  value:" + vv)
		}
	}

	// 判断是否multipart方式
	isMultipart := false
	for _, v := range r.Header["Content-Type"] {
		if strings.Index(v, "multipart/form-data") != -1 {
			isMultipart = true
		}
	}

	// 解析body
	if isMultipart == true {
		r.ParseMultipartForm(128)
		fmt.Println("解析方式:ParseMultipartForm")
	} else {
		r.ParseForm()
		fmt.Println("解析方式:ParseForm")
	}

	// body内容长度
	fmt.Println("ContentLength", r.ContentLength)

	// 是否在回复请求后关闭连接
	fmt.Println("Close", r.Close)

	// HOSt
	fmt.Println("host", r.Host)

	// 该请求的来源地址
	fmt.Println("RemoteAddr", r.RemoteAddr)

	fmt.Fprintf(w, "hello, let's go!") //这个写入到w的是输出到客户端的
}

func main() {
	http.HandleFunc("/", request)
	http.ListenAndServe(":8888", nil)
}

代码截图

在这里插入图片描述

总结

本套教程主要讲解Go Web开发的基础知识,特别是讲解了httprouter的用法以及本地化方法,比附上了完整的实战代码。

通过本套课程,能帮你入门Go Web开发,写一些简单的Web程序。

如果您需要完整的源码,打赏20元即可。

人生苦短,我用Python,我是您身边的Python私教~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【算法专题】双指针算法之18. 四数之和(力扣)

欢迎来到 CILMY23的博客 &#x1f3c6;本篇主题为&#xff1a;双指针算法之18. 四数之和&#xff08;力扣&#xff09; &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux | 算…

网络安全威胁情报是什么,它对代工生产(OEM)意味着什么?

随着汽车数字环境的不断变化&#xff0c;网络安全基础设施及其面临的威胁也日趋复杂。 为了更好地识别、理解并最终预防这些风险&#xff0c;网络安全威胁情报&#xff08;CTI&#xff09;的管理应是一个综合多方面的过程。 以下是CTI对OEM的意义&#xff0c;以及如何利用网络…

代码随想录算法训练营第40天|LeetCode 198.打家劫舍、213.打家劫舍II、337.打家劫舍III

1. LeetCode 198.打家劫舍 题目链接&#xff1a;https://leetcode.cn/problems/house-robber/ 文章链接&#xff1a;https://programmercarl.com/0198.打家劫舍.html#算法公开课 视频链接&#xff1a;https://www.bilibili.com/video/BV1Te411N7SX 思路&#xff1a; 递推公式&a…

Profinet从站转TCP/IP协议转化网关(功能与配置)

如何将Profinet和TCP/IP网络连接通讯起来呢?近来几天有几个朋友问到这个问题&#xff0c;那么作者在这里统一说明一下。其实有一个不错的设备产品可以很轻易地解决这个问题&#xff0c;名为JM-DNT-PN。接下来作者就从该设备的功能及配置详细说明一下。 一&#xff0c;设备主要…

相机镜头移动特效视频转场模板Pr工程文件

Pr转场模板&#xff0c;相机镜头移动特效视频转场Pr工程文件 逼真的相机移动&#xff1a;具有一系列动态相机移动功能&#xff0c;包括平移、倾斜、缩放和旋转&#xff0c;为您的过渡添加逼真和引人入胜的视觉元素。 无缝集成&#xff1a;以.prproj文件形式提供&#xff0c;便…

操作系统——进程深度理解

目录 一、操作系统 1、概念 2、操作系统的结构 3、操作系统的理解 二、进程 一、操作系统 1、概念 操作系统是一个软件&#xff0c;一款进行软硬件资源管理的软件 电脑开机的时间&#xff0c;就是把操作系统加载到内存并运行的过程。 对操作系统广义的认识&#xff1a;…

PowerBI 度量值不被切片器筛选

我们有这样一张表&#xff1a; 我们用一个切片器绑定奖金表[奖金]&#xff0c;就可以用表格来联动显示数据: 现在用户有个新的需求&#xff0c;当单选某个奖金时&#xff0c;需要统计小于这个奖金数的人数。 我用了一个度量值来统计&#xff1a; 度量值 VAR selected_bonus…

全国区块链职业技能大赛样题第9套后端源码

后端源码地址:https://blog.csdn.net/Qhx20040819/article/details/140746050 前端源码地址:https://blog.csdn.net/Qhx20040819/article/details/140746216 智能合约+数据库表设计:https://blog.csdn.net/Qhx20040819/article/details/140746646 项目预览 登录 用户管理

vue3 快速入门 (五) : Flex布局

1. 如何变成Flex布局 变成Flex容器&#xff0c;只需在容器布局的节点的CSS中&#xff0c;增加display : flex .mylayout {/* 省略了其他代码 */display: flex; }2. flex direction : 方向 row : 以行排列 row-reverse &#xff1a; 以行反向排列 column &#xff1a;以列排列…

向日葵RCE复现(CNVD-2022-10270/CNVD-2022-03672)

一、环境 1.1 网上下载低版本的向日葵<2022 二、开始复现 2.1 在目标主机上打开旧版向日葵 2.2 首先打开nmap扫描向日葵主机端口 2.3 在浏览器中访问ip端口号cgi-bin/rpc?actionverify-haras &#xff08;端口号&#xff1a;每一个都尝试&#xff0c;直到获取到session值…

AJAX之原理

目录 XMLHttpRequest基本使用查询参数数据提交&#xff08;注册账号&#xff09; Promise基本语法Promise三种状态Promise链式调用 async函数和await XMLHttpRequest 基本使用 XMLHttpRequest对象用于与服务器交互 与axios关系&#xff1a;axios内部采用XMLHttpRequest与服务…

Elasticsearch:跨集群使用 ES|QL

警告&#xff1a;ES|QL 的跨集群搜索目前处于技术预览阶段&#xff0c;可能会在未来版本中更改或删除。Elastic 将努力解决任何问题&#xff0c;但技术预览中的功能不受官方 GA 功能的支持 SLA 约束。 使用 ES|QL&#xff0c;你可以跨多个集群执行单个查询。 前提&#xff1a; …

每天一个设计模式之命令模式(第二天)

交互模式中的命令模式&#xff0c;在开始记录之前&#xff0c;要讲些自己的感受&#xff0c;真真切切的感受到了悟性的瓶颈&#xff01;一共十页书&#xff0c;需要自己细细琢磨品味&#xff0c;至少三四遍才大概了解了他们间的逻辑&#xff0c;我需要调整下自己的学习思路&…

Lumos学习王佩丰Excel第七讲:认识公式与函数

一、认识Excel公式 1、运算符 运算符 作用 算术运算符 加 - 减 * 乘 / 除 % 百分比&#xff0c;相当于除以100 & 连接符&#xff0c;文本数字均可连接 ^ 乘方 比较运算符 等于 > 大于 < 小于 ≤ 小于等于 ≥ 大于等于 例1&#xff1…

python实现信号合成(DSP仿真系统)【1】

python实现信号合成(DSP仿真系统)【1】 1、效果图 2、功能结构 1、基础信号正弦波、脉冲函数、阶跃函数、斜坡函数、方波、sinc曲线、矩形波(非周期) 2、信号合成(叠加)叠加噪音 3、波形展示原始波形、叠加波形、FFT、PSD、卷积 4、各种滤波器4.1.限幅滤波器4.2.中位值滤…

【OSCP系列】OSCP靶机-BTRsys-2.1(原创)

OSCP系列靶机—BTRsys-2.1 原文转载已经过授权 原文链接&#xff1a;Lusen的小窝 - 学无止尽&#xff0c;不进则退 (lusensec.github.io) 一、主机发现 二、端口扫描 1、快速扫描 2、全端口扫描 3、服务系统探测 4、漏洞探测 80端口扫到了一些目录&#xff0c;有wordpress框…

CentOS7使用yum安装MySQL

废话不多说&#xff0c;直接上干货 1、CentOS7的yum源中默认是没有mysql的&#xff0c;我们先下载mysql的repo源 wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 2、安装mysql-community-release-el7-5.noarch.rpm包 sudo rpm -ivh mysql-community-r…

算法通关:007时间复杂度和空间复杂度:生成相邻两数不相等的数组

生成相邻两数不相等的数组 全部代码&#xff1a; import java.util.Arrays;/*** Author: ggdpzhk* CreateTime: 2024-07-28* 随机生成数组&#xff0c;比如每个元素都在0-3之间&#xff0c;且相邻两个元素不相同*/ public class _007 {public static void main(String[] args)…

Redis:管道

1. 面试题 如何优化频繁命令往返造成的性能瓶颈&#xff1f; 问题由来 edis是一种基于客户端-服务端模型以及请求/响应协议的TCP服务。一个请求会遵循以下步骤&#xff1a; 1 客户端向服务端发送命令分四步(发送命令→命令排队→命令执行→返回结果)&#xff0c;并监听Socket…

Vue.js 2 项目实战(九):商品列表

前言 Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架。它的设计初衷是通过采用简洁且强大的结构&#xff0c;使前端开发变得更简单和高效。以下是对 Vue.js 的详细介绍&#xff1a; 核心特性 声明式渲染 Vue.js 使用声明式语法来描述用户界面&#xff0c;通过数据绑…