package main import ( "fmt" "net/http" "path" "path/filepath" "strings" "time" ) func main() { // 演示地址:http://localhost:8080/demo.html?name=张三&gender=男&age=18 http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) { // 屏蔽“/favicon.ico”的请求 if request.URL.Path == "/favicon.ico" { return } // 设置响应头 writer.Header().Set("Content-Type", "text/html; charset=utf-8") // 默认为"text/plain; charset=utf-8" // writer.Header().Set("Content-Type", "application/json; charset=utf-8") // 响应内容为JSON时使用 writer.Header().Set("Server", "MaNongServer") writer.Header().Set("X-AspNetMvc-Version", "4.0") // 自定义响应头 writer.Header().Set("X-AspNet-Version", "4.0.30319") // 自定义响应头 writer.Header().Set("X-Powered-By", "ASP.NET") // 自定义响应头 // 简单返回404错误页 // 重要提醒:writer.WriteHeader()会覆盖http.NotFound()的状态码,若状态码不符合预期可检查是否为两者先后顺序导致 // http.NotFound(writer, request) // return // http.NotFound()不会终止程序往下执行,必须使用return手动终止 // 设置HTTP状态码(非必须,若不设置则默认为200) writer.WriteHeader(http.StatusOK) // const StatusOK int = 200 // writer.WriteHeader(http.StatusNotFound) // const StatusNotFound int = 404 // 获取请求头部分信息 fmt.Printf("Accept-Encoding ===> %+v \n", request.Header.Get("Accept-Encoding")) fmt.Printf("Referer ===> %+v \n", request.Header.Get("Referer")) fmt.Printf("User-Agent ===> %+v \n", request.Header.Get("User-Agent")) // Accept-Encoding ===> gzip, deflate, br // Referer ===> // User-Agent ===> Mozilla/5.0 (Windows NT 10.0; Win64; x64) ……(此处省略内容若干)…… // 请求方法 fmt.Printf("request.Method ===> %+v \n", request.Method) // request.Method ===> GET // 请求URI fmt.Printf("request.RequestURI ===> %+v \n", request.RequestURI) // request.RequestURI ===> /demo.html?name=%E5%BC%A0%E4%B8%89&gender=%E7%94%B7&age=18 // 请求路径 fmt.Printf("request.URL.Path ===> %+v \n", request.URL.Path) // request.URL.Path ===> /demo.html // 请求参数(map) fmt.Printf("request.URL.Query() ===> %+v \n", request.URL.Query()) // request.URL.Query() ===> map[age:[18] gender:[男] name:[张三]] // 请求参数(裸) fmt.Printf("request.URL.RawQuery ===> %+v \n", request.URL.RawQuery) // request.URL.RawQuery ===> name=%E5%BC%A0%E4%B8%89&gender=%E7%94%B7&age=18 // 解析请求路径 dir, file := filepath.Split(request.URL.Path) ext := path.Ext(file) filename := strings.TrimSuffix(file, ext) fmt.Printf("dir ===> %+v \n", dir) // dir ===> / 目录 fmt.Printf("file ===> %+v \n", file) // file ===> demo.html 文件名(含扩展名) fmt.Printf("ext ===> %+v \n", ext) // ext ===> .html 扩展名 fmt.Printf("filename ===> %+v \n", filename) // filename ===> demo 文件名(无扩展名) // 获取GET参数 name := request.URL.Query().Get("name") gender := request.URL.Query().Get("gender") age := request.URL.Query().Get("age") fmt.Printf("俺叫%+v(%+v),今年%+v岁。\n", name, gender, age) // 俺叫张三(男),今年18岁。 // 设置要输出的内容,writer.Write()可多次调用 _, _ = writer.Write([]byte("PHP是世界上最好の语言")) _, _ = writer.Write([]byte("~~~")) // 页面输出结果:PHP是世界上最好の语言~~~ // 重要提醒:即使网页已加载完毕,协程也不会终止,且不依赖客户端,就算关掉浏览器协程任务依然会执行 go func(writer http.ResponseWriter) { fmt.Println("协程任务执行开始") // 由于协程不会阻塞网页加载且不依赖客户端,故这里可执行非紧急任务(如记录本次请求日志)或长耗时任务 max := 5 for i := 1; i <= max; i++ { time.Sleep(time.Second * 1) fmt.Printf("协程任务执行中(%d/%d)……\n", i, max) } // 重要提醒:不能在协程里调用writer.Write(),因为协程是异步的,可能服务器已经返回响应内容了协程还没启动 _, err := writer.Write([]byte("从入门到放弃")) if err != nil { fmt.Println("在协程里调用writer.Write()出错:" + err.Error()) // 在协程里调用writer.Write()出错:http: wrote more than the declared Content-Length } fmt.Println("协程任务执行完毕") }(writer) }) // 启动HTTP服务器 err := http.ListenAndServe(":8080", nil) if err != nil { panic("启动HTTP服务器失败:" + err.Error()) } } // ========== 总结 ========== // // 1、响应HTTP请求有顺序要求,建议按照(设置响应头)→(设置HTTP状态码)→(设置要输出的内容)顺序依次执行。
Copyright © 2024 码农人生. All Rights Reserved