Этой статьей я хочу запустить небольшой цикл пошаговых инструкций, в которых мы рассмотрим основные моменты, необходимые для создания и запуска полноценного сайта на Golang. Не знаю как вам, но мне бы в свое время такие статьи очень упростили процесс обучения. Сам я с трудом собирал эту информацию по крупинкам из книг на английском, статей разных авторов или ответов на всеми любимом stackoferflow.
В этой статье мы создадим и запустим свой сервер, пропишем первые маршруты роутинга и узнаем как возвращать клиенту (часть сайта, с которой работают пользователи) простой текст и данные в формате JSON.
Мы могли бы написать все в одном файле «main.go», но я предлагаю сразу начать создавать структуру нашего проекта. Скажем, она может выглядеть следующим образом:
- Папка «app» — здесь будет храниться исходный код нашего приложения на Golang. Внутри создадим еще две папки: «controller» — для хендлеров, обслуживающих маршруты; «model» — для описания структур и их методов.
- Папка «public» — здесь будут находиться все внешние файлы: html, js, css, изображения и т.д;
- файл «main.go» — основной файл нашего проекта.

В файле main.go размещаем следующий код:
package main
import (
"github.com/julienschmidt/httprouter"
"goSiteProject/app/controller"
"log"
"net/http"
)
func main() {
//создаем и запускаем в работу роутер для обслуживания запросов
r := httprouter.New()
routes(r)
//прикрепляемся к хосту и свободному порту для приема и обслуживания входящих запросов
//вторым параметром передается роутер, который будет работать с запросами
err := http.ListenAndServe("localhost:4444", r)
if err != nil {
log.Fatal(err)
}
}
func routes(r *httprouter.Router) {
//путь к папке со внешними файлами: html, js, css, изображения и т.д.
r.ServeFiles("/public/*filepath", http.Dir("public"))
//что следует выполнять при входящих запросах указанного типа и по указанному адресу
r.GET("/", controller.StartPage)
r.GET("/users", controller.GetUsers)
}
Я предпочитаю использовать роутер от Julien Schmidt. Он очень легковесный, функциональный и простой.
Для обслуживания запросов по первым двум маршрутам («/» и «/users») нам необходимо в папке (или пакете) «controller» создать функции — хендлеры, реализующие соответствующий интерфейс.
Чтобы на стартовой странице выводилось простое текстовое приветствие, создадим файл «pages.go» в нем разместим следующий код:
package controller
import (
"fmt"
"github.com/julienschmidt/httprouter"
"net/http"
)
func StartPage(rw http.ResponseWriter, r *http.Request, p httprouter.Params) {
text := "Приветствую тебя на стартовой странице этого сайта!"
//возвращаем простой текст
fmt.Fprint(rw, text)
}
Функция «StartPage» реализует интерфейс хендлера, который обрабатывает запрос, приходящий по маршруту «/» для запросов типа GET. В нашем случае мы пока просто выводим текстовое сообщение в окно браузера при заходе на данную страницу «localhost:4444» или, чтобы было понятнее, «localhost:4444/».
Прежде чем писать хендлер для маршрута «/users» нам потребуется создать структуру для типа данных «User» и написать функцию, которая будет возвращать нам массив с данными всех пользователей. В пакете «model» создаем файл «user.go» и размещаем там следующий код:
package model
type User struct {
Id int
Name string
Surname string
}
func GetAllUsers () (users []User, err error) {
users = []User{
{1,"Джон","До"},
{2,"Говард","Рорк"},
{3,"Джек","Доусон"},
{4,"Лизель","Мемингер"},
{5,"Джейн","Эйр"},
{6,"Мартин","Иден"},
{7,"Джон","Голт"},
{8,"Сэмвелл","Тарли"},
{9,"Гермиона","Грейнджер"},
}
return
}
Разбирать вопрос подключения к СУБД мы будем в следующих частях данной статьи, поэтому пока мы заполнили массив возвращаемых данных (список пользователей) вручную. Ошибок на текущий момент здесь не может быть, поэтому пока просто объявляем переменную «err» в списке возвращаемых значений и возвращаем ее в значении по умолчанию (nil) вместе с массивом пользователей «users»
Теперь создадим файл «users.go» и в нем разместим хендлер для маршрута «/users» :
package controller
import (
"encoding/json"
"github.com/julienschmidt/httprouter"
"goSiteProject/app/model"
"net/http"
)
func GetUsers(rw http.ResponseWriter, r *http.Request, p httprouter.Params) {
//получаем список всех пользователей
users, err := model.GetAllUsers()
if err != nil {
http.Error(rw, err.Error(), 400)
return
}
//возвращаем список клиенту в формате JSON
err = json.NewEncoder(rw).Encode(users)
if err != nil {
http.Error(rw, err.Error(), 400)
return
}
}
Получив массив с данными, мы преобразуем их в JSON одной простой функцией и возвращаем клиенту. В случае возникновения ошибки, мы возвращаем ее текст со статусом ответа «400» — «Bad Request».
Запускаем сервер командой в консоли «go run main.go».
Проверяем маршрут «/»:

И маршрут «/users»:

Как видим, все работает так, как мы запланировали. В следующей части мы рассмотрим как выводить статические и генерировать динамические HTML страницы.