《golang笔记》第五篇-网络服务端(一)

323 阅读4分钟

web服务毫无疑问是现代信息高速公路的实现者,我们平时的冲浪上网,购买商品,在线学习都是依赖web服务。golang号称实现了一套完善的网络服务,查阅资料时,大家都在说使用golang很容易搭建web服务。其实本人很讨厌在编码过程中说容易简单的词语,因为一切在编码之前的断言都是空谈,因为你不可能想到所有编码细节,就无法准确判断出一个服务的实现是否真的简单。即使golang确实可以使用较少的代码实现一个简单的web服务,但是代码的背后并不简单,你要学习的不是那几行简单的代码,而代码之后的原理才具有真正的价值。

package main

import (
	"fmt"
	"net/http"
	"log"
)

// '/'模式对应的处理函数
func rootHandler(response http.ResponseWriter, request *http.Request) {
	fmt.Fprintf(response, "Pattern is '/', URL is " + request.URL.Path)
}

// '/getResource/'模式对应的处理函数
func resourceHandler(response http.ResponseWriter, request *http.Request) {
	fmt.Fprintf(response, "Pattern is '/getResource/', URL is " + request.URL.Path)
}

func main() {
	// 将pattern注册到对应的处理函数
	http.HandleFunc("/", rootHandler)
	http.HandleFunc("/getResource/", resourceHandler)
	// 监听80端口,开启web服务
	err := http.ListenAndServe(":80", nil)
	if err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

一个简单的web服务只需要一个文件就实现了,该文件中定义了main包,然后定义了两个处理模式的函数,最后是main主函数。什么是处理模式的函数?其实就是告诉web服务,如何从url找到其对应的处理函数。如果读者使用过正则表达式,大概能理解到字符串‘/getResource/haha’可以匹配模式'/getResource/'。同理,‘www.baidu.com/getResource/haha’可以匹配到模式‘/getResource/’,那么该模式对应的处理函数是什么呢?我们是通过以下方式告诉web服务的:

	// 将pattern注册到对应的处理函数
	http.HandleFunc("/", rootHandler)
	http.HandleFunc("/getResource/", resourceHandler)

最后web服务就可以从‘www.baidu.com/getResource/haha’找到resourceHandler函数来处理了。

我们看下main函数中的代码逻辑在表达什么,首先,将pattern注册到对应的处理函数,其次监听80端口,开启web服务,最后,失败了怎么办?失败处理也是编码中非常重要的一环。如果我能保证每一步代码执行都是预期成功的,那代码还不写的飞起,事实上参数检查,错误处理,日志输出都是软件开发中非常重要的环节。我们在编码过程中既在写符合预期的逻辑其实也在写不符合预期时代码该怎么处理。你以为代码bug是什么?代码bug就是异常处理的还不够,想的还不够完善,这是填不完的坑。

读者应该站在软件开发者的角度来阅读源代码,和人之间有了跨越时空的交流,才有真正意义上的学习。如果我是读者,如何阅读main函数这段代码逻辑呢?我们需要站在软件开发者的角度有层次感的阅读源码。在应用程序这一层,我首先通过HandleFunc注册了两个pattern对应的处理函数,这样应用程序就知道如何通过url找到处理函数了。其次,让应用程序监听80端口,然后提供web服务。最后如果失败了,打印日志就退出,其实就是让应用程序告诉程序员,哎呀,监听以及开启web服务失败了,程序员你快看看吧。到此为止,软件开发者想要表达的应用程序层面的逻辑已经完成了。作为一个搬砖的程序员学到这一步就可以了,至少以后复制粘贴快多了。但是这仅仅是软件开发者在应用程序层面的逻辑读者已经掌握了,但是http包层面的逻辑,以及更深入net包层面的逻辑你了解了吗?以后web服务更复杂的需求难道就凭借学到这简单的逻辑就能搞定了吗?当然不可能。如果我是读者,这时候我会发问:

  1. HandleFunc函数在http层面做了什么?怎么就能将pattern和处理函数对应起来了呢?
  2. ListenAndServe函数做了啥?是怎么监听80端口的?web服务怎么开启的?


带着上面的疑问看下一篇文章吧,这一篇文章废话空话太多了,占用了篇幅。