1 简单的装饰器模式
func decorator(f func(s string)) func(s string) {
return func(s string) {
fmt.Println("Started")
f(s)
fmt.Println("Ended")
}
}
func Hello(s string){
fmt.Printf(s)
}
// 简单的装饰器模式
func main(){
decorator(Hello)("Hello, world!\n")
}
2 简单的装饰器模式(接口化)
type SumFunc func(int64, int64) int64
func getFunctionName(i interface{}) string {
return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}
func timedSumFunc(f SumFunc) SumFunc {
return func(start, end int64) int64 {
defer func(t time.Time) {
fmt.Printf("--- Time Elapsed (%s): %v ---\n", getFunctionName(f), time.Since(t) )
}(time.Now())
return f(start, end)
}
}
func Sum1(start, end int64) int64 {
var sum int64
sum = 0
if start > end {
start, end = end, start
}
for i := start; i <= end; i++ {
sum += i
}
return sum
}
func Sum2(start, end int64) int64 {
if start > end {
start, end = end, start
}
return (end - start + 1) * (end + start) / 2
}
// 简单的装饰器模式(接口化)
func main(){
sum1 := timedSumFunc(Sum1)
sum2 := timedSumFunc(Sum2)
fmt.Printf("%d, %d\n", sum1(-10000, 10000000), sum2(-1000, 1000000))
}
3 嵌套修饰函数 -->pipeline
func WithServerHeader(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Println("------>WithServerHeader()")
w.Header().Set("Server", "HelloServer v0.0.1")
h(w, r)
}
}
func WithAuthCookie(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request){
log.Println("---->WithAuthCookie()")
cookie := &http.Cookie{Name: "Auth", Value: "Pass", Path: "/"}
http.SetCookie(w, cookie)
h(w, r)
}
}
func WithDebugLog(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
log.Println("---->WithDebuglog")
r.ParseForm()
log.Println(r.Form)
log.Println("path", r.URL.Path)
log.Println("scheme", r.URL.Scheme)
log.Println(r.Form["url_long"])
for k,v := range r.Form {
log.Println("key:", k)
log.Println("val:", strings.Join(v, ""))
}
h(w, r)
}
}
func WithBasicAuth(h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r * http.Request) {
log.Println("---> WithBasicAuth()")
cookie, err := r.Cookie("Auth")
if err != nil || cookie.Value != "Pass" {
w.WriteHeader(http.StatusForbidden)
return
}
h(w, r)
}
}
func hello(w http.ResponseWriter, r *http.Request) {
log.Printf("Received Request %s from %s\n", r.URL.Path, r.RemoteAddr)
fmt.Fprintf(w, "Hello, world!" + r.URL.Path)
}
// 嵌套修饰函数
func main() {
http.HandleFunc("/v1/hello", WithServerHeader(WithAuthCookie(hello)))
http.HandleFunc("/v2/hello", WithServerHeader(WithBasicAuth(hello)))
http.HandleFunc("/v3/hello", WithServerHeader(WithBasicAuth(WithDebugLog(hello))))
http.HandleFunc("/v4/hello", WithServerHeader(WithBasicAuth(WithDebugLog(WithAuthCookie(hello)))))
http.HandleFunc("/v5/hello", Handler(hello, WithServerHeader, WithBasicAuth, WithDebugLog))
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServer:", err)
}
}
// 定义接口
type HttpHandlerDecorator func(http.HandlerFunc) http.HandlerFunc
// pipeline
func Handler(h http.HandlerFunc, decors ...HttpHandlerDecorator) http.HandlerFunc {
for i := range decors {
d := decors[len(decors) - i - 1] // 逆序
h = d(h)
}
return h
}
4 小结
- 修饰器模式就是扩展现有的一个函数的功能,让它可以干一些其他的事,或是在现有的函数功能上再附加上一些别的功能。
- 函数式编程下的代码扩展能力-:::::-->函数互相和随意拼装.
- 容易将一些非业务功能的、属于控制类型的代码给抽象出来( for-loop,打日志,函数路由,求函数运行时间之类非业务功能性的代码)