【golang】对net包中http的简单理解及使用

写在前面

博主很早之前就接触过net包,使用过里面的方法来进行前后端的一个交互。
当时,对于这一块知识是一点都不理解。也不明白为什么HandFunc后面加个函数就可以处理请求了。

时隔多日,博主终于再次捡起昔日的“科研精神”,直面自己内心的恐惧,对net/http进行基础的学习,也算是小于收获。写下此文,希望能给各位带来一定的帮助。

1.看图

首先给大家画一幅图…,如下
图图
通过这张图,我们大致能看到Client和Sever通过http通信的过程,博主在这里简单描述一下:

1.客户端发送请求,通过多路复用器选择到对应的处理器
2.处理器和数据库交互,处理用户的请求
3.处理完毕后,需要通过模板引擎选择对应的模板,将数据渲染到模板上
4.并最终在用户界面上显示。

2.看例子
// 处理器
func sayHandler(w http.ResponseWriter, r *http.Request)  {
	fmt.Fprintf(w,"hello")
}

func main()  {
	// HandleFunc注册路径处理函数:在根路由上注册了sayHandler这个处理器
	http.HandleFunc("/say",sayHandler)
	e := http.ListenAndServe(":8080",nil)
	if e != nil {
		fmt.Println(e)
	}
}

上述例子中,sayHandler就是一个处理器。所以说,处理器的功能就是用来处理用户的请求。

接着我们来看http.ResponseWriter这个参数

http.ResponseWriter 是一个接口类型

源码:

大家根据他的英文意思猜测一下,也能明白个七七八八。改类型是用来响应客户端的请求的。也就是向服务端对客户端的响应,发送到客户端。

下面我们来看ListenAndServe:

e := http.ListenAndServe(":8080",nil)

大家一定能想到该方法的第一参数是要服务端要监听的端口。那么第二个参数是什么,为什么这里写的是nil?

大家结合上面的图,我们已经了解了处理器、响应接口,那么聪明的你一定能想到,这第二个参数就是没有涉及到的复用器了。这里传入nil,表示使用
默认的多路复用器DefalutServeMux.

说了半天复用器,那它到底是个啥,起到什么作用?

复用器是一种特殊的处理器,它的作用是将用户的请求送到处理改请求的对应的处理器中。

不然,你想想,我们每天登录网站,进行一些操作。如果乱搭配处理器,那么整个功能不就乱套了。

那你说,我不想用默认的复用器,我自己造一个行不行?这必须行啊。

看代码:


type SayHello struct {
	Name string
}

type SayNo struct {
	Name string
}

// 创建一个处理器,实现ServerHTTP方法

func (s *SayHello) ServeHTTP(w http.ResponseWriter, r *http.Request)  {
	w.Write([]byte("hello world"+s.Name))
}

func (s *SayNo) ServeHTTP(w http.ResponseWriter, r *http.Request)  {
	w.Write([]byte("hello world"+s.Name))
}
func main()  {
	// 创建一个多路复用器
	sm := http.NewServeMux()
	// 绑定相应的路由
	sm.Handle("/hello",&SayHello{Name:"王小明"})
	sm.Handle("/no",&SayNo{Name:"no"})
	// 使用多路复用器
	e := http.ListenAndServe("127.0.0.1:8080",sm)
	if e != nil {
		fmt.Println(e)
	}
}

上面代码中,大家可能看到了创建一个处理器,实现ServerHTTP方法这句话,那这又是什么意思呢,接着往下看吧。

1.首先我们去看下Hanlder处理器源码
在这里插入图片描述
看我们发现了什么,处理器是一个接口类型。也就是只要是实现了ServeHTTP方法的类型,都是一个处理器。

现在明白为什么要这样写了吧。

但是,每次都要实现serveHTTP方法,感觉好麻烦啊,有没有更简洁的写法,别慌,真有,看这里

// 处理器
func sayHandler(w http.ResponseWriter, r *http.Request)  {
	fmt.Fprintf(w,"hello")
}

func main()  {
	// HandleFunc注册路径处理函数:在根路由上注册了sayHandler这个处理器
	http.HandleFunc("/say",sayHandler)
	e := http.ListenAndServe(":8080",nil)
	if e != nil {
		fmt.Println(e)
	}
}

细心的你一定发现,这是刚开始的例子。**这里我们只是写了一个函数,**注册的时候换成HandleFunc就可以实现和之前例子的相同的功能。

这时候,好奇的你又该问了,这又是为什么啊?

让我们进一步探索,来到HandleFunc的源码处

可以看到传入了一个处理器类型的函数
在这里插入图片描述

继续挖掘,最终来到了这里
在这里插入图片描述
看我们发现了什么,handlerFunc(不是handleFunc注意啊),也是一个处理器,只不过是函数类型的处理器。

到这里算是真相大白了,也就是说go在底层为我们做了一层封装,当我们传入一个函数类型的时候,它在底层也实现了ServeHTTP方法。所以也是一个处理器。

所以说如果你想简单的实现的话,可以使用HandleFunc进行注册处理器。
不然的话,就使用Handle吧。

插一句:
hanlder和handlerFunc是处理器
handle和handlefunc是注册函数…

不要搞混…(虽然博主曾经搞混过…笑)

说了这么多,咱们来看看http中一些常用的方法

http.Get()
http.Post()

想必大家都不陌生。发送请求嘛…

下面写个例子,练练手

Client端:

apiUrl := "http://127.0.0.1:8080/receive"
	// url.Values里面是键值对
	data := url.Values{}

	var name string
	var content string
	fmt.Println("请输入发送的内容")
	// 读取标准流输入
	fmt.Scanln(&name,&content)
//	fmt.Println(name,content)

	// 设置要发送的数据
	data.Set("send_name",name)
	data.Set("content",content)


	// 将原始url字符串传换成url对象
	u,err := url.ParseRequestURI(apiUrl)
	if err != nil {
		fmt.Println("路径转换出错")
	}
	// 将data数据进行编码,并添加到url对象
	u.RawQuery = data.Encode()
	// 将url路径转换成字符串发送请求
	response,err := http.Get(u.String())
	if err != nil{
		fmt.Println("发送失败")
	}

	defer response.Body.Close()
	
	// 读取服务端响应的数据
		b,err := ioutil.ReadAll(response.Body)
		if err != nil{
			fmt.Println("获取数据失败")
    	}
		fmt.Println(string(b))
		
	}

Server端:

// get请求
func receiveGetHandler(w http.ResponseWriter, r *http.Request)  {
	defer r.Body.Close()
	// 获取路径中的数据
	// 测试用...可以写上
	// data := r.URL.Query()
	// fmt.Println(data.Get("send_name"))
	// fmt.Println(data.Get("content"))
	answer := `{"status":"ok"}`
	// 写入响应内容
	w.Write([]byte(answer))

}
func main()  {
	server := &http.Server{
		Addr: "127.0.0.1:8080",
		Handler: nil,
	}
	http.HandleFunc("/receive",receiveGetHandler)
	// 已经构造过地址和处理器了,不用在ListenAndServe中在写了啦
	e := server.ListenAndServe()
	if e != nil {
		fmt.Println("连接服务器失败")
	}
}

结果:
在这里插入图片描述

好了,码字不易,希望大家多多提出自己宝贵的意见!!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值