関数型プログラミング (FP) の原則は、不変性、構成可能性、および明示性を重視しているため、現代のソフトウェア開発で人気が高まっています。 Go は伝統的に命令型言語ですが、IBM によって開発された fp-go ライブラリでは、Option、Either、Fold、関数合成用のユーティリティなどの FP 抽象化が導入されています。この記事では、fp-go を使用してエラーを明示的に処理し、複数のエラー タイプの関数シグネチャを定義し、これらの概念を示す実際の CRUD API サンプルを構築する方法を検討します。
エラー処理は、信頼性の高いソフトウェアを構築するために非常に重要です。従来の Go エラー処理は返されるエラー値に依存しているため、意図せずに無視されたり、誤って処理されたりする可能性があります。機能エラー処理では、次のような抽象化が導入されます。
これらの概念を詳しく見て、fp-go が Go でどのようにそれらを容易にするかを見てみましょう。
まず、fp-go を Go プロジェクトに追加します。
go get github.com/IBM/fp-go
必要なモジュールをインポートします:
import ( either "github.com/IBM/fp-go/either" option "github.com/IBM/fp-go/option" )
オプションは、存在する場合も存在しない場合もある値を表します。 Some(value) または None のいずれかです。
func parseInt(input string) option.Option[int] { value, err := strconv.Atoi(input) if err != nil { return option.None[int]() } return option.Some(value) } func main() { opt := parseInt("42") option.Fold( func() { fmt.Println("No value") }, func(value int) { fmt.Printf("Parsed value: %d\n", value) }, )(opt) }
どちらも、次の 2 つの可能性が生じる計算を表します。
type MathError struct { Code string Message string } func safeDivide(a, b int) either.Either[MathError, int] { if b == 0 { return either.Left(MathError{Code: "DIV_BY_ZERO", Message: "Cannot divide by zero"}) } return either.Right(a / b) } func main() { result := safeDivide(10, 0) either.Fold( func(err MathError) { fmt.Printf("Error [%s]: %s\n", err.Code, err.Message) }, func(value int) { fmt.Printf("Result: %d\n", value) }, )(result) }
実際のアプリケーションでは、多くの場合、複数の種類のエラーを処理する必要があります。タグ付き共用体を使用すると、明示的なエラー タイプを定義できます。
go get github.com/IBM/fp-go
Either を使用して明示的なエラー処理を備えたシンプルな CRUD API を実装してみましょう。
import ( either "github.com/IBM/fp-go/either" option "github.com/IBM/fp-go/option" )
func parseInt(input string) option.Option[int] { value, err := strconv.Atoi(input) if err != nil { return option.None[int]() } return option.Some(value) } func main() { opt := parseInt("42") option.Fold( func() { fmt.Println("No value") }, func(value int) { fmt.Printf("Parsed value: %d\n", value) }, )(opt) }
type MathError struct { Code string Message string } func safeDivide(a, b int) either.Either[MathError, int] { if b == 0 { return either.Left(MathError{Code: "DIV_BY_ZERO", Message: "Cannot divide by zero"}) } return either.Right(a / b) } func main() { result := safeDivide(10, 0) either.Fold( func(err MathError) { fmt.Printf("Error [%s]: %s\n", err.Code, err.Message) }, func(value int) { fmt.Printf("Result: %d\n", value) }, )(result) }
type AppError struct { Tag string Message string } const ( MathErrorTag = "MathError" DatabaseErrorTag = "DatabaseError" ) func NewMathError(msg string) AppError { return AppError{Tag: MathErrorTag, Message: msg} } func NewDatabaseError(msg string) AppError { return AppError{Tag: DatabaseErrorTag, Message: msg} } func process(a, b int) either.Either[AppError, int] { if b == 0 { return either.Left(NewMathError("Division by zero")) } return either.Right(a / b) } func main() { result := process(10, 0) either.Fold( func(err AppError) { fmt.Printf("Error [%s]: %s\n", err.Tag, err.Message) }, func(value int) { fmt.Printf("Processed result: %d\n", value) }, )(result) }
Go で fp-go を使用すると、次のことができます。
これらのパターンにより、Go コードがより堅牢になり、読みやすく、機能的になります。 CRUD API を構築している場合でも、複雑なビジネス ロジックを構築している場合でも、fp-go を使用すると、エラーをクリーンかつ一貫して処理できます。
以上がIBM fp-go を使用した Go の関数型プログラミング: 明示的なエラー処理の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。