#12 Goで学ぶファイル読み書きの基本
Goのファイル操作は、`os`パッケージを使い、エラーを戻り値として確認するという、Goらしい設計になっています。この記事では、Goにおけるファイル操作の基本と、実務でよく使う関連の書き方を解説します。
ファイルを読み込む
content, err := os.ReadFile("data.txt")
if err != nil {
fmt.Println("エラー:", err)
return
}
fmt.Println(string(content))
読み込んだ内容はバイト列として返されるため、`string()`を使って文字列に変換します。`os.ReadFile`はファイル全体を一度にメモリへ読み込む方式なので、数MB程度までの設定ファイルやログの断片を読むのに向いています。
ファイルに書き込む
err := os.WriteFile("data.txt", []byte("こんにちは"), 0644)
if err != nil {
fmt.Println("エラー:", err)
}
`0644`という数字は、ファイルのアクセス権限を表す設定です。所有者は読み書き可能、それ以外のユーザーは読み取りのみ、という意味になります。この関数は呼び出すたびにファイルの中身をすべて上書きするため、既存の内容に追記したい場合には向きません。
大きなファイルを1行ずつ読む
ログファイルのように大きなファイルを扱う場合は、全体を一度にメモリへ載せる`os.ReadFile`ではなく、`bufio.Scanner`で1行ずつ処理する方法がよく使われます。
file, err := os.Open("access.log")
if err != nil {
fmt.Println("エラー:", err)
return
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
`os.Open`でファイルを開いたら、すぐ次の行で`defer file.Close()`を書いておくのが定石です。`defer`は関数を抜けるタイミングで自動的に実行されるため、途中でreturnする分岐が増えても閉じ忘れる心配がありません。
ファイルに追記する
既存の内容を消さずに追記したい場合は、`os.OpenFile`にフラグを指定して開きます。
f, err := os.OpenFile("log.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Println("エラー:", err)
return
}
defer f.Close()
f.WriteString("追記する行\n")
`os.O_APPEND`は末尾への追記、`os.O_CREATE`はファイルが無ければ新規作成、`os.O_WRONLY`は書き込み専用で開く、という意味です。これらは`|`(ビット単位のOR)でまとめて指定できます。
Goならではの注意点
他の言語の関数が「読み込んだ内容」だけを返すのに対し、Goの`os.ReadFile`は「内容」と「エラー」の両方を返します。以前の記事でも触れた通り、エラーの確認を省略しないことがGoの基本的な書き方です。ファイルが存在しない、権限が無いといったエラーは実行時まで分からないため、`if err != nil`のチェックを飛ばしてしまうと、原因の分かりにくいクラッシュにつながります。
まとめ
Goのファイル操作は`os.ReadFile`・`os.WriteFile`が基本ですが、大きなファイルには`bufio.Scanner`、追記には`os.OpenFile`とフラグの組み合わせが役立ちます。バイト列と文字列の変換、`defer`によるクローズ処理、そしてエラーの確認を忘れずに行いましょう。
本ページはプロモーションを含みます。
参考書籍(PR)
Goをもっと学びたい方には「Go言語入門」がおすすめです。
PR
コードを書かずに自動化したい方へ
「学んだけど自分の作業に組み込む時間がない」という方向けに、ダブルクリックで動く Windows専用の自動化ツールをオーダーメイドで作成しています。気になる方は こちらをご覧ください。
コメント
コメントを投稿