Menu
Coddy logo textTech

復習 - ファイルパーサー

CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 58/107。

challenge icon

チャレンジ

簡単

この章で学んだすべてのエラーハンドリング手法を統合した、設定ファイルパーサーを構築しましょう。このパーサーは、カスタムエラー型、センチネルエラー、エラーラッピング、そして defer を使用した適切なクリーンアップを用いて、複数の失敗シナリオを処理します。

コードは以下の3つのファイルに分けて構成します:

  • errors.go: パーサーのためのエラーインフラストラクチャを定義します。

    2つのセンチネルエラーを作成してください:

    • ErrEmptyContent:メッセージは "file content is empty"
    • ErrInvalidFormat:メッセージは "invalid configuration format"

    Line (int) と Message (string) フィールドを持つカスタムエラー型 ParseError を作成してください。その Error() メソッドは parse error at line [Line]: [Message] を返すようにします。

  • parser.go: 階層化されたエラーハンドリングを持つ設定パーサーを構築します。

    解析が正常に完了したかどうかを追跡するための parsed ブール値フィールドを持つ ConfigParser 構造体を作成してください。

    以下のメソッドを実装してください:

    • NewConfigParser() *ConfigParser - parsedfalse に設定して新しいパーサーを作成します。
    • ParseLine(lineNum int, line string) error - 単一の行を検証します。行に = 文字が含まれていない場合は、行番号とメッセージ "missing key-value separator" を持つ *ParseError を返します。それ以外の場合は nil を返します。
    • Parse(content string) error - 以下の処理を行うメインの解析メソッドです:
      • content が空の場合は ErrEmptyContent を返します。
      • content に少なくとも1つの改行文字が含まれていない場合は ErrInvalidFormat を返します。
      • content を改行で分割し、各行に対して ParseLine を呼び出します(行番号は1から始まります)。
      • ParseLine がエラーを返した場合は、それを "parsing configuration: %w" でラップして返します。
      • 成功した場合は parsedtrue に設定し、nil を返します。
    • Status() string - parsed が true の場合は "ready" を、そうでない場合は "not parsed" を返します。
  • main.go: 設定内容を読み込み、包括的なエラー検査を実演します。

    設定内容を構成する2行の入力を読み込みます(これらを改行で結合します)。成功か失敗かにかかわらず、最後に必ずパーサーのステータスを出力するために defer を使用してください。

    解析を試みた後、errors.Is()errors.As() の両方を使用してエラーを検査し、何が問題だったかに基づいて具体的なフィードバックを提供します。

以下の入力が提供されます:

  • 1行目:設定内容の最初の行
  • 2行目:設定内容の2番目の行

特定のエラーメッセージでエラーを処理してください:

  • errors.Is()ErrEmptyContent が見つかった場合:Error: No configuration provided と出力します。
  • errors.Is()ErrInvalidFormat が見つかった場合:Error: Configuration must have multiple lines と出力します。
  • errors.As()*ParseError が見つかった場合:ラップされたエラーのフルメッセージを出力し、次の行に Fix line [Line]: [Message] と出力します。
  • 解析に成功した場合:Configuration parsed successfully と出力します。

結果(成功またはエラー)を処理した後、遅延実行(deferred)されたステータスを新しい行に出力する必要があります:Parser status: [status]

例えば、host=localhostport=8080 が与えられた場合、出力は以下のようになります:

Configuration parsed successfully
Parser status: ready

また、host=localhostinvalid line が与えられた場合、出力は以下のようになります:

parsing configuration: parse error at line 2: missing key-value separator
Fix line 2: missing key-value separator
Parser status: not parsed

自分で試してみよう

package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
)

func main() {
	reader := bufio.NewReader(os.Stdin)
	
	// 設定の1行目を読み込む
	line1, _ := reader.ReadString('\n')
	line1 = line1[:len(line1)-1] // 末尾の改行を削除
	
	// 設定の2行目を読み込む
	line2, _ := reader.ReadString('\n')
	if len(line2) > 0 && line2[len(line2)-1] == '\n' {
		line2 = line2[:len(line2)-1]
	}
	
	// 2つの行を改行で結合して設定内容を作成する
	content := line1 + "\n" + line2
	
	// 新しいパーサーを作成する
	parser := NewConfigParser()
	
	// TODO: deferを使用して、最後に必ずパーサーのステータスを出力する
	// 形式: "Parser status: [status]"
	
	// TODO: コンテンツの解析を試みる
	
	// TODO: errors.Is() と errors.As() を使用してエラーを処理する
	// - errors.Is() で ErrEmptyContent が見つかった場合: "Error: No configuration provided" と出力
	// - errors.Is() で ErrInvalidFormat が見つかった場合: "Error: Configuration must have multiple lines" と出力
	// - errors.As() で *ParseError が見つかった場合: ラップされたエラーの全文を出力し、
	//   次の行に "Fix line [Line]: [Message]" と出力
	// - 解析に成功した場合: "Configuration parsed successfully" と出力
	
	_ = errors.Is // ヒント: センチネルエラーには errors.Is を使用します
	_ = errors.As // ヒント: カスタムエラー型には errors.As を使用します
	_ = fmt.Println
}

オブジェクト指向プログラミングのすべてのレッスン