前言
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。
Go语言最擅长的领域就是Web开发,此贴是本人入门完go语法基础后学习Web开发的学习笔记。
第一个Go Web
新建go文件hello_world.go 写入:
package main
import (
"fmt"
"net/http"
)
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Println("hello world")
}
func main() {
server := &http.Server{
Addr: "0.0.0.0:80",
}
http.HandleFunc(
"/",
hello,
)
server.ListenAndServe()
}
在命令行运行:
go run ./hello_world.go
可以发现控制台输出以下信息
Web程序运行原理
通过上述代码可以看到,要编写一个Web服务器端程序是很简单的:只是要调用net/http包中的HandleFunc()处理器函数和==ListenAndServe()==函数即可。
Go通过简单的几行代码,就可以运行一个Web服务端程序。
注:通过go程序构建起来的服务端程序拥有高并发的特性。
- 运行原理
首先来讲讲用户浏览网页的原理:
(1)用户打开客户端浏览器,输入URL地址。
(2)客户端浏览器通过HTTP协议向服务器发送浏览请求。
(3)服务器端通过CGI程序接收请求,如果在客户端浏览器请求的资源包不含动态语言的内容,则服务端CGI程序直接通过HTTP协议向客户端浏览器发送应答包。
(4)客户端浏览器解释并显示HTML页面
其中客户端浏览器通过与服务器端建立连接,发起请求(请求一般为GET或者POST请求),再由客户端进行HTTP响应。
- Web应用程序的组成
Web应用程序负责调用动态语言的解释引擎负责处理”动态内容”,一般由处理器和模板引擎组成。
通常情况下,处理器会接收HTTP请求,然后解析路由,最后将URL映射到对应的控制器中。
- MVC模式
MVC模式是软件工程中的一种常用的软件架构模式,它把软件系统分为3个基础部分:模型(Model)、视图(View)、控制器(Controller)。
模型:用于处理与应用程序业务逻辑相关的数据,以及封装对数据的处理方法。模型有对数据直接访问的权力,例如对数据库的访问。
视图:能够实现数据有目的的显示。在视图中一般没有程序的逻辑。
控制器:起到组织不同层面间的作用,用于控制应用程序的流程。它处理事件并作出响应。事件包括用户的请求处理和与模型的交互。
创建简单的服务器端
(1)创建和解析HTTP服务器端
需要用HandleFunc()函数注册路由,然后通过ListenAndServe()函数开启对客户端的监听。
package main
import "net/http"
func SayHello(w http.ResponseWriter,r *http.Request){
w.Write([]byte("Hello"))
}
func main(){
http.HandleFunc("/hello",SayHello) //注册路由和设置回调函数
http.ListenAndServe("8080",nil) //开启对客户端的监听
}
(2) 内部调用逻辑分析
http.ListenAndServe的第一个参数是端口号,第二个参数是事件处理器handler。
在go语言中handler接口的定义如下:
type Handler interface{
ServeHTTP(ResponseWriter,*Request)
}
也就是说,只要实现这个接口,就可以实现自己的handler处理器Go语言在net/http包中已经提供了实现这个接口的公共方法:
type HandlerFunc func(ResponseWriter *Request)
func (f HandlerFunc) ServeHTTP(w,ResponseWriter,r *Request){
f(w,r)
}
在 Go 语言中,实现 Handler 接口需要定义一个函数,该函数接受一个 http.ResponseWriter 和一个 *http.Request 参数,并返回一个 http.Handler 对象。示例:
package main
import (
"fmt"
"net/http"
)
type MyHandler struct {
// 这里可以定义一些成员变量或者方法
}
func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, world!")
}
func main() {
var h MyHandler
http.ListenAndServe(":8080", &h)
}
上面的示例中,我们定义了一个 MyHandler 结构体,并在其中实现了一个 ServeHTTP 方法。该方法接受一个 http.ResponseWriter 和一个 *http.Request 参数,并返回一个 http.Handler 对象。在方法中,我们简单地输出了一条 “Hello, world!” 的消息。最后,我们在 main 函数中创建了一个 MyHandler 对象,并将其传递给 http.ListenAndServe 函数来启动一个 HTTP 服务器。
创建跳转Web服务器端
package main
import "net/http"
type Refer struct {
handler http.Handler
refer string
}
func (this *Refer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.Referer() == this.refer {
this.handler.ServeHTTP(w, r)
} else {
w.WriteHeader(403)
}
}
func myHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("this is handler"))
}
func hello(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello"))
}
func main() {
referer := &Refer{
handler: http.HandlerFunc(myHandler),
refer: "www.baidu.com",
}
http.HandleFunc("/hello", hello)
http.ListenAndServe(":8080", referer)
}
创建简单客户端
在net/http包中还提供了一个被称为Client的结构体。该结构体位于库文件 src/net/http/client.go 中,并且还提供了一个默认的变量可直接使用:
var DefaultClient = &Client{}
Client结构体实现了Get()、Post()两个请求函数
1、创建GET请求
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main(){
resp,err := http.Get("https://www.baidu.com")
if err!=nil{
fmt.Print("err",err)
}
closer := resp.Body
bytes,err:=ioutil.ReadAll(closer)
fmt.Println(string((bytes)))
}
2、Post请求
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main(){
url := "https://www.shirdon.com/comment/add"
body:="xxxxx"
response,err:=http.Post(url,"xxxx")
if err != nil{
fmt.Println("err",err)
}
b,err := ioutil.ReadAll(respose.Body)
fmt.Println(string(b))
}