ホームページ バックエンド開発 Golang Golang の Mo パッケージに Do 記法を導入

Golang の Mo パッケージに Do 記法を導入

Jul 16, 2024 pm 04:32 PM

Introducing Do Notation in the Mo Package for Golang

Do記法とは何ですか?

Do 記法は、主に Haskell や Scala などの関数型プログラミング言語で使用される糖衣構文です。モナド操作の連鎖が簡素化され、コードがより読みやすく、保守しやすくなります。この機能を Go に導入することで、モナドを操作するときに、よりクリーンで表現力豊かなコードを作成できるようになりました。

なぜ記法を行うのか?

モナドを扱うとき、特に複雑なビジネス ロジックでは、操作の連鎖が面倒になることがあります。エラーの処理とさまざまな状態の管理は、多くの場合、理解するのが難しい深くネストされた構造につながります。 Do 記法は、命令型プログラミングに似たシーケンシャル スタイルでモナド演算を記述できるようにすることでこの問題に対処しますが、関数型プログラミングの利点もすべて備えています。

Mo パッケージではどのように動作しますか?

Go では、do 記法の実装は簡単ではありませんでしたが、Do 関数を使用してなんとか実現できました。以下に、例を示してその使用方法を簡単に示します。

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())
    }
}
ログイン後にコピー

この例では、bookRoom は Do 関数を使用して、予約パラメータの検証、予約の作成、部屋の割り当てといったいくつかの操作を順番に実行します。各ステップは、Do 関数を使用してシームレスに連鎖できる Result を返し、クリーンで読みやすいエラー処理を保証します。

bookRoom機能比較

Do 表記なし

2 つのオプションがあります:

1.バインドの使用 (実装されている場合):
モナドの「バインド」操作は、多数のモナド操作がある場合、これらの操作のネストされた順次的な性質のため、コールバック地獄に似ている可能性があります。このような操作が多数連鎖すると、非同期プログラミングでコールバックが深くネストされるのと同様に、コードが深くネストされ、読みにくくなる可能性があります。 Bind が Mo パッケージに実装されている場合、この例でそれを使用すると次のようになります。

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})
            })
        })
    })
}
ログイン後にコピー

このアプローチはすぐに読みにくく、保守しにくくなります。

2. .Get() の使用:
もう 1 つのオプションは、モナドで .Get() を使用してモナドをラップ解除し、基になる値とエラーを取得することです。これは典型的な Go コードのように見えますが、エラー処理が冗長になる場合があります:

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})
}
ログイン後にコピー

このアプローチはバインドを使用するよりも読みやすいですが、それでも多くの定型的なエラー処理が必要です。

Do 表記あり

do 記法を使用すると、モナドで .MustGet() を呼び出して、エラーなしで基になる値を直接取得できます。この関数 (MustGet()) は、モナドにエラーがある場合にパニックになります。ただし、Do 記法はこれを処理し、エラーが発生した場合は実行を短縮するか、ラップされていない値を返します。

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}
    })
}
ログイン後にコピー

このアプローチは明確で簡潔で読みやすく、定型的なエラー処理コードを大幅に削減します。


最終的な考え

do 記法を使用する大きな利点の 1 つは、モナド演算のたびにエラーをチェックする必要がないことです。モナドはエラー型を持つことができますが、Do 記法は自動的にエラーの伝播を処理し、エラーが発生した場合には実行を短縮します。これにより、コードがよりクリーンで保守しやすくなり、複雑なワークフローで特に価値があります。

以上がGolang の Mo パッケージに Do 記法を導入の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Go Language Packのインポート:アンダースコアとアンダースコアなしの違いは何ですか? Go Language Packのインポート:アンダースコアとアンダースコアなしの違いは何ですか? Mar 03, 2025 pm 05:17 PM

Go Language Packのインポート:アンダースコアとアンダースコアなしの違いは何ですか?

Beegoフレームワークのページ間で短期情報転送を実装する方法は? Beegoフレームワークのページ間で短期情報転送を実装する方法は? Mar 03, 2025 pm 05:22 PM

Beegoフレームワークのページ間で短期情報転送を実装する方法は?

MySQLクエリ結果リストをGO言語のカスタム構造スライスに変換する方法は? MySQLクエリ結果リストをGO言語のカスタム構造スライスに変換する方法は? Mar 03, 2025 pm 05:18 PM

MySQLクエリ結果リストをGO言語のカスタム構造スライスに変換する方法は?

GOのジェネリックのカスタムタイプ制約を定義するにはどうすればよいですか? GOのジェネリックのカスタムタイプ制約を定義するにはどうすればよいですか? Mar 10, 2025 pm 03:20 PM

GOのジェネリックのカスタムタイプ制約を定義するにはどうすればよいですか?

GOでテスト用のモックオブジェクトとスタブを書くにはどうすればよいですか? GOでテスト用のモックオブジェクトとスタブを書くにはどうすればよいですか? Mar 10, 2025 pm 05:38 PM

GOでテスト用のモックオブジェクトとスタブを書くにはどうすればよいですか?

Goでユニットテストをどのように書きますか? Goでユニットテストをどのように書きますか? Mar 21, 2025 pm 06:34 PM

Goでユニットテストをどのように書きますか?

Go言語でファイルを便利に書く方法は? Go言語でファイルを便利に書く方法は? Mar 03, 2025 pm 05:15 PM

Go言語でファイルを便利に書く方法は?

トレースツールを使用して、GOアプリケーションの実行フローを理解するにはどうすればよいですか? トレースツールを使用して、GOアプリケーションの実行フローを理解するにはどうすればよいですか? Mar 10, 2025 pm 05:36 PM

トレースツールを使用して、GOアプリケーションの実行フローを理解するにはどうすればよいですか?

See all articles