Go Web编程(三——Web基础)
2021/5/11 22:25:22
本文主要是介绍Go Web编程(三——Web基础),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
- 参考技术论坛文档:《Go Web 编程》
- https://learnku.com/docs/build-web-application-with-golang/031-web-working-mode/3168
- Web服务器的工作原理
客户机通过 TCP/IP 协议建立到服务器的 TCP 连接
客户端向服务器发送 HTTP 协议请求包,请求服务器里的资源文档
服务器向客户机发送 HTTP 协议应答包,如果请求的资源包含有动态语言的内容,那么服务器会调用动态语言的解释引擎负责处理 “动态内容”,并将处理得到的数据返回给客户端
客户机与服务器断开。由客户端解释 HTML 文档,在客户端屏幕上渲染图形结果
需要注意的是客户机与服务器之间的通信是非持久连接的,也就是当服务器发送了应答后就与客户机断开连接,等待下一次请求。
- URL和DNS解析
URL是统一资源定位符的缩写。
scheme://host[:port#]/path/.../[?query-string][#anchor] scheme 指定底层使用的协议(例如:http, https, ftp) host HTTP 服务器的 IP 地址或者域名 port# HTTP 服务器的默认端口是 80,这种情况下端口号可以省略。如果使用了别的端口,必须指明,例如 http://www.cnblogs.com:8080/ path 访问资源的路径 query-string 发送给 http 服务器的数据 anchor 锚
DNS是域名系统的英文缩写,它用于TCP/IP网络,从事将主机名和域名转换为IP地址的工作。
迭代查询:查询的递交者不变(本地DNS服务器)
迭代查询:查询的递交者更替
- Http协议详解
HTTP 协议是无状态的,同一个客户端的这次请求和上次请求是没有对应关系,对 HTTP 服务器来说,它并不知道这两个请求是否来自同一个客户端。为了解决这个问题, Web 程序引入了 Cookie 机制来维护连接的可持续状态。
HTTP 协议定义了很多与服务器交互的请求方法,最基本的有 4 种,分别是 GET, POST, PUT, DELETE。一个 URL 地址用于描述一个网络上的资源,而 HTTP 中的 GET, POST, PUT, DELETE 就对应着对这个资源的查,增,改,删 4 个操作。
GET用于获取、POST用于更新。
- Http/net包建立一个简单的Web服务器
package main import ( "fmt" "net/http" "strings" "log" ) func sayhelloName(w http.ResponseWriter, r *http.Request) { r.ParseForm() // 解析参数,默认是不会解析的 fmt.Println(r.Form) // 这些信息是输出到服务器端的打印信息 fmt.Println("path", r.URL.Path) fmt.Println("scheme", r.URL.Scheme) fmt.Println(r.Form["url_long"]) for k, v := range r.Form { fmt.Println("key:", k) fmt.Println("val:", strings.Join(v, "")) } fmt.Fprintf(w, "Hello astaxie!") // 这个写入到 w 的是输出到客户端的 } func main() { http.HandleFunc("/", sayhelloName) // 设置访问的路由 err := http.ListenAndServe(":9090", nil) // 设置监听的端口 if err != nil { log.Fatal("ListenAndServe: ", err) } }
访问:http://localhost:9090
可以看到浏览器输出了:http://localhost:9090
访问http://localhost:9090/?url_long=111&url_long=222服务端输出:
C:\Users\Administrator\AppData\Local\Temp\___go_build_GOWEB1_go.exe D:/GO/main/GOWEB1.go #gosetup C:\Users\Administrator\AppData\Local\Temp\___go_build_GOWEB1_go.exe #gosetup map[] path / scheme [] map[url_long:[111 222]] path / scheme [111 222] key: url_long val: 111222 map[url_long:[111 222]] path / scheme [111 222] key: url_long val: 111222
-
Web工作方式的几个概念
- Request:用户请求的信息,用来解析用户的请求信息,包括 post、get、cookie、url 等信息
- Response:服务器需要反馈给客户端的信息
- Conn:用户的每次请求链接
- Handler:处理请求和生成返回信息的处理逻辑
-
如何监听端口、接收客户端请求、分配handller?
ListenAndServe 来处理这些事情的,这个底层其实这样处理的:初始化一个 server 对象,然后调用了 net.Listen("tcp", addr),也就是底层用 TCP 协议搭建了一个服务,然后监控我们设置的端口。
HTTP包源码:
func (srv *Server) Serve(l net.Listener) error { defer l.Close() var tempDelay time.Duration // how long to sleep on accept failure for { rw, e := l.Accept() if e != nil { if ne, ok := e.(net.Error); ok && ne.Temporary() { if tempDelay == 0 { tempDelay = 5 * time.Millisecond } else { tempDelay *= 2 } if max := 1 * time.Second; tempDelay > max { tempDelay = max } log.Printf("http: Accept error: %v; retrying in %v", e, tempDelay) time.Sleep(tempDelay) continue } return e } tempDelay = 0 c, err := srv.newConn(rw) if err != nil { continue } go c.serve() } }
- GO的HTTP包详解
GO的http有两个核心功能:Conn、ServeMux
GO在等待客户端请求里面是这样写的:
c,err := srv.newConn(rw) if err != nil { continue } go c.serve()
Handler定义:
type Handler interface { ServeHTTP(ResponseWriter, *Request) // 路由实现器 }
HandlerFunc定义:
type HandlerFunc func(ResponseWriter, *Request) // ServeHTTP calls f(w, r). func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { f(w, r) //f拥有了ServerHttp方法 }
默认的路由器对Handler接口的实现:
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) { if r.RequestURI == "*" { w.Header().Set("Connection", "close") w.WriteHeader(StatusBadRequest) return } h, _ := mux.Handler(r) h.ServeHTTP(w, r) }
如上所示路由器接收到请求之后,如果是 * 那么关闭链接,不然调用 mux.Handler(r) 返回对应设置路由的处理 Handler,然后执行 h.ServeHTTP(w, r)
也就是调用对应路由的 handler 的 ServerHTTP 接口。
Handler方法:
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) { if r.Method != "CONNECT" { if p := cleanPath(r.URL.Path); p != r.URL.Path { _, pattern = mux.handler(r.Host, p) return RedirectHandler(p, StatusMovedPermanently), pattern } } return mux.handler(r.Host, r.URL.Path) } func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) { mux.mu.RLock() defer mux.mu.RUnlock() // Host-specific pattern takes precedence over generic ones if mux.hosts { h, pattern = mux.match(host + path) } if h == nil { h, pattern = mux.match(path) } if h == nil { h, pattern = NotFoundHandler(), "" } return }
Go 其实支持外部实现的路由器 ListenAndServe 的第二个参数就是用以配置外部路由器的,它是一个 Handler 接口,即外部路由器只要实现了 Handler 接口就可以,我们可以在自己实现的路由器的 ServeHTTP 里面实现自定义路由功能。
package main import ( "fmt" "net/http" ) type MyMux struct { } func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" { sayhelloName(w, r) return } http.NotFound(w, r) return } func sayhelloName(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello myroute!") } func main() { mux := &MyMux{} http.ListenAndServe(":9090", mux) //mux自定义的路由 }
main例:
func main() { http.HandleFunc("/", sayhelloName) // 设置访问的路由 //""中为访问的路由,sayhelloName为调用的Handler(自己定义的) err := http.ListenAndServe(":9090", nil) // 设置监听的端口 if err != nil { log.Fatal("ListenAndServe: ", err) } }
这篇关于Go Web编程(三——Web基础)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-20MongoDB教程:从入门到实践详解
- 2024-11-17执行 Google Ads API 查询后返回的是空数组什么原因?-icode9专业技术文章分享
- 2024-11-17google广告数据不同经理账户下的凭证可以获取对方的api数据吗?-icode9专业技术文章分享
- 2024-11-15SendGrid 的 Go 客户端库怎么实现同时向多个邮箱发送邮件?-icode9专业技术文章分享
- 2024-11-15SendGrid 的 Go 客户端库怎么设置header 和 标签tag 呢?-icode9专业技术文章分享
- 2024-11-12Cargo deny安装指路
- 2024-11-02MongoDB项目实战:从入门到初级应用
- 2024-11-01随时随地一键转录,Google Cloud 新模型 Chirp 2 让语音识别更上一层楼
- 2024-10-25Google Cloud动手实验详解:如何在Cloud Run上开发无服务器应用
- 2024-10-24AI ?先驱齐聚 BAAI 2024,发布大规模语言、多模态、具身、生物计算以及 FlagOpen 2.0 等 AI 模型创新成果。