前言

我们都知道,go语言的编程方式是duck type,也就是,接口和实现类是完全解耦的,如果一个接口实现了某个接口的方法,则实现了这个接口。这给编程和灵活性带来了极大的可变性和灵活性。

Go中的ServerHTTP

在go语言中如果要开启一个Web服务,则要实现http.Handler提供的ServerHTTP方法
这是Handler接口的源码:

type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

开启一个简单的Http服务:

main(){
	server := http.Server{
		Addr:"localhost:8080",
	}
	server.ListenAndServer()
}
通过实现Handler接口来开启Http服务
package main

import (
	"fmt"
	"net/http"
)

type HelloHandler struct {
}

func (HelloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	_, _ = fmt.Fprintf(w, "hello")
}

type WorldHandler struct {
}

func (WorldHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	_, _ = fmt.Fprintf(w, "world")
}

func main() {
	server := http.Server{
		Addr: "localhost:8080",
	}
	http.Handle("/hello", HelloHandler{})
	http.Handle("/world", WorldHandler{})
	server.ListenAndServe()
}

如上所示,如果需要n个不同的处理器,则需要新建n个结构体,然后实现Handler接口的方法,那我们可以用更加简便的方式:

通过HandlerFunc开启多个服务

http.HandlerFunc的方法签名

type HandlerFunc func(ResponseWriter, *Request)

它对实现ServerHTTP的防范形式参数进行封装,编程了一个类型,但是他还是一个匿名的ServerHTTP方法。
它也实现了ServerHTTP方法:然后再调用它所调用的方法

// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}
package main

import (
	"fmt"
	"net/http"
)
func hello(w http.ResponseWriter,r *http.Request) {
	_, _ = fmt.Fprintf(w, "hello")
}

func world(w http.ResponseWriter,r *http.Request) {
	_, _ = fmt.Fprintf(w, "world")
}

func main() {
	server := http.Server{
		Addr: "localhost:8080",
	}
	http.HandleFunc("/hello", hello)
	http.HandleFunc("/hello", world)
	server.ListenAndServe()
}

这样不用新建好多结构体,直接使用方法来实现,简便了很多

嵌套实现多切面:

在java中AOP思想很出名,因为其可以简便很多代码,其实在go中,也可实现其功能:

使用HandlerFunc来实现串联web服务

package main

import (
	"fmt"
	"net/http"
	"reflect"
	"runtime"
)


func hello( w http.ResponseWriter,r *http.Request) {
	_, _ = fmt.Fprint(w, "Hello")
	fmt.Println("hello")
}

func log(h http.HandlerFunc) http.HandlerFunc {
	return func(writer http.ResponseWriter, request *http.Request) {
		name := runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name()
		fmt.Println("handler func called name:", name)
		h(writer, request)
	}
}

func main() {
	server := http.Server{
		Addr: "localhost:8080",

	}
	http.HandleFunc("/hello",log(hello))
	server.ListenAndServe()
}

使用Handler来实现串联web服务

package main

import (
	"fmt"
	"net/http"
)

type HelloStruct struct {
}

func (HelloStruct) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello")
}
func log1(h http.Handler) http.Handler {
	return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
		fmt.Println("handler func called name:", "hkfhsf")
		h.ServeHTTP(writer, request)
	})
}

func protect(h http.Handler) http.Handler {
	return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
		fmt.Println("protect")
		h.ServeHTTP(writer, request)
	})
}

func main() {
	server := http.Server{
		Addr: "localhost:8080",
	}
	helloStruct := HelloStruct{}
	http.Handle("/meme", protect(log1(helloStruct)))
	server.ListenAndServe()
}