Анонимные функции. Замыкания
В этой главе мы сделаем первую 100% работающую версию нашего приложения!
Напомню, наше приложение должно регистрировать обращения к счетику и выдавать статистику о текущей посещаемости (пока ограничимся счетчиком посетителей).
Напишем структуру у которой будут две функции:
RegisterHit()
- будет регистрировать событиеTotalHits()
- будет возвращать количество зарегистрированных событий
type Datastore struct {
hitCounter int
}
func (ds *Datastore) RegisterHit() {
ds.hitCounter++
}
func (ds *Datastore) TotalHits() int {
return ds.hitCounter
}
Можно положить эту структуру в наш пакет handlers
, создать глобальную переменную
и использовать напрямую в обработчиках. Однако, лучше вынести данный код в отдельный
пакет, вдруг мы захотим использовать его в дальнейшем в другом месте. Например, выводить
колчество обращений в консоль.
Создайте пакет app/datastore
и добавьте туда данную струкуру.
Далее нужно сделать так, чтобы наши обработчики могли использовать данную структуру. Для этого мы воспользуемся механизмом замыканий и анонимными функциями.
Изменим файл handlers/stat.go
следующим образом:
package handlers
import (
"fmt"
"github.com/labstack/echo"
"net/http"
ds "app/datastore"
)
func Stat(ds *ds.Datastore) echo.HandlerFunc {
return func(c echo.Context) error {
return c.String(http.StatusOK, fmt.Sprintf(`{ "total": %d }`, ds.TotalHits()))
}
}
Обратите внимание на импорт пакета ds "app/datastore"
. В PHP мы бы написали
use App\Datastore as ds;
. Теперь мы можем использовать короткую версию ds
для обращению к данным внутри пакета, вместо полной версии datastore
Далее, мы изменили функцию Stat
таким образом, чтобы она возвращала
обработчик http
запроса. Для формирования JSON мы воспользовались
встроенным пактом fmt
который отвечает за форматирование ввода и вывода.
Короче, если бы мы писали на PHP, то код мог бы выглядеть так:
function Stat($ds ds\Datastore) {
return function($c) use ($ds) {
return $c->String(200, sprintf('{ "total": %d }', $ds->TotalHits()));
}
}
Измените файл handlers/counter.go
по аналогии с handlers/stat.go
самостоятельно.
Осталось создать экземпляр нашего datastore в main.go
и передать его в обработчики.
func main() {
ds := datastore.Datastore{}
e := echo.New()
e.GET("/stat.js", handlers.Stat(&ds))
e.GET("/counter.js", handlers.Counter(&ds))
e.Start(":8080")
}
Запустите приложение и откройте http://localhost:8080/counter.js, а затем http://localhost:8080/stat.js. Если вы все сделали правильно, то увидите
{ "total": 1 }
Все, первая версия нашего приложения готова! Однако не надо радоваться, проблем в нем больше чем достаточно. Более того, оно скорее всего упадет при высокой нагрузке. Какие проблемы есть и что можно улучшить расскажу далее.
Код находится в src/anonymous_functions
.