Maison > développement back-end > Golang > le corps du texte

Présentation de Do Notation dans le package Mo pour Golang

王林
Libérer: 2024-07-16 16:32:12
original
629 Les gens l'ont consulté

Introducing Do Notation in the Mo Package for Golang

Qu’est-ce que la notation Do ?

La notation Do est un sucre syntaxique principalement utilisé dans les langages de programmation fonctionnels comme Haskell et Scala. Il simplifie l'enchaînement des opérations monadiques, rendant le code plus lisible et maintenable. En apportant cette fonctionnalité à Go, nous pouvons désormais écrire du code plus propre et plus expressif lorsque nous travaillons avec des monades.

Pourquoi faire de la notation ?

Lorsqu'il s'agit de monades, en particulier dans une logique métier complexe, le chaînage des opérations peut devenir fastidieux. La gestion des erreurs et la gestion des différents états conduisent souvent à des structures profondément imbriquées et difficiles à suivre. La notation Do résout ce problème en nous permettant d'écrire des opérations monadiques dans un style séquentiel, semblable à la programmation impérative, mais avec tous les avantages de la programmation fonctionnelle.

Comment ça marche dans le package Mo ?

En Go, l'implémentation de la notation do n'était pas simple, mais j'ai réussi à y parvenir en utilisant la fonction Do. Voici un aperçu rapide de la façon dont vous pouvez l'utiliser avec un exemple :

package main

import (
    "errors"
    "fmt"
    "github.com/samber/mo"
)

func validateBooking(params map[string]string) mo.Result[map[string]string] {
    if params["guest"] != "" && params["roomType"] != "" {
        return mo.Ok(params)
    }
    return mo.Err[map[string]string](errors.New("validation failed"))
}

func createBooking(guest string) mo.Result[string] {
    if guest != "" {
        return mo.Ok("Booking Created for: " + guest)
    }
    return mo.Err[string](errors.New("booking creation failed"))
}

func assignRoom(booking string, roomType string) mo.Result[string] {
    if roomType != "" {
        return mo.Ok("Room Assigned: " + roomType + " for " + booking)
    }
    return mo.Err[string](errors.New("room assignment failed"))
}

// This could be a service package that performs the entire process
func bookRoom(params map[string]string) mo.Result[[]string] {
    return mo.Do(func() []string {
        // Validate booking parameters
        values := validateBooking(params).MustGet()

        // Create booking
        booking := createBooking(values["guest"]).MustGet()

        // Assign room
        room := assignRoom(booking, values["roomType"]).MustGet()

        // Return success with booking and room details
        return []string{booking, room}
    })
}

func main() {
    params := map[string]string{
        "guest":   "Foo",
        "roomType": "Suite",
    }

    result := bookRoom(params)
    if result.IsError() {
        fmt.Println("Error:", result.Error())
    } else {
        fmt.Println("Success:", result.MustGet())
    }
}
Copier après la connexion

Dans cet exemple, bookRoom utilise la fonction Do pour effectuer séquentiellement plusieurs opérations : valider les paramètres de réservation, créer une réservation et attribuer une salle. Chaque étape renvoie un résultat qui peut être enchaîné de manière transparente à l'aide de la fonction Do, garantissant une gestion des erreurs propre et lisible.

Comparaison de la fonction bookRoom

Sans Do-Notation

Vous pouvez avoir deux options :

1. Utilisation de bind (si implémenté) :
L'opération de « liaison » dans les monades peut ressembler à l'enfer des rappels lorsqu'il existe de nombreuses opérations monadiques en raison de la nature imbriquée et séquentielle de ces opérations. Lorsque de nombreuses opérations de ce type sont enchaînées, le code peut devenir profondément imbriqué et plus difficile à lire, de la même manière que les rappels peuvent être profondément imbriqués dans la programmation asynchrone. Si bind était implémenté dans le package Mo, son utilisation dans cet exemple ressemblerait à ceci :

func bookRoom(params map[string]string) mo.Result[[]string] {
    return bind(validateBooking(params), func(values map[string]string) mo.Result[[]string] {
        return bind(createBooking(values["guest"]), func(booking string) mo.Result[[]string] {
            return bind(assignRoom(booking, values["roomType"]), func(room string) mo.Result[[]string] {
                return mo.Ok([]string{booking, room})
            })
        })
    })
}
Copier après la connexion

Cette approche devient vite difficile à lire et à maintenir.

2. Utilisation de .Get() :
Une autre option consiste à utiliser .Get() sur la monade pour déballer la monade et obtenir la valeur et l'erreur sous-jacentes. Cela ressemble à du code Go typique, mais la gestion des erreurs peut être verbeuse :

func bookRoom(params map[string]string) mo.Result[[]string] {
    values, err := validateBooking(params).Get()
    if err != nil {
        return mo.Err[[]string](err)
    }

    booking, err := createBooking(values["guest"]).Get()
    if err != nil {
        return mo.Err[[]string](err)
    }

    room, err := assignRoom(booking, values["roomType"]).Get()
    if err != nil {
        return mo.Err[[]string](err)
    }

    return mo.Ok([]string{booking, room})
}
Copier après la connexion

Cette approche est plus lisible que l'utilisation de bind, mais implique toujours beaucoup de gestion des erreurs passe-partout.

Avec Do-Notation

Avec la notation do, vous pouvez appeler .MustGet() sur la monade pour obtenir la valeur sous-jacente directement sans erreur. Cette fonction (MustGet()) paniquera si la monade a une erreur ; cependant, la notation do gérera cela et court-circuitera l'exécution s'il y a une erreur ou renverra la valeur non enveloppée :

func bookRoom(params map[string]string) mo.Result[[]string] {
    return mo.Do(func() []string {
        values := validateBooking(params).MustGet()
        booking := createBooking(values["guest"]).MustGet()
        room := assignRoom(booking, values["roomType"]).MustGet()
        return []string{booking, room}
    })
}
Copier après la connexion

Cette approche est claire, concise et facile à lire, réduisant considérablement le code de gestion des erreurs passe-partout.


Pensées finales

L'un des grands avantages de l'utilisation de la notation do est que vous n'avez pas à vérifier les erreurs après chaque opération monadique. Même si une monade peut avoir un type d'erreur, la notation do gérera automatiquement la propagation des erreurs et court-circuitera l'exécution si une erreur se produit. Cela conduit à un code plus propre et plus maintenable, ce qui est particulièrement précieux dans les flux de travail complexes.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!