避免在Go Lang中重复使用http.ResponseWriter等

时间:2017-11-04 18:55:15

标签: go

我正在学习Go并开始使用一个小型Web应用程序。

惊人。但我已经掌握了基础知识。

那么,您认为Go Web应用程序的真实文档源是什么?

例如,现在我有15个方法将“http.ResponseWriter”等作为参数(我的意思是重复吨数)。

我想有更好的方法。

但我不想用其他语言(Python,Ruby,Perl等)的精确思维(解决方案)开始编程Go。

不是因为它错了,而是因为它可能(我不知道,这就是重点)是一个错误。

以下是一个例子:

func newStudentHandler(w http.ResponseWriter, r *http.Request) {
    p := studentPage{Title:"New Student"}
    t, _ := template.ParseFiles("new_student.html")
    t.Execute(w, p)
}

func newTeacherHandler(w http.ResponseWriter, r *http.Request) {
    p := teacherPage{Title:"New Teacher"}
    t, _ := template.ParseFiles("new_teacher.html")
    t.Execute(w, p)

}

func newClassHandler(w http.ResponseWriter, r *http.Request) {
    p := classPage{Title:"New Class"}
    t, _ := template.ParseFiles("new_class.html")
    t.Execute(w, p)
}

[]中 吉奥

2 个答案:

答案 0 :(得分:0)

这就是处理程序通常用Go编写的方式,因为它们必须具有特定的签名才能接受您需要能够处理请求的两个参数值。

现在,如果您打算减少打字数量,那么您当然可以解决这个问题。可能有很多方法可以做到这一点,但想到的就是这样。

type H struct {
    w http.ResponseWriter
    r *http.Request
}

type HF func(H)

func (f HF) ServeHTTP(w http.ResponseWriter, r *http.Request) {
        f(H{w:w, r:r})
}

func (h H) newStudent() {
    p := studentPage{Title:"New Student"}
    t, _ := template.ParseFiles("new_student.html")
    t.Execute(h.w, p)
}

func (h H) newTeacher() {
    p := teacherPage{Title:"New Teacher"}
    t, _ := template.ParseFiles("new_teacher.html")
    t.Execute(h.w, p)

}

func (h H) newClass() {
    p := classPage{Title:"New Class"}
    t, _ := template.ParseFiles("new_class.html")
    t.Execute(h.w, p)
}

// ...

http.Handle("/students", HF(H.newStudent))
http.Handle("/teachers", HF(H.newTeacher))
http.Handle("/classes", HF(H.newClass))

就我个人而言,我不建议将处理程序从标准处理程序中更改,因为在执行此操作时可能会失去一些清晰度,例如,其他开发人员在阅读代码和查看非标准处理程序时可能会感到困惑。 / p>

答案 1 :(得分:0)

在这种情况下最好使用 'go:generate'

如果你需要找史密斯。像这样:

package main

import (
    "log"
    "net/http"
)

//go:generate gen/gen.sh

func main() {
    http.HandleFunc("/student", newStudentHandler)
    http.HandleFunc("/teacher", newTeacherHandler)
    http.HandleFunc("/class", newClassHandler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

如果我们在 Golang 中仍然没有模板,你必须自动生成这个函数,所以结构可能是这样的:

├── [ 128]  gen
│   ├── [ 987]  gen.go
│   └── [  63]  gen.sh
├── [  67]  Makefile
└── [ 273]  main.go

哪里 gen.go :

package main

import (
    "fmt"
    "log"
    "os"
    "text/template"
    "time"
)

type HandlerStruct struct {
    Who   string
    Title string
    Html  string
}

const pfx = "generate helpers 'new<T>Handler'"

func main() {
    fmt.Println("...", pfx)
    var (
        lst = []HandlerStruct{
            {"Student", "New Student", "new_student"},
            {"Teacher", "New Teacher", "new_teacher"},
            {"Class", "New Class", "new_Class"},
        }
        tpl = `
//  Code auto generated. DO NOT EDIT.
//  date: ` + time.Now().Format("2006-01-02 15:04:05") + `
//  source: gen/gen.go

package main
{{range $val := .}}
type {{.Who}}Page struct {
    Title string
}
func new{{.Who}}Handler(w http.ResponseWriter, r *http.Request) {
     p := {{.Who}}Page{Title:"{{.Title}}"}
     t, _ := template.ParseFiles("{{.Html}}.html")
     t.Execute(w, p)
}       
{{end}}`
    )

    fl, err := os.Create("helper.go")
    if err != nil {
        log.Fatal(fmt.Errorf("%s: %w", pfx, err))
    }
    defer fl.Close()

    t := template.Must(template.New("tpl").Parse(tpl))
    t.Execute(fl, lst)
}

go.sh :

#!/bin/bash

go run gen/gen.go
goimports -w helper.go

和 Makefile 是:

build: autogenerate
    go build -v -o srv

autogenerate:
    go generate

在这种情况下,只需在 cmd 上输入“make”就足够了,它会生成所有内容:

$make

go generate
... generate helpers 'new<T>Handler'

go build -v -o srv

├── [ 128]  gen
│   ├── [ 987]  gen.go
│   └── [  63]  gen.sh
├── [  67]  Makefile
├── [ 787]  helper.go
├── [ 273]  main.go
└── [7.8M]  srv

附注。这就是自动代码生成的快乐 ))