Bonjour ! Beaucoup se demandent comment fonctionnent les feuilles de tâche simples ou les applications qui offrent de telles fonctionnalités. Dans cet article, je vous invite à considérer comment vous pouvez écrire votre petit service en Go en quelques heures et mettre tout dans une base de données.
Commençons notre voyage avec Go et MongoDB.
Pourquoi Go ?
Je veux montrer les clés :
- Conception minimaliste et compilation rapide
- Modèle de concurrence forte avec des Goroutines et des canaux
- Écosystème immense
- Cross-plateforme à la case
Un autre facteur est de ne pas passer trop de temps à étudier les bibliothèques ou les solutions open source. Dans mon cas, je veux créer un microservice qui fonctionnera presque à l’outil. La langue de programmation Go a tout pour cela.
Toutefois, je vais remarquer que la langue est déjà riche en projets très cools qui résolvent beaucoup de problèmes pour le développeur. Des projets tels que :
- Gin : FrameHTTP haute performance
- Viper : Solution de configuration (JSON, propriétés, fichiers YML) pour les applications Go
- GORM : Bibliothèque ORM
- Protocol Buffers (Protobuf) : La meilleure manière de sérialiser les données structurées.
Nous ne les passerons pas en revue dans le cadre de cet article, mais j’écrirai peut-être quelque chose à leur sujet plus tard. Avec Protobuf, j’ai déjà écrit un article intéressant, « Fde JSON à FlatBuffers : Enhancing Performance in Data Serialization. »
Installation
Installation du langage Go
Visitez golang.org et téléchargez. Ensuite, allez dans le terminal et vérifiez-le.
go version
IDE
Installez simplement VS Code (c’est gratuit).
Et ajoutez ensuite l’extension Golang:
Tapez votre premier code:
package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}
Et exécutez-le:
go run main.go
C’est tout ! L’étape suivante consiste à choisir la meilleure option pour collecter nos données.
Notre structure de tâche
Je pense que notre première structure devrait être très simple. Commençons par 3 champs :
- Titre (texte)
- Description (texte)
- Statut (bool)
Fichier JSON comme référence :
{
"title": "Go to the groceries",
"description": "Purchase milk, eggs, and bread",
"completed": false
}
Pourquoi MongoDB ?
Nous avons besoin de collecter des données pour nos tâches et devenir flexibles. Nous n’avons pas besoin de créer un schéma ou une relation entre les choses.
- Schéma Flexible
- Scalabilité : Il permet la scalabilité horizontale.
- Langage de requête riche
Pour notre petit service, nous pouvons le démarrer en utilisant docker-compose
.
# Utilisez root/example comme identifiant utilisateur/mot de passe.
version: '3.1'
services:
mongo:
image: mongo
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
J’aime utiliser l’interface graphique Compass pour travailler avec nos données (collections, bases de données, etc.). Téléchargez-le ici.
Exécutez-le simplement et configurez vos identifiants dans « Options avancées« . Il fonctionne parfaitement et peut vous aider à trouver des problèmes et à optimiser les requêtes si vous en avez besoin.
Conception système (vraiment petit)
Pour notre service, évidemment, l’option la plus appropriée est de créer des méthodes CRUD (Créer, Lire, Mettre à jour, Supprimer), quelque chose comme ceci (sans supprimer) :
http.HandleFunc("/api/v1/add", todoHandler.AddTask)
http.HandleFunc("/api/v1/get-all", todoHandler.GetAllTasks)
http.HandleFunc("/api/v1/update", todoHandler.UpdateTask)
http.HandleFunc("/api/v1/complete", todoHandler.CompleteTask)
J’aimerais utiliser la méthode de séparer toutes les responsabilités par des dossiers.
- Gestionnaire – Couche HTTP
- Modèle – Structures pour les données
- Use cases – Couches d’affaires avec des services et des dépôts
La structure du projet pourrait ressembler à cela :
todo-list/
│
├── cmd/
│ └── main.go
├── pkg/
│ └── handler
│ └── add_task.go
│ └── http_handler.go
│ └── complite_task.go
│ └── get_all_task.go
│ └── update_task.go
│ └── mapper
│ └── task.go
│ └── model
│ └── task.go
│ └── usecase
│ └── task
│ └── repository
│ └── add_task.go
│ └── complite_task.go
│ └── get_all_task.go
│ └── mongo_repositiry.go
│ └── repository.go
│ └── update_task.go
│ └── service
│ └── add_task.go
│ └── complite_task.go
│ └── get_all_task.go
│ └── service.go
│ └── update_task.go
└── go.mod
Comme nous pouvons le voir, nous avons un fichier « go.mod », mais que est-ce que c’est ? C’est un gestionnaire de paquets ou un gestionnaire de dépendances. Nous pouvons installer et ajouter des librairies externes et les utiliser également. Pour notre exemple, nous avons besoin de quelques commandes utilisant « go mod ».
- Initialiser notre application ->
go mod init todo-service
. Nous initialiserons tout ; le gestionnaire de dépendances créera des fichiers et ajoutera tout ce qu’il nous faut. - Ajouter une dépendance supplémentaire en utilisant
go mod add "link"
.
Vous pouvez en savoir plus sur la page de référence des modules Go .
Ensuite, focusons-nous sur une seule méthode — l’ajout de tâches. Pour explorer davantage et pour des exemples de code complets, visitez le référentiel GitHub Golang Workshop .
Connexion à MongoDB
Avec seulement deux dépendances, nous pouvons créer une connexion :
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
Bien sûr, nous devons l’ajouter à notre service. Veuillez utiliser les commandes :
go get "go.mongodb.org/mongo-driver/mongo"
et
go get "go.mongodb.org/mongo-driver/mongo/options"
Ensuite, écrivez un morceau de code :
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Configurer les options du client MongoDB
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017").SetAuth(options.Credential{
Username: "root",
Password: "example",
})
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal(err)
}
err = client.Ping(ctx, nil)
if err != nil {
log.Fatal(err)
}
log.Println("Connected to MongoDB!")
}
Structures de données pour notre application :
package model
import "go.mongodb.org/mongo-driver/bson/primitive"
type Task struct {
ID string `json:"id"`
Title string `json:"title"`
Desciption string `json:"description"`
Completed bool `json:"completed"`
}
type MongoTask struct {
ID primitive.ObjectID `json:"id" bson:"_id"`
Title string `json:"title"`
Desciption string `json:"description"`
Completed bool `json:"completed"`
}
Tâche
– pour la requête HTTP,MongoTask
– pour la couche MongoDB : L’utilisation de deux structures est facile parce que parfois, nous n’avons pas besoin d’envoyer des données supplémentaires à nos utilisateurs. Par exemple, nous pourrions avoir un champ secret, comme un nom d’utilisateur, que nous devons cacher.
1. Couche de référentiel :
type Repository interface {
AddTask(ctx context.Context, task model.MongoTask) error
}
func (r *MongoRepository) AddTask(ctx context.Context, task model.MongoTask) error {
task.ID = primitive.NewObjectID()
_, err := r.collection.InsertOne(ctx, task)
}
2. Couche de service :
type TodoService interface {
AddTask(ctx context.Context, task model.Task) error
}
func (s *Service) AddTask(ctx context.Context, task model.Task) error {
return s.Repo.AddTask(ctx, mapper.MapToDto(task))
}
3. Couche de gestionnaire (pour traiter les requêtes HTTP) :
func (h *Handler) AddTask(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
var task model.Task
err := json.NewDecoder(r.Body).Decode(&task)
if err != nil {
http.Error(w, "Invalid request body", http.StatusBadRequest)
return
}
err = h.Service.AddTask(ctx, task)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusCreated)
}
Maintenant, nous devons installer la connexion à la base de données et initialiser la dépendance « layers » dans le fichier main.go
.
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
// Configurer les options du client MongoDB
clientOptions := options.Client().ApplyURI("mongodb://localhost:27017").SetAuth(options.Credential{
Username: "root",
Password: "example",
})
client, err := mongo.Connect(ctx, clientOptions)
if err != nil {
log.Fatal(err)
}
err = client.Ping(ctx, nil)
if err != nil {
log.Fatal(err)
}
log.Println("Connected to MongoDB!")
// Initialiser le référentiel, le service et le gestionnaire
todoRepo := repository.NewMongoRepository(client)
todoService := service.NewService(todoRepo)
todoHandler := handler.NewHandler(todoService)
// Configurer les routes
http.HandleFunc("/api/v1/add", todoHandler.AddTask)
// Créer un serveur
srv := &http.Server{
Addr: ":8080",
Handler: nil,
}
// TODO : exécuter le service et arrêter
}
Et le tester avec la requête :
# curl -X POST http://localhost:8080/add
#-H "Content-Type: application/json"
#-d '{
# "id": 1,
# "title": "Buy groceries",
# "completed": false
#}'
POST http://localhost:8080/api/v1/add
Content-Type: application/json
{
"title": "Add description to the structure",
"description": "your desc here..."
}
C’est tout. Ensuite, nous devons ajouter et implémenter de nouvelles méthodes, et notre service sera prêt à travailler.
Conclusion
Nous avons créé un petit service de gestion de tâches robuste en utilisant Golang et MongoDB.
Comme nous pouvons le voir, si nous avons besoin de construire un petit service, nous le faisons vraiment rapidement sans beaucoup d’obstacles. Dans mon cas, je voudrais vraiment utiliser MongoDB comme base de données principale si je travaillais avec des documents. C’est juste facile à gérer.
Il peut également être remarqué que cela ne serait pas pire dans d’autres langages de programmation. En某些endroits, il est même plus rapide. Par exemple, si vous utilisez Python et FastAPI – et ici, je pourrais être d’accord avec vous. Le langage Go est toujours basé sur les paradigmes de langages de programmation tels que C ++ et Java, où il existe OOP. Ce type de code et de méthode vous permet de conserver le code le plus clair et le plus propre possible.
Comme début, il sera bon de consolider des facteurs tels que la base, qui vous aideront à comprendre TDD et d’autres méthodologies. Je remarquerais également que pour éviter d’overloader l’article avec des métriques et du texte, j’ai omis de les comparer aux autres langages. Je noterai que Go n’a pas de problèmes à cet égard, et après avoir écrit la fonction principale, vous la lancez déjà dans votre thread. Vous pouvez facilement trouver des comparaisons sur Internet, y compris des benchmarks.
Pour une exploration plus approfondie et des exemples de code complets, veuillez visiter le référentiel GitHub (lien fourni plus tôt).
Merci et prenez soin de vous !
Source:
https://dzone.com/articles/build-a-to-do-list-with-mongodb-and-golang