Этой статьей я хочу запустить небольшой цикл пошаговых инструкций, в которых мы рассмотрим основные моменты, необходимые для создания и запуска полноценного сайта на 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 страницы.
Спасибо большое! Всё доступно и понятно! Продолжаю чтение и изучение)
Спасибо за фидбек!)
Спасибо огромное, для начинающих отличная инфа!! У меня есть сервер хамрр и скрипты php, хочу это дело перевести на го. Задача такая- выборка из бд на основе запросов клиентского приложения, сложный поиск по многим параметрам с расчетами и вычислениями, но базу хочу одну, не обязательно реляционную, главное скорость. Можете что нибудь посоветовать?
Алекс, спасибо за отзыв!
Golang отлично работает со всеми известными популярными СУБД. Я сам, к сожалению, работал только с реляционными, поэтому могу подсказать что-то только по ним. Да и то, в своих задачах разницы в скорости между MySQL и PostgreSQL не заметил. MySQL проще на мой взгляд, PostgreSQL чаще всего используют в связке с go.