Golang: Простой веб-сервер

В этой заметке я расскажу, сделать простой веб-сервер на Go, который умеет обрабатывать запросы. Поскольку Go удобно использовать в разных узких местах, то порой удобно это сделать в виде неких внешних сервисов, к которым можно обратиться. Грубо говоря - API.


Простой Hello World в виде веб-сервера

Давайте сделаем простой веб-сервер, который просто нам будет что-нибудь отдавать. Создадим папку C:/GoPath/demo-server и создадим там файл main.go со следующим содержимым:

package main

import (
    "fmt"
    "html"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hi, %q", html.EscapeString(r.URL.Path))
    })

    log.Fatal(http.ListenAndServe(":8080", nil))
}

Перед тем как описать код, что там и к чему, давайте запустим его и проверим следующей командой:

cd C:/GoPath/demo-server
go run main.go
Запуск веб-сервера

Теперь, пока открыто командное окно, мы можем в браузере открыть следующий адрес http://127.0.0.1:8080/.

Результат обращения к вебсерверу.

А теперь как читать данный код. Начинается все с определения пакета. Любая программа Go должна начинаться с определения имени пакета. Название пакета формируем-придумываем самостоятельно:

package main

Далее мы перечисляем пакеты, которые будем использовать в текущей программе. Пакеты могут быть встроенные, внешние и пользовательские. Например в коде ниже мы используем встроенные пакеты для форматирования строк fmt, логирования log, работы с HTML кодом html и клиент-серверные инструменты net/http:

import (
    "fmt"
    "html"
    "log"
    "net/http"
)

Далее идет определение функции main(). Эта функция - входная точка программы, Go автоматически начинает исполнение программы именно с нее.

func main() {
    // Код тут
}

А уже в функции main() идет запуск веб-сервера на порте 8080, который читает любые запросы и отвечает фразой Hi + текущий запрошенный адрес:

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi, %q", html.EscapeString(r.URL.Path))
})

log.Fatal(http.ListenAndServe(":8080", nil))

По-умолчанию все запросы идут на HandleFunc("/" ..., но можно добавить еще один HandleFunc("/second/" ..., тогда при обращении на /second/ будет срабатывать именно этот обработчик, а не первый:

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
    })
	
    http.HandleFunc("/second/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "I am second, %q", html.EscapeString(r.URL.Path))
    })

    log.Fatal(http.ListenAndServe(":8080", nil))
}

Чтобы перезапустить веб-сервер надо закрыть командной окно и снова выполнить:

cd C:/GoPath/demo-server
go run main.go

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