学习材料:https://geektutu.com/post/gee-day1.html
一、fmt格式化输出和占位符
https://pkg.go.dev/fmt
fmt.Fprintln使用默认的%v
fmt.Fprintln(w, http.StatusText(http.StatusNotFound))
fmt.Fprintf使用占位符%s
fmt.Fprintf(w, "hello\n%s", http.StatusText(http.StatusOK))
二、interface的强制类型转换
定义一个struct Engine,Engine
的成员函数func (egine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request)
,实现了interface Handler
中的ServeHTTP
。在使用ListenAndServe
时,满足interface Handler
要求的Engine实例
可以直接传入参数,自动转换为interface Handler
类型。
家用电器需要用电,规定通用的插座口(二插头/三插头——interface Handler
中的ServeHTTP
),不关心家电运作起来是什么样子的(Engine
中的ServeHTTP的功能
),只关心家电是否实现了对应的二插头/三插头(Engine
中是否实现了`ServeHTTP),来达到通电的目的。
package main
import (
"fmt"
"log"
"net/http"
)
// 定义一个handler
type Engine struct {
}
func (egine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
func main() {
egine := new(Engine)
log.Fatal(http.ListenAndServe(":9999", egine))
}
三、URI和URL的区别
访问 localhost:9999/hello?page=1
req.URL.Path
只是/hello
req.URL.RequestURI()
包括查询参数/hello?page=1
func (egine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// 访问 localhost:9999/hello?page=1, 会输出/hello?page=1,可以看出和Path的区别
fmt.Println(req.URL.RequestURI())
URL := req.URL.Path
}
四、map类型使用
# ok 判断元素是否存在
if handler, ok := engine.router[key]; ok {
handler(w, req)
} else {
fmt.Fprintf(w, "404 NOT FOUND: %s\n", req.URL)
}
五、struct实例化
键值对的方式实例化,初始化参数
type Engine struct {
router Router
}
func New() *Engine {
return &Engine{router: make(map[string]HandlerContext)}
}
type Context struct {
ResponseWriter http.ResponseWriter
Request *http.Request
Path string
}
c := &Context{Request: req, ResponseWriter: w, Path: req.URL.Path}