Pourquoi Déployer Go sur Railway ?
Au quotidien, les développeurs cherchent des solutions simples et rapides pour déployer leurs applications. Lorsqu'il s'agit d'applications Go, la plateforme Railway est une solution idéale. Elle offre une expérience de déploiement intuitive avec un processus minimaliste. Un cas d'utilisation concret est la création d'une petite API RESTful qui permet de gérer des tâches simplement.
Prerequis
- Connaissances en Go
- Un compte Railway
- Un environnement local avec Docker et Git installés
Concepts fondamentaux
1. Création d'un projet Go sur Railway
Pour créer un nouveau projet Go, il faut utiliser l'interface web de Railway. En cliquant sur "New Project", choisir le type de projet (ici "Go") et suivre les instructions pour connecter votre dépôt Git.
// ❌ Mauvais : Projet non créé
2. Structure d'un projet Go
Un projet Go typique a une structure simple :
myapp/
├── cmd/
│ └── app/
│ └── main.go
├── internal/
│ ├── handlers/
│ │ └── task_handler.go
│ └── services/
│ └── task_service.go
├── pkg/
│ └── models/
│ └── task.go
└── go.mod
3. Configuration de Railway
Pour configurer Railway, vous devez créer un fichier .railway/manifest.yml :
## ❌ Mauvais : Fichier manifest.yaml incorrect
Mise en pratique : projet fil rouge
Nous allons créer une application simple qui permet d'ajouter et de lister des tâches.
Étape 1 : Création du modèle task.go
Dans le dossier pkg/models/task.go :
package models
type Task struct {
ID int `json:"id"`
Name string `json:"name"`
Done bool `json:"done"`
}
Étape 2 : Création du service task_service.go
Dans le dossier internal/services/task_service.go :
package services
import (
"context"
"errors"
"myapp/pkg/models"
)
type TaskService struct {
tasks []models.Task
}
func NewTaskService() *TaskService {
return &TaskService{
tasks: make([]models.Task, 0),
}
}
func (s *TaskService) Create(ctx context.Context, task models.Task) error {
s.tasks = append(s.tasks, task)
return nil
}
func (s *TaskService) List(ctx context.Context) ([]models.Task, error) {
return s.tasks, nil
}
Étape 3 : Création du handler task_handler.go
Dans le dossier internal/handlers/task_handler.go :
package handlers
import (
"context"
"encoding/json"
"net/http"
"github.com/gorilla/mux"
"myapp/internal/services"
)
type TaskHandler struct {
taskService *services.TaskService
}
func NewTaskHandler(taskService *services.TaskService) *TaskHandler {
return &TaskHandler{
taskService: taskService,
}
}
func (h *TaskHandler) Create(w http.ResponseWriter, r *http.Request) {
var task models.Task
err := json.NewDecoder(r.Body).Decode(&task)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
err = h.taskService.Create(context.Background(), task)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusCreated)
}
func (h *TaskHandler) List(w http.ResponseWriter, r *http.Request) {
tasks, err := h.taskService.List(context.Background())
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
json.NewEncoder(w).Encode(tasks)
}
Étape 4 : Création du fichier main.go
Dans le dossier cmd/app/main.go :
package main
import (
"context"
"fmt"
"log"
"github.com/gorilla/mux"
"myapp/internal/handlers"
"myapp/internal/services"
)
func main() {
taskService := services.NewTaskService()
taskHandler := handlers.NewTaskHandler(taskService)
r := mux.NewRouter()
r.HandleFunc("/tasks", taskHandler.Create).Methods("POST")
r.HandleFunc("/tasks", taskHandler.List).Methods("GET")
log.Println("Starting server at port 8080")
if err := http.ListenAndServe(":8080", r); err != nil {
log.Fatal(err)
}
}
Étape 5 : Configuration de Railway
Créez un fichier .railway/manifest.yml :
## myapp/.railway/manifest.yml
services:
app:
image: golang:latest
env:
- NAME=MyApp
command: go run cmd/app/main.go
Erreurs frequentes et debugging
1. command not found
## ❌ Mauvais : Commande non trouvée
go build cmd/app/main.go
## ✅ Correct
go build -o app cmd/app/main.go
2. Error: could not read manifest file
## ❌ Mauvais : Fichier manifest.yaml incorrect
services:
app:
image: golang:latest
env:
- NAME=MyApp
## ✅ Correct
services:
app:
image: golang:latest
env:
- NAME=MyApp
3. Error: could not find main.go
## ❌ Mauvais : Fichier main.go incorrect
package main
func main() {
}
## ✅ Correct
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, World!")
}
Pour aller plus loin
- Tests unitaires : Ajouter des tests pour chaque fonction.
- Authentication JWT : Utiliser le middleware JSON Web Token pour sécuriser les routes.
- Docker Compose : Utilisez Docker Compose pour gérer les dépendances et les configurations complexes.
Défi pratique
Créez une application Go qui permet de gérer des utilisateurs avec les fonctionnalités suivantes :
- Inscription et connexion d'utilisateurs
- Création, mise à jour et suppression d'utilisateurs
- Authentification JWT pour sécuriser les routes