# Server 的抽象

了解了golang中http包的基础使用后,我们是否可以直接使用它http来构建我们的web服务器?答案是可以的,但是会有一些问题:

  • 面对复杂业务的时候,我们的代码的意图将会比较混乱,可能就像是面向过程编写的代码。
  • 存在大量重复代码,比如,在读取body并解析到结构体的代码err的重复处理,大量的判断代码
  • 缺少生命周期的管理,比如服务注册、拦截器等功能

# 最简单的web服务

package main

import (
	"fmt"
	"net/http"
)

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

func main(){
	http.HandleFunc("/hello", Hello)
	http.ListenAndServe(":8080", nil)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

启动main函数,访问localhost:8080/hello如下所示:

# Server接口抽象

从基础的web服务器代码来看,我们所需要的web服务,也需要有两种功能,一种是注册路由,一种是监听端口并启动服务。

由于我们想直接使用底层的http来搭建我们的server,那么我们注册的路由,需要与http包中的一致,我们可以定义出如下接口:

type Server interface {
	Route(pattern string, f http.HandlerFunc)
	Start(port string) error
}
1
2
3
4

采用底层的http包实现我们的接口

type sdkHttpServer struct {

}

func (s sdkHttpServer) Route(pattern string, handleFunc http.HandlerFunc) {
	http.HandleFunc(pattern, handleFunc)
}

func (s sdkHttpServer) Start(port string) error {
	return http.ListenAndServe(port, nil)
}
1
2
3
4
5
6
7
8
9
10
11

可以采用如下获取Server实例的方式,来获取不同实现的Server

func NewSdkHttpServer() Server {
	return &sdkHttpServer{}
}

type Factory func() Server

var factory Factory

func RegisterFactory(f Factory) {
	factory = f
}

func NewServer() Server {
	return factory()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

启动服务

func main() {
	RegisterFactory(NewSdkHttpServer)
	server := NewServer()
	hello := func(w http.ResponseWriter,r *http.Request) { // http.HandlerFunc 的类型
		fmt.Fprintf(w, "hello")
	}
	server.Route("/hello", hello)
	server.Start(":8080")
}
1
2
3
4
5
6
7
8
9
上次更新: 10/9/2023,