GoWeb——创建简单的服务端和客户端

创建简单的服务端

1、创建HTTP服务端

要创建一个Go语言的HTTP服务器端,需先使用HandleFunc()函数注册路由,然后通过ListenAndServe()函数开启对客户端的监听。

func main() {
	http.HandleFunc("/hello", SayHello)
	http.ListenAndServe(":8080", nil)
}

func SayHello(w http.ResponseWriter, req *http.Request) {
	w.Write([]byte("hello"))
}

内部调用逻辑分析:
这里简要分析一下Go语言net/http包的内部调用逻辑。如果要创建一个Web服务器端,则需要:①调用http.HandleFunc()函数;②调用htp.ListenAndServe()函数。

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)
}

handler处理器的机制类似于Java SpringMVC框架中的Interceptor,是一个拦截器。它发生在http.HandleFunc()函数处理逻辑之前。

ServeHTTP()方法的使用示例:

例如要实现一个功能:在发送HTTP请求时,只有带上指定的refer参数,该请求才能调用成功,否则返回403状态。示例如下。

/*
实现一个功能:在发送HTTP请求时,只有带上指定的refer参数,该请求才能
调用成功,否则返回403状态
*/
func main() {
	referer := &Refer{
		handler: http.HandlerFunc(myHandler),
		refer:   "www.shirdon.com",
	}
	http.HandleFunc("/hello", hello1)
	http.ListenAndServe(":8080", referer)
}

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 hello1(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("hello"))
}
2、创建HTTPS服务端

在Go语言中使用HTTPS的方法很简单,net/http包,中提供了启动HTTPS服务的方法,其定义如下:

func (srv *Server)ListenAndServeTLS(certFile,keyFile string)
error

通过方法可知,只需要两个参数就可以实现HTTPS服务。这两个参数分别是证书文件的路径和私钥文件的路径。要获取这两个文件,通常需要从证书颁发机构获取。虽然有免费的,但还是比较麻烦,通常还需要购买域名及申请流程。

为了简单起见,我们直接使用自己创建的签名证书。注意,这样的证书是不会被浏览器信任的。

Go语言的net/htp包默认支持HTTP2。在1.6以上的版本中,如果使用HTTPS模式启动服务器,则服务器默认使用HTTP2。使用方法如下。

创建一个私钥和一个证书:

在Liux系统中,打开命令行终端输入下面的命令:

openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.crt

该命令将生成两个文件:server.key和server.crt。

/*
创建一个简单的HTTPS服务器端
*/
func main() {
	//启动服务器
	srv := &http.Server{
		Addr:    ":8080",
		Handler: http.HandlerFunc(handle),
	}
	//用TLS启动服务器,因为运行的是HTTP2,所以它必须与TLS一起运行
	log.Printf("Serving on https://0.0.0.0:8080")
	log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key"))
}

func handle(w http.ResponseWriter, r *http.Request) {
	//记录请求协议
	log.Printf("Got connection: %s", r.Proto)
	//想客户端发送一条消息
	w.Write([]byte("hello this is a HTTP 2 message!"))
}

创建简单的客户端

在net/http包中还提供了一个被称为Client的结构体。该结构体位于库文件src/net/http/client.go中,并且还提供了一个默认的变量可直接使用:

var Defaultclient &client(}

Client:结构体实现了Get()、Post()两个请求函数。这两个函数的定义如下:

func Get(url string)(resp *Response,err error)
func Post(url,contentType string,body io.Reader)

查看源码可以发现,net/http包的Get)函数实现如下:

func Get(url string)(resp *Response,err error){
	return Defaultclient.Get (url)
}

在上面的Get()函数中,使用了DefaultClient对象的Get()方法。该Get()方法的具体实现代码如下:

func (c *client)Get(url string)(resp *Response,err error){
	req,err:=NewRequest ("GET",url,nil)
	if err != nil {
		return nil,err
	}
	return c.Do(req)
}

同样,net/http包的Post()函数的具体实现代码如下:

func Post(url string, contentType string, body io.Reader) (resp *Response, err error) {
	return DefaultClient.Post(url, contentType, body)
}

func (c *Client) Post(url string, contentType string, body io.Reader) (resp *Response, err error) {
	req, err := NewRequest("POST", url, body)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Content-Type", contentType)
	return c.Do(req)
}

Get()、Post()函数的本质是,Go程序在底层传递相应的参数去调用NewRequest()函数。所以,在Go语言中创建客户端,最核心的HTTP请求方法就是NewRequest()函数。因为PUT、DELETE方法在Go语言中没有被单独封装,所以只能通过直接调用NewRequest()函数来实现。

GET请求
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))
}
POST请求
func main() {
	url := "https://www.shirdon.com/comment/add"
	body := "{\"userId\":1,\"articleId\":1,\"comment\":\"这是一条评论\"}"
	response, err := http.Post(url, "application/x-www-form-urlencoded", bytes.NewBuffer([]byte(body)))
	if err != nil {
		fmt.Println("err", err)
	}
	b, err := ioutil.ReadAll(response.Body)
	fmt.Println(string(b))
}
PUT请求
func main() {
	url := "https://www.shirdon.com/comment/update"
	payload := strings.NewReader("{\"userId\":1, \"articleId\":1,\"comment\":\"这是一条评论\"}")
	req, _ := http.NewRequest("PUT", url, payload)
	req.Header.Add("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))
}
DELETE请求
func main() {
	url := "https://www.shirdon.com/comment/update"
	payload := strings.NewReader("{\"userId\":1, \"articleId\":1,\"comment\":\"这是一条评论\"}")
	req, _ := http.NewRequest("DELETE", url, payload)
	req.Header.Add("Content-Type", "application/json")
	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))
}
设置请求头
	//请求头设置
	header := http.Header{"token": {"dhfsklsdfdksfddslieccssef3243dlsdc"}}
	header.Add("Accept-Charset", "UTF-8")
	header.Set("Host", "www.shirdon.com")
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值