Передача параметров метода для интерфейса только один раз? - PullRequest
0 голосов
/ 09 июня 2018

Я пытаюсь найти способ сделать мой код короче и проще, просто вызвав параметры для методов интерфейса только один раз в родительской структуре (?)

Сначала определим маршрут:

func Init() {
    // Create route
    r := mux.NewRouter()

    // Default routes
    router.Route("/", webtest.TestController{}, r)

    // Serve the routes
    router.Serve(r)
}

Тогда функции для него:

type Controller struct {
    ControllerInterface
}

type ControllerInterface interface {
    Get(w http.ResponseWriter, r *http.Request)
}

func Route(path string, ct interface{}, r *mux.Router) {
    if c, ok := ct.(controllers.ControllerInterface); ok {
        r.HandleFunc(path, http.HandlerFunc(c.Get)).Methods("GET")
    }
}

Затем я называю маршрут с

type TestController struct {
    controllers.Controller
}

func (c TestController) Get(w http.ResponseWriter, r *http.Request) {
    println("Hello World")
}

Как вы можете видеть, я должен иметь w http.ResponseWriter, r *http.Request везде, илимаршруты не будут работать.Можно ли как-то включить эти параметры в родительскую структуру (или аналогичную), чтобы мне не приходилось включать их каждый раз?

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

К сожалению, я не думаю, что найдется ответ, которым вы довольны.В конце дня должно быть верно следующее:

Каждый обработчик должен использовать http.Responsewriter и *http.Request для обслуживания запроса.

Следует помнить, что корочеи проще не всегда идут рука об руку.Передача автора и ответ на функции, которые в них нуждаются, хотя и немного многословны, чрезвычайно просты.

Что может сделать вас счастливее, так это вместо этого подтолкнуть большую часть логики фактически к некоторым дополнительным методам, которые имеют дело с семантикой операций, а не с уровнем сетевых запросов.Используя GET-запрос для загрузки записи в качестве примера, вы могли бы вместо этого структурировать ее следующим образом:

func main() {
    http.DefaultServeMux.HandleFunc("/", getHandler)

    if err := http.ListenAndServe(":8080", nil); err != nil {
        panic(err)
    }
}

func getHandler(w http.ResponseWriter, r *http.Request) {
    // Do stuff with the request, like deserialize
    // Extract the ID
    // Call getLogic
    // return an appropriate error or serialize the response back out
}

func getLogic(recordID int) (Record, error) {
    // Do actual interesting logic here.
}

Разделение на части так, как это не без потенциальных затрат в простоте.Хотя он позволяет вам тестировать куски вашей логики без необходимости иметь дело с http.ResponseWriter или http.Request, теперь вы должны принять решение, где разрезать этот шов.Постоянно делать это может быть неловко.

Вы также можете попытаться использовать другие подходы, такие как создание структуры для каждого запроса, наложение автора и запроса на него, а затем вызывать соответствующий метод, но я бы не рекомендовалэто:

func getHandler(w http.ResponseWriter, r *http.Request) {
    SingleRequest{w, r}.Get()
}

type SingleRequest struct {
    writer  http.ResponseWriter
    request *http.Request
}

func (s SingleRequest) Get() {
    // Do logic here, but the method still has to access s.writer and s.request
}

Ни один из этих подходов не предлагает много с точки зрения простоты краткости.Какая незначительная краткость, которую они действительно дают, на мой взгляд, за счет простоты.Первый подход, однако, может быть разумным в зависимости от сложности данного обработчика.В конце концов, это расширение шаблона создания меньших функций для разбиения большей функции.

В настоящее время я не знаю ни одного подхода, который повсеместно увеличивает простоту при уменьшении размера кода.Вместо этого мы должны сосредоточиться на том, почему вы чувствуете, что это проблема, которую нужно решить в первую очередь.Вы знакомы с пакетом httptest в стандартной библиотеке lib?Если вас интересует тестирование, это поможет вам протестировать эти обработчики.

0 голосов
/ 09 июня 2018

Просто переместите биты, которые вы вызываете в Init, в свою основную функцию.Init вызывается при запуске, и все созданное в нем может исчезнуть при выходе из Init.

func main(){
    r := mux.NewRouter()

    // Default routes
    router.Route("/", webtest.TestController{}, r)

    // Serve the routes
    router.Serve(r)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...