Handle, HandleFunc, HandlerFunc и Handler - как с ними быть?

926 views
Skip to first unread message

Антон Тупов

unread,
Mar 24, 2018, 4:26:04 PM3/24/18
to Golang Russian
Доброго времени суток.

Являюсь полным дном в отношении разработки, как таковой, но на старости лет захотелось что-то резко поменять в жизни. С теорией программирования мало-мальски знаком (последний раз продолжительная "практика" написания кода была около 15 лет назад, в институте на "плюсах"). Мой выбор пал на Go, как на язык с низким порогом вхождения.

С типизацией познакомился на основании информации из стандартного тура, параллельно читал gobyexamples и профильные темы на стэковерфлоу. Начал читать Саммерфилда, но понял, что рановато мне до него :) После решил проголосовать рублем за видеокурсы, и приобрел "Web Development w/ Google’s Go (golang)" на udemy.

В рамках одного из заданий было предложено, цитирую:

Take the previous program and change it so that:
func main uses http.Handle instead of http.HandleFunc
Contstraint: Do not change anything outside of func main

Код мною выполненного задания выглядит так (не думаю, что мой файл с шаблоном здесь принципиален):

package main

import (
"fmt"
"html/template"
"io"
"log"
"net/http"
"os"
)

func root(res http.ResponseWriter, req *http.Request) {
io.WriteString(res, "<H1>You are on the top</H1>")
}

func dog(res http.ResponseWriter, req *http.Request) {
io.WriteString(res, "<H1>Bow-wow!</H1>")
}

func me(res http.ResponseWriter, req *http.Request) {
tpl, err := template.ParseFiles("tpl.gohtml")
if err != nil {
log.Fatalln(err)
}
tpl.Execute(res, "<H1>My name is Slim Shadey!</H1>")
}

func main() {
dir, _ := os.Getwd()
fmt.Println(dir)
mux := http.NewServeMux()
mux.Handle("/", http.HandlerFunc(root))
mux.Handle("/dog/", http.HandlerFunc(dog))
mux.HandleFunc("/me/", me) //намеренно использовал этот метод, чтобы попытаться понять разницу...
http.ListenAndServe(":8080", mux)
}

Правильно, ли я понимаю:

1. Handle в качестве аргументов ожидает URI и обработчик (можно так называть Handler в русском языке?)
2. HandleFunc в качестве аргументов ожидает URI и функцию с сигнатурой вида func(ResponseWriter, *Request) {}
3. HandlerFunc возвращает handler для функции с сигнатурой вида func(ResponseWriter, *Request) {} 

?

4. Есть ли плюсы в использовании Handle перед HandleFunc с учетом того, что синтаксис последней, в целом, выглядит несколько проще? :)

Alex Lurye

unread,
Mar 26, 2018, 2:53:30 AM3/26/18
to gola...@googlegroups.com
Handler - это интерфейс. Любой тип, который реализует его, можно передать в http.Handle (или mux.Handle). От вас хотели чего-то такого:

type myHandler struct {}
func (h *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  ...
}
mux.Handle("/my", &myHandler{})

Достоинство этого подхода, что с каждым экземпляром обработчика можно связать данные - например положить хэндлер базы данных, всякие параметры и т.д.

http.HandleFunc - это тип, который тоже реализует интерфейс http.Handler - посмотрите код:
  1939  // The HandlerFunc type is an adapter to allow the use of
  1940  // ordinary functions as HTTP handlers. If f is a function
  1941  // with the appropriate signature, HandlerFunc(f) is a
  1942  // Handler that calls f.
  1943  type HandlerFunc func(ResponseWriter, *Request)
  1944  
  1945  // ServeHTTP calls f(w, r).
  1946  func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
  1947  	f(w, r)
  1948  }

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+...@googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

Andrey Velikoredchanin

unread,
Mar 26, 2018, 2:55:47 AM3/26/18
to golang-ru
Очень интересно! А в контексте одного хэндлера исполнение разве идет в одной горотине? Или, все-таки, на каждый запрос своя, хоть и с одним объектом Handler?

26 марта 2018 г., 9:53 пользователь 'Alex Lurye' via Golang Russian <gola...@googlegroups.com> написал:
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+unsubscribe@googlegroups.com.

Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+unsubscribe@googlegroups.com.

Alex Lurye

unread,
Mar 26, 2018, 2:57:36 AM3/26/18
to gola...@googlegroups.com
Объект Handler один, а горутины создаются по одной на каждый запрос.

Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+...@googlegroups.com.

Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+...@googlegroups.com.

Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.

--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+...@googlegroups.com.

Антон Тупов

unread,
Mar 29, 2018, 2:49:16 PM3/29/18
to Golang Russian
Большое спасибо за подробный ответ!

понедельник, 26 марта 2018 г., 11:53:30 UTC+5 пользователь Alex Lurye написал:
Reply all
Reply to author
Forward
0 new messages