From 91e01701b59db2d158a53db8a39df9b6800a6cbb Mon Sep 17 00:00:00 2001 From: kasmanavt Date: Fri, 16 Sep 2016 16:19:37 +0300 Subject: [PATCH 1/5] add ru translation for 03.4 --- ru/03.4.md | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 ru/03.4.md diff --git a/ru/03.4.md b/ru/03.4.md new file mode 100644 index 00000000..a346c6d7 --- /dev/null +++ b/ru/03.4.md @@ -0,0 +1,136 @@ +# 3.4 Внутренний мир пакета http + +В предыдущих разделах мы узнали о том, как работает Веб и немного затронули работу с пакетом http. В данном разделе мы изучим две основные функции этого пакета: Conn и ServeMux. + +## Использование горутин в функции Conn + +В отличи от обычных HTTP серверов, Go использует гоурутины при каждом обращении создаваемые функцией Conn. За счет эго обеспечивается высокая производительность и параллельная обработка. + +Go использует следующий код для ожидания новых подключений от клиента: + +c, err := srv.newConn(rw) +if err != nil { +continue +} +go c.serve() + +Как вы видите, горутины создаются для каждого подключения. При этом в горутину передает обработчик, способный читать данные из запросов. + +## Настройка ServeMux + +В предыдущем разделе, когда рассматривали метод conn.server, мы использовали роутер по умолчанию. + +Структура роутера по умолчанию: + +type ServeMux struct { +mu sync.RWMutex // because of concurrency, we have to use mutex here +m map[string]muxEntry // router rules, every string mapping to a handler +} + +Структура muxEntry: + +type muxEntry struct { +explicit bool // exact match or not +h Handler +} + +Интерфейс Handler: + +type Handler interface { +ServeHTTP(ResponseWriter, *Request) // routing implementer +} + +`Handler` - это интерфейс, однако, функция `sayhelloName` не реализует этот интерфейс. Почему, в таком случае, мы смогли использовать ее в качестве обработчика? Потому, что в пакете `http` существует другой тип `HandlerFunc`. В нашем нашем сервере из раздела 3.2 при вызове `HandlerFunc` происходит автоматическое приведение нашей функции `sayhelloName` к интерфейсу `Handler`. Это равносильно вызову `HandlerFunc(f)`, при этом `f` будет принудительно привдена к типу `HandlerFunc`. + +type HandlerFunc func(ResponseWriter, *Request) + +// ServeHTTP вызывает f(w, r). +func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { +f(w, r) +} + +Как маршрутизатор вызывает обработчики после установки правил? + +Маршрутизатор вызывает `mux.handler.ServeHTTP(w, r)` при получении запросов. Другими словами, он вызывает `ServeHTTP` интерфейсы обработчиков. + +Давайте посмотрим как работает `mux.handler`. + +func (mux *ServeMux) handler(r *Request) Handler { +mux.mu.RLock() +defer mux.mu.RUnlock() + +// Host-specific pattern takes precedence over generic ones +h := mux.match(r.Host + r.URL.Path) +if h == nil { +h = mux.match(r.URL.Path) +} +if h == nil { +h = NotFoundHandler() +} +return h +} + +Маршрутизатор использует URL-адрес в качестве ключа для поиска соответствующего обработчика, который сохранен в карте и вызовов handler.ServeHTTP для выполнения функций обработки данных. + +Теперь вы должны понимать принципы работы роутера. Фактически, Go поддерживает настраиваемые роутеры. Второй аргумент функции `ListenAndServe` необходим для конфигурации настраиваемого роутера с типом `Handler`. Таким образом любой роутер реализует интерфейс `Handler`. + +Следующий пример покажет, как реализовать простой роутер. + +package main + +import ( +"fmt" +"net/http" +) + +type MyMux struct { +} + +func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { +if r.URL.Path == "/" { +sayhelloName(w, r) +return +} +http.NotFound(w, r) +return +} + +func sayhelloName(w http.ResponseWriter, r *http.Request) { +fmt.Fprintf(w, "Hello myroute!") +} + +func main() { +mux := &MyMux{} +http.ListenAndServe(":9090", mux) +} + +## Исполнение кода по шагам + +Давайте посмотрим на поток выполнения. + +- Вызывается `http.HandleFunc`. +1. Вызывается HandleFunc из DefaultServeMux. +2. Вызывается Handle из DefaultServeMux. +3. Добавляются правила маршрутизации в карту map[string]muxEntry из DefaultServeMux. +- Вызывается `http.ListenAndServe(":9090", nil)`. +1. Создается экземпляр Server. +2. Вызывается ListenAndServe для Server. +3. Вызывается net.Listen("tcp", addr) для прослушки порта. +4. Запускается бесконечный цикл, в теле которого происходит прием запросов. +5. Создается экземпляр Conn и запускаются горутины для каждого запроса: `go c.serve()`. +6. Читаются данные запроса: `w, err := c.readRequest()`. +7. Проверяется существует ли обработчик и если обработчика нет используется DefaultServeMux. +8. Вызывается ServeHTTP для обработчика. +9. Исполняется код в DefaultServeMux в нашем случае. +10. Выбирается обработчик, соответсвующий URL, и исполняется код обработчика: `mux.handler.ServeHTTP(w, r)` +11. Как выбирается обработчик: +A. Проверяются правила маршрутизации по данному URL. +B. Вызывается ServeHTTP в данном обработчике, если он есть. +C. В противном случае вызывается ServeHTTP для NotFoundHandler. + +## Ссылки + +- [Содержание](preface.md) +- Предыдущий раздел: [Как Go работает с веб](03.3.md) +- Следующий раздел: [Итоги раздела](03.5.md) + From 179ad2b05ddde192508e1bdbeb2ab643d9ef1d7a Mon Sep 17 00:00:00 2001 From: kasmanavt Date: Fri, 16 Sep 2016 17:01:53 +0300 Subject: [PATCH 2/5] some fix for 03.4 --- ru/03.4.md | 273 +++++++++++++++++++++++++++-------------------------- 1 file changed, 137 insertions(+), 136 deletions(-) diff --git a/ru/03.4.md b/ru/03.4.md index a346c6d7..c6fce517 100644 --- a/ru/03.4.md +++ b/ru/03.4.md @@ -1,136 +1,137 @@ -# 3.4 Внутренний мир пакета http - -В предыдущих разделах мы узнали о том, как работает Веб и немного затронули работу с пакетом http. В данном разделе мы изучим две основные функции этого пакета: Conn и ServeMux. - -## Использование горутин в функции Conn - -В отличи от обычных HTTP серверов, Go использует гоурутины при каждом обращении создаваемые функцией Conn. За счет эго обеспечивается высокая производительность и параллельная обработка. - -Go использует следующий код для ожидания новых подключений от клиента: - -c, err := srv.newConn(rw) -if err != nil { -continue -} -go c.serve() - -Как вы видите, горутины создаются для каждого подключения. При этом в горутину передает обработчик, способный читать данные из запросов. - -## Настройка ServeMux - -В предыдущем разделе, когда рассматривали метод conn.server, мы использовали роутер по умолчанию. - -Структура роутера по умолчанию: - -type ServeMux struct { -mu sync.RWMutex // because of concurrency, we have to use mutex here -m map[string]muxEntry // router rules, every string mapping to a handler -} - -Структура muxEntry: - -type muxEntry struct { -explicit bool // exact match or not -h Handler -} - -Интерфейс Handler: - -type Handler interface { -ServeHTTP(ResponseWriter, *Request) // routing implementer -} - -`Handler` - это интерфейс, однако, функция `sayhelloName` не реализует этот интерфейс. Почему, в таком случае, мы смогли использовать ее в качестве обработчика? Потому, что в пакете `http` существует другой тип `HandlerFunc`. В нашем нашем сервере из раздела 3.2 при вызове `HandlerFunc` происходит автоматическое приведение нашей функции `sayhelloName` к интерфейсу `Handler`. Это равносильно вызову `HandlerFunc(f)`, при этом `f` будет принудительно привдена к типу `HandlerFunc`. - -type HandlerFunc func(ResponseWriter, *Request) - -// ServeHTTP вызывает f(w, r). -func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { -f(w, r) -} - -Как маршрутизатор вызывает обработчики после установки правил? - -Маршрутизатор вызывает `mux.handler.ServeHTTP(w, r)` при получении запросов. Другими словами, он вызывает `ServeHTTP` интерфейсы обработчиков. - -Давайте посмотрим как работает `mux.handler`. - -func (mux *ServeMux) handler(r *Request) Handler { -mux.mu.RLock() -defer mux.mu.RUnlock() - -// Host-specific pattern takes precedence over generic ones -h := mux.match(r.Host + r.URL.Path) -if h == nil { -h = mux.match(r.URL.Path) -} -if h == nil { -h = NotFoundHandler() -} -return h -} - -Маршрутизатор использует URL-адрес в качестве ключа для поиска соответствующего обработчика, который сохранен в карте и вызовов handler.ServeHTTP для выполнения функций обработки данных. - -Теперь вы должны понимать принципы работы роутера. Фактически, Go поддерживает настраиваемые роутеры. Второй аргумент функции `ListenAndServe` необходим для конфигурации настраиваемого роутера с типом `Handler`. Таким образом любой роутер реализует интерфейс `Handler`. - -Следующий пример покажет, как реализовать простой роутер. - -package main - -import ( -"fmt" -"net/http" -) - -type MyMux struct { -} - -func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { -if r.URL.Path == "/" { -sayhelloName(w, r) -return -} -http.NotFound(w, r) -return -} - -func sayhelloName(w http.ResponseWriter, r *http.Request) { -fmt.Fprintf(w, "Hello myroute!") -} - -func main() { -mux := &MyMux{} -http.ListenAndServe(":9090", mux) -} - -## Исполнение кода по шагам - -Давайте посмотрим на поток выполнения. - -- Вызывается `http.HandleFunc`. -1. Вызывается HandleFunc из DefaultServeMux. -2. Вызывается Handle из DefaultServeMux. -3. Добавляются правила маршрутизации в карту map[string]muxEntry из DefaultServeMux. -- Вызывается `http.ListenAndServe(":9090", nil)`. -1. Создается экземпляр Server. -2. Вызывается ListenAndServe для Server. -3. Вызывается net.Listen("tcp", addr) для прослушки порта. -4. Запускается бесконечный цикл, в теле которого происходит прием запросов. -5. Создается экземпляр Conn и запускаются горутины для каждого запроса: `go c.serve()`. -6. Читаются данные запроса: `w, err := c.readRequest()`. -7. Проверяется существует ли обработчик и если обработчика нет используется DefaultServeMux. -8. Вызывается ServeHTTP для обработчика. -9. Исполняется код в DefaultServeMux в нашем случае. -10. Выбирается обработчик, соответсвующий URL, и исполняется код обработчика: `mux.handler.ServeHTTP(w, r)` -11. Как выбирается обработчик: -A. Проверяются правила маршрутизации по данному URL. -B. Вызывается ServeHTTP в данном обработчике, если он есть. -C. В противном случае вызывается ServeHTTP для NotFoundHandler. - -## Ссылки - -- [Содержание](preface.md) -- Предыдущий раздел: [Как Go работает с веб](03.3.md) -- Следующий раздел: [Итоги раздела](03.5.md) - +# 3.4 Внутренний мир пакета http + +В предыдущих разделах мы узнали о том, как работает Веб и немного затронули работу с пакетом `http`. В данном разделе мы изучим две основные функции этого пакета: Conn и ServeMux. + +## Использование горутин в функции Conn + +В отличи от обычных HTTP серверов, Go использует гоурутины при каждом обращении к функции Conn. За счет эго обеспечивается высокая производительность и параллельная обработка. + +Go использует следующий код для ожидания новых подключений от клиента: + + c, err := srv.newConn(rw) + if err != nil { + continue + } + go c.serve() + +Как вы видите, горутины создаются для каждого подключения. При этом в горутину передается обработчик, способный читать данные из запросов. + +## Настраиваемые ServeMux + +В предыдущем разделе, при рассмотрении метода conn.server, мы использовали роутер по умолчанию. Основная задача роутера - передать данные запроса конкретному обработчику. + +Структура роутера по умолчанию: + + type ServeMux struct { + mu sync.RWMutex // здесь используются мьютексы для синхронизации параллельных потоков + m map[string]muxEntry // правила маршрутизации, каждая строка ссылается на обработчик + } + +Структура muxEntry: + + type muxEntry struct { + explicit bool // exact match or not + h Handler + } + +Интерфейс Handler: + + type Handler interface { + ServeHTTP(ResponseWriter, *Request) // реализация маршрутизации + } + +`Handler` - это интерфейс, однако, функция `sayhelloName` не реализует этот интерфейс. Почему, в таком случае, мы смогли использовать ее в качестве обработчика? Потому, что в пакете `http` существует другой тип `HandlerFunc`. В нашем нашем сервере из раздела 3.2 при вызове `HandlerFunc` происходит автоматическое приведение нашей функции `sayhelloName` к интерфейсу `Handler`. Это равносильно вызову `HandlerFunc(f)`, при этом `f` будет принудительно приведена к типу `HandlerFunc`. + + type HandlerFunc func(ResponseWriter, *Request) + + // ServeHTTP вызывает f(w, r). + func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { + f(w, r) + } + +Как маршрутизатор вызывает обработчики после установки правил? + +Маршрутизатор вызывает `mux.handler.ServeHTTP(w, r)` при получении запросов. Другими словами, он вызывает `ServeHTTP` интерфейсы обработчиков. + +Давайте посмотрим как работает `mux.handler`. + + func (mux *ServeMux) handler(r *Request) Handler { + mux.mu.RLock() + defer mux.mu.RUnlock() + + // Host-зависимый шаблон, имеет приоритет над универсальным + h := mux.match(r.Host + r.URL.Path) + if h == nil { + h = mux.match(r.URL.Path) + } + if h == nil { + h = NotFoundHandler() + } + return h + } + +Маршрутизатор использует URL-адрес в качестве ключа для поиска соответствующего обработчика, который сохранен в карте и вызовов handler.ServeHTTP для выполнения функций обработки данных. + +Теперь вы должны понимать принципы работы роутера. Фактически, Go поддерживает настраиваемые роутеры. Второй аргумент функции `ListenAndServe` необходим для конфигурации настраиваемого роутера с типом `Handler`. Таким образом любой роутер реализует интерфейс `Handler`. + +Следующий пример покажет, как реализовать простой роутер. + + package main + + import ( + "fmt" + "net/http" + ) + + type MyMux struct { + } + + func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/" { + sayhelloName(w, r) + return + } + http.NotFound(w, r) + return + } + + func sayhelloName(w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, "Hello myroute!") + } + + func main() { + mux := &MyMux{} + http.ListenAndServe(":9090", mux) + } + +## Исполнение кода по шагам + +Давайте посмотрим на поток выполнения. + +- Вызывается `http.HandleFunc`. +1. Вызывается `HandleFunc` из `DefaultServeMux`. +2. Вызывается `Handle` из `DefaultServeMux`. +3. Добавляются правила маршрутизации в карту `map[string]muxEntry` из `DefaultServeMux`. +- Вызывается `http.ListenAndServe(":9090", nil)`. +1. Создается экземпляр `Server`. +2. Вызывается `ListenAndServe` для `Server`. +3. Вызывается `net.Listen("tcp", addr)` для прослушки порта. +4. Запускается бесконечный цикл, в теле которого происходит прием запросов. +5. Создается экземпляр Conn и запускаются горутины для каждого запроса: `go c.serve()`. +6. Читаются данные запроса: `w, err := c.readRequest()`. +7. Проверяется существует ли обработчик и если обработчика нет используется `DefaultServeMux`. +8. Вызывается `ServeHTTP` для обработчика. +9. Исполняется код в `DefaultServeMux` в нашем случае. +10. Выбирается обработчик, соответсвующий URL, и исполняется код обработчика: `mux.handler.ServeHTTP(w, r)` +11. Как выбирается обработчик: +A. Проверяются правила маршрутизации по данному URL. +B. Вызывается `ServeHTTP` в данном обработчике, если он есть. +C. В противном случае вызывается `ServeHTTP` для `NotFoundHandler`. + +## Ссылки + +- [Содержание](preface.md) +- Предыдущий раздел: [Как Go работает с веб](03.3.md) +- Следующий раздел: [Итоги раздела](03.5.md) + + From 3481f373a38f82b5344b343319626a8c3b693d52 Mon Sep 17 00:00:00 2001 From: kasmanavt Date: Fri, 16 Sep 2016 17:15:55 +0300 Subject: [PATCH 3/5] add ru translation for 03.5 --- ru/03.5.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 ru/03.5.md diff --git a/ru/03.5.md b/ru/03.5.md new file mode 100644 index 00000000..1dfdb1e7 --- /dev/null +++ b/ru/03.5.md @@ -0,0 +1,12 @@ +# 3.5 Итоги раздела + +В этой главе мы познакомились с тем как работает HTTP, разрешение имен DNS и как создать простой веб-сервер на языке Go. После этого мы обсудили как Go создает веб-сервер на примере исходных кодов пакета `net/http`. + +Я надеюсь, вы узнали гораздо больше о веб-разработке и поняли, что создавать веб-приложения в Go достаточно легко. + +## Ссылки + +- [Содержание](preface.md) +- Предыдущий раздел: [Внутренний мир пакета http](03.4.md) +- Следующая глава: [Форма пользователя](04.0.md) + From 4a85fe57b2d1b174a85926d758edd598c555cbff Mon Sep 17 00:00:00 2001 From: kasmanavt Date: Fri, 16 Sep 2016 17:22:25 +0300 Subject: [PATCH 4/5] change preface --- ru/preface.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ru/preface.md b/ru/preface.md index c02bc35c..f424ce7c 100644 --- a/ru/preface.md +++ b/ru/preface.md @@ -13,11 +13,11 @@ - 2.6. [Интерфейсы](02.6.md) - 2.7. [Многопоточность](02.7.md) - 2.8. [Итоги раздела](02.8.md) -- 3.[Web foundation](03.0.md) - - 3.1. [Web working principles](03.1.md) - - 3.2. [Build a simple web server](03.2.md) - - 3.3. [How Go works with web](03.3.md) - - 3.4. [Get into http package](03.4.md) +- 3.[Основы Веба](03.0.md) + - 3.1. [Принципы работы веб](03.1.md) + - 3.2. [Создание простого веб-сервера](03.2.md) + - 3.3. [Как Go работает с веб](03.3.md) + - 3.4. [Внутренний мир пакета http](03.4.md) - 3.5. [Итоги раздела](03.5.md) - 4.[Пользовательские формы](04.0.md) - 4.1. [Работа с формами](04.1.md) From 92fd76f2204cea8d449eee236edbfa90ae798583 Mon Sep 17 00:00:00 2001 From: kasmanavt Date: Fri, 16 Sep 2016 17:37:00 +0300 Subject: [PATCH 5/5] fix mistakes --- ru/03.4.md | 34 +++++++++++++++++----------------- ru/03.5.md | 4 ++-- ru/preface.md | 2 +- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/ru/03.4.md b/ru/03.4.md index c6fce517..0deb8985 100644 --- a/ru/03.4.md +++ b/ru/03.4.md @@ -109,24 +109,24 @@ Go использует следующий код для ожидания нов Давайте посмотрим на поток выполнения. - Вызывается `http.HandleFunc`. -1. Вызывается `HandleFunc` из `DefaultServeMux`. -2. Вызывается `Handle` из `DefaultServeMux`. -3. Добавляются правила маршрутизации в карту `map[string]muxEntry` из `DefaultServeMux`. + 1. Вызывается `HandleFunc` из `DefaultServeMux`. + 2. Вызывается `Handle` из `DefaultServeMux`. + 3. Добавляются правила маршрутизации в карту `map[string]muxEntry` из `DefaultServeMux`. - Вызывается `http.ListenAndServe(":9090", nil)`. -1. Создается экземпляр `Server`. -2. Вызывается `ListenAndServe` для `Server`. -3. Вызывается `net.Listen("tcp", addr)` для прослушки порта. -4. Запускается бесконечный цикл, в теле которого происходит прием запросов. -5. Создается экземпляр Conn и запускаются горутины для каждого запроса: `go c.serve()`. -6. Читаются данные запроса: `w, err := c.readRequest()`. -7. Проверяется существует ли обработчик и если обработчика нет используется `DefaultServeMux`. -8. Вызывается `ServeHTTP` для обработчика. -9. Исполняется код в `DefaultServeMux` в нашем случае. -10. Выбирается обработчик, соответсвующий URL, и исполняется код обработчика: `mux.handler.ServeHTTP(w, r)` -11. Как выбирается обработчик: -A. Проверяются правила маршрутизации по данному URL. -B. Вызывается `ServeHTTP` в данном обработчике, если он есть. -C. В противном случае вызывается `ServeHTTP` для `NotFoundHandler`. + 1. Создается экземпляр `Server`. + 2. Вызывается `ListenAndServe` для `Server`. + 3. Вызывается `net.Listen("tcp", addr)` для прослушки порта. + 4. Запускается бесконечный цикл, в теле которого происходит прием запросов. + 5. Создается экземпляр Conn и запускаются горутины для каждого запроса: `go c.serve()`. + 6. Читаются данные запроса: `w, err := c.readRequest()`. + 7. Проверяется существует ли обработчик и если обработчика нет используется `DefaultServeMux`. + 8. Вызывается `ServeHTTP` для обработчика. + 9. Исполняется код в `DefaultServeMux` в нашем случае. + 10. Выбирается обработчик, соответсвующий URL, и исполняется код обработчика: `mux.handler.ServeHTTP(w, r)` + 11. Как выбирается обработчик: + A. Проверяются правила маршрутизации по данному URL. + B. Вызывается `ServeHTTP` в данном обработчике, если он есть. + C. В противном случае вызывается `ServeHTTP` для `NotFoundHandler`. ## Ссылки diff --git a/ru/03.5.md b/ru/03.5.md index 1dfdb1e7..6b5ea9be 100644 --- a/ru/03.5.md +++ b/ru/03.5.md @@ -1,4 +1,4 @@ -# 3.5 Итоги раздела +# 3.5 Итоги главы В этой главе мы познакомились с тем как работает HTTP, разрешение имен DNS и как создать простой веб-сервер на языке Go. После этого мы обсудили как Go создает веб-сервер на примере исходных кодов пакета `net/http`. @@ -8,5 +8,5 @@ - [Содержание](preface.md) - Предыдущий раздел: [Внутренний мир пакета http](03.4.md) -- Следующая глава: [Форма пользователя](04.0.md) +- Следующая глава: [Пользовательские формы](04.0.md) diff --git a/ru/preface.md b/ru/preface.md index f424ce7c..074031e2 100644 --- a/ru/preface.md +++ b/ru/preface.md @@ -26,7 +26,7 @@ - 4.4. [Дублирование отправки](04.4.md) - 4.5. [Загрузка файлов](04.5.md) - 4.6. [Итоги раздела](04.6.md) -- 5.[Database](05.0.md) +- 5.[Базы данных](05.0.md) - 5.1. [database/sql interface](05.1.md) - 5.2. [MySQL](05.2.md) - 5.3. [SQLite](05.3.md)