# 4.01 课后复习-Server

本节课工程结构:

```
(base) yanglei@yuanhong v4-rc % tree ./
./

0 directories, 0 files
```

## PART1. Server

### 1.1 接口定义

`serverInterface.go`:

```go
package v4_rc

import "net/http"

// ServerInterface 服务器实体接口
// 用于定义服务器实体的行为
type ServerInterface interface {
	// Handler 组合http.Handler接口
	http.Handler
	// Start 启动服务器
	Start(addr string) error
}
```

这里组合`http.Handler`,是为了最终调用`http.Serve()`,使得该方法的第2个参数是我们自己实现的`http.Handler`接口的实现.这一点我当时整理笔记时其实是不理解的,我复习时也发现我解释不清楚这件事.故补充.

### 1.2 实现接口的`Start()`方法

#### 1.2.1 实现`Start()`方法

`server.go`:

```go
package v4_rc

import (
	"net"
	"net/http"
)

type Server struct {
}

// ServeHTTP 是http.Handler接口的方法 此处必须先写个实现 不然Server不是http.Handler接口的实现
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	panic("implement me")
}

// Start 启动服务器
func (s *Server) Start(addr string) error {
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}

	return http.Serve(listener, s)
}
```

在`net.Listen()`和`http.Serve()`之间做框架的操作,例如生命周期回调.

#### 1.2.2 测试

`server_test.go`:

```go
package v4_rc

import (
	"testing"
)

// TestServer_Start 测试服务器启动
func TestServer_Start(t *testing.T) {
	s := &Server{}
	err := s.Start(":8081")
	if err != nil {
		t.Fatal(err)
	}
}
```

### 1.3 定义注册路由的方法`addRoute()`

#### 1.3.1 定义`Context`

`context.go`:

```go
package v4_rc

type Context struct {
}
```

这里其实是为了定义`HandleFunc`,而定义`HandleFunc`是为了定义`AddRoute()`.

#### 1.3.2 定义`HandleFunc`

`handle_func.go`

```go
package v4_rc

type HandleFunc func(ctx *Context)
```

#### 1.3.3 在接口上定义`addRoute()`

`server_interface.go`:

```go
package v4_rc

import "net/http"

// ServerInterface 服务器实体接口
// 用于定义服务器实体的行为
type ServerInterface interface {
	// Handler 组合http.Handler接口
	http.Handler
	// Start 启动服务器
	Start(addr string) error

	// addRoute 注册路由
	addRoute(method string, pattern string, handler HandleFunc)
}
```

#### 1.3.4 在实现上定义`addRoute()`

`server.go`:

```go
package v4_rc

import (
	"net"
	"net/http"
)

type Server struct {
}

// ServeHTTP 是http.Handler接口的方法 此处必须先写个实现 不然Server不是http.Handler接口的实现
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	panic("implement me")
}

// Start 启动服务器
func (s *Server) Start(addr string) error {
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}

	return http.Serve(listener, s)
}

// addRoute 注册路由
func (s *Server) addRoute(method string, pattern string, handler HandleFunc) {
	panic("implement me")
}
```

#### 1.3.5 定义`addRoute()`的衍生方法

或者也可以说是暴露给使用者的方法

`server.go`:

```go
package v4_rc

import (
	"net"
	"net/http"
)

type Server struct {
}

// ServeHTTP 是http.Handler接口的方法 此处必须先写个实现 不然Server不是http.Handler接口的实现
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	panic("implement me")
}

// Start 启动服务器
func (s *Server) Start(addr string) error {
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}

	return http.Serve(listener, s)
}

// addRoute 注册路由
func (s *Server) addRoute(method string, pattern string, handler HandleFunc) {
	panic("implement me")
}

// GET 注册GET路由
func (s *Server) GET(path string, handler HandleFunc) {
	s.addRoute(http.MethodGet, path, handler)
}

// POST 注册POST路由
func (s *Server) POST(path string, handler HandleFunc) {
	s.addRoute(http.MethodPost, path, handler)
}
```

## PART2. 完成Server时的工程结构

```
(base) yanglei@yuanhong v4-rc % tree ./
./
├── context.go
├── handle_func.go
├── server.go
├── server_interface.go
└── server_test.go

0 directories, 5 files
```

## 附录

### 1. 可以魔改的点

* 将addr作为Server的一个成员属性
* 我看原生的`http.Server`结构体为了支持HTTPS,组合了一个`*tls.Config`,可以尝试
