Создание базового RESTful (CRUD) с помощью Golang и MySQL
Мы будем разрабатывать приложение, которое предоставляет базовый сервер REST-API для операций CRUD для управления пользователями (id, firstName, lastName, age).
Настройка приложения
Начнем с создания нашей корневой папки
mkdir rest-go-demo && cd rest-go-demo
Это создаст папку с именем «rest-go-demo».
Теперь давайте начнем с инициализации и добавления go-модулей, необходимых для нашего приложения.
go mod init
go get github.com/gorilla/mux
go get github.com/jinzhu/gorm
go get github.com/go-sql-driver/mysql
Мы будем использовать управление зависимостями, представленное Golang в виде их-модулей.
«Go mod init» используется для инициализации корневого приложения, а зависимости можно отслеживать с помощью go.mod, созданного после выполнения вышеуказанной команды.
Нам понадобятся определенные пакеты, чтобы помочь в нашем путешествии:
1. gorilla/mux
Для создания маршрутов и обработчиков HTTP для наших конечных точек
2. jinzhu/gorm
Инструмент ORM для MySQL.
3. go-sql-driver/mysql
драйвер MYSQL.
Настройка MySQL
Давайте начнем с создания базы данных, соответствующей нашим потребностям.
CREATE DATABASE learning;
Давайте создадим структуру для управления конфигурацией нашей базы данных, которая будет использоваться для создания соединения с базой данных.
package database
import "fmt"
//Config to maintain DB configuration properties
type Config struct {
ServerName string
User string
Password string
DB string
}
var getConnectionString = func(config Config) string {
connectionString := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&collation=utf8mb4_unicode_ci&parseTime=true&multiStatements=true", config.User, config.Password, config.ServerName, config.DB)
return connectionString
}
Теперь давайте создадим клиента для управления и создания подключений к нашей базе данных.
package database
import (
"log"
"github.com/jinzhu/gorm"
)
//Connector variable used for CRUD operation's
var Connector *gorm.DB
//Connect creates MySQL connection
func Connect(connectionString string) error {
var err error
Connector, err = gorm.Open("mysql", connectionString)
if err != nil {
return err
}
log.Println("Connection was successful!!")
return nil
}
Давайте проверим, может ли наш клиент подключиться к нашей базе данных или нет!!
package main
import (
"rest-go-demo/database"
_ "github.com/jinzhu/gorm/dialects/mysql" //Required for MySQL dialect
)
func main() {
config :=
database.Config{
ServerName: "localhost:3306",
User: "root",
Password: "root",
DB: "learning",
}
connectionString := database.GetConnectionString(config)
err := database.Connect(connectionString)
if err != nil {
panic(err.Error())
}
}
$ go run main.go
2021/02/14 16:56:34 Connection was successful!!
Теперь давайте создадим нашу простую структуру Person
, которая будет нашей моделью.
type Person struct {
ID string `json:"id"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
Age string `json:"age"`
}
Создаем простой HTTP-сервер с gorilla/mux
Мы будем использовать gorilla/mux
для создания простого сервера для обработки наших HTTP-запросов.
package main
import (
"log"
"net/http"
"github.com/gorilla/mux"
)
func main() {
log.Println("Starting the HTTP server on port 8090")
router := mux.NewRouter().StrictSlash(true)
log.Fatal(http.ListenAndServe(":8090", router))
}
HTTP-сервер, работающий на порту 8090, будет запущен для нашего использования.
Теперь давайте добавим нашу конечную точку REST и продолжим наше путешествие.
POST/CREATE
Мы начнем с добавления маршрута /create/
к нашему маршрутизатору для обслуживания конечной точки, которая будет создавать нового человека при каждом запуске.
router.HandleFunc("/create",createPerson).Methods("POST")
Давайте создадим соответствующую функцию createPerson(), которая будет принимать данные POST-запроса и создавать новую запись о человеке в БД.
Мы сделаем то же самое, сначала распаковав данные JSON, полученные из тела, в нашу структуру Person, созданную выше, а затем вставим данные, создав новую запись.
func createPerson(w http.ResponseWriter, r *http.Request) {
requestBody, _ := ioutil.ReadAll(r.Body)
var person entity.Person
json.Unmarshal(requestBody, &person)
database.Connector.Create(person)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(person)
}
GET/SELECT
Аналогично, тому как мы добавили обработчик и соответствующую функцию для POST, мы добавим /get/{id}
к нашему маршрутизатору для получения данных
router.HandleFunc("/get/{id}", getPersonByID).Methods("GET")
Давайте добавим соответствующую функцию getPersonByID(), которая будет использовать параметр запроса «id» для получения соответствующих данных и возврата ответа JSON.
Здесь мы бы отменили процедуру, которую мы выполняли при создании конечной точки POST, мы будем маршалировать структуру человека, полученную из базы данных, в JSON и создать HTTP-ответ.
func getPersonByID(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
key := vars["id"]
var person entity.Person
database.Connector.First(&person, key)
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(person)
}
PUT/UPDATE
Теперь я могу предположить, что вы уже догадались, что будет дальше с нашим маршрутизатором и соответствующими функциями.
router.HandleFunc("/update/{id}", updatePersonByID).Methods("PUT")
updatePersonByID()
примет данные POST-запроса, распакует JSON в структуру person и обновит соответственно
func updatePersonByID(w http.ResponseWriter, r *http.Request) {
requestBody, _ := ioutil.ReadAll(r.Body)
var person entity.Person
json.Unmarshal(requestBody, &person)
database.Connector.Save(&person)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(person)
}
DELETE/DELETE
router.HandleFunc("/delete/{id}", deletPersonByID).Methods("DELETE")
deletePersonByID()
удалит «id», переданный в параметре запроса, и удалит соответствующую запись из базы данных.
func deletPersonByID(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
key := vars["id"]
var person entity.Person
id, _ := strconv.ParseInt(key, 10, 64)
database.Connector.Where("id = ?", id).Delete(&person)
w.WriteHeader(http.StatusNoContent)
}
Теперь, когда все наши конечные точки на месте, давайте объединим их все и протестируем наши CRUD операции.
Мы сделаем это, выполнив следующие команды
go mod tidy
go build
./rest-go-demo
Создание человека
Получение по ID
Обновление данных
Удаление