Bootstrap

01 Go Web基础_20240728 课程笔记

概述

如果您没有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私教~

;