Skip to content

エラー処理

エラーの分類

HTML ライブラリのエラーは以下のカテゴリに分類されます:

カテゴリセンチネルエラー説明
入力エラーErrInputTooLarge, ErrInvalidHTML入力コンテンツの問題
設定エラーErrInvalidConfig, ErrMultipleConfigs設定の問題
ファイルエラーErrFileNotFound, ErrInvalidFilePathファイル操作の問題
処理エラーErrProcessingTimeout, ErrMaxDepthExceeded処理中の問題
システムエラーErrProcessorClosed, ErrInternalPanic内部状態の問題

errors.Is パターン

errors.Is でエラータイプを判定します:

go
result, err := html.Extract(data)
if err != nil {
    switch {
    case errors.Is(err, html.ErrInputTooLarge):
        slog.Warn("入力が大きすぎます。ドキュメントサイズを小さくしてください")
    case errors.Is(err, html.ErrInvalidHTML):
        slog.Warn("無効な HTML です。入力を確認してください")
    case errors.Is(err, html.ErrProcessingTimeout):
        slog.Warn("処理がタイムアウトしました。ドキュメントが複雑すぎる可能性があります")
    case errors.Is(err, html.ErrFileNotFound):
        slog.Warn("ファイルが存在しません")
    case errors.Is(err, html.ErrMaxDepthExceeded):
        slog.Warn("DOM 深度が深すぎます。悪意のある構成の可能性があります")
    case errors.Is(err, html.ErrInternalPanic):
        slog.Error("内部パニックからリカバリしました。この問題を報告してください")
    default:
        slog.Error("不明なエラー", "err", err)
    }
}

errors.As パターン

構造化されたエラー情報を抽出します:

go
var inputErr *html.InputError
var configErr *html.ConfigError
var fileErr *html.FileError

if errors.As(err, &inputErr) {
    fmt.Printf("サイズ %d が制限 %d を超過\n", inputErr.Size, inputErr.MaxSize)
}

if errors.As(err, &configErr) {
    fmt.Printf("フィールド %s の値 %v が無効: %s\n", configErr.Field, configErr.Value, configErr.Message)
}

if errors.As(err, &fileErr) {
    fmt.Printf("ファイル操作: %s\n", fileErr.SafePath())
}

コンテキストのキャンセル

ExtractWithContext バージョンを使用してキャンセルに対応します:

go
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

result, err := html.ExtractWithContext(ctx, data)
if err != nil {
    switch {
    case errors.Is(err, html.ErrProcessingTimeout):
        // ライブラリ内の ProcessingTimeout タイムアウト(この時点で ctx.Err() は nil の可能性あり)
    case ctx.Err() == context.DeadlineExceeded:
        // ユーザーコンテキストの期限切れ
    case ctx.Err() == context.Canceled:
        // 手動キャンセル
    default:
        // その他のエラー(ErrInvalidHTML、ErrInputTooLarge など)
        slog.Error("抽出失敗", "err", err)
    }
}

バッチエラー

バッチ処理の結果には部分的な成功と部分的な失敗が含まれます:

go
batch := p.ExtractBatch(pages)

for i, err := range batch.Errors {
    if err != nil {
        fmt.Printf("項目 %d が失敗: %v\n", i, err)
    }
}

fmt.Printf("成功:%d, 失敗:%d, キャンセル:%d\n",
    batch.Success, batch.Failed, batch.Cancelled)