ファイル入出力

編集

ファイルの作成・読出し・書込みなどの操作を「ファイル入出力」と言います。 Goのファイル入出力機能は、 "os" パッケージで実装されています。 "os" パッケージで定義された関数 os.Open 関数でファイルをオープンできます。 os.Open 関数を使用する際、この関数は戻り値を2つ返します(多値返却)。 os.Open 関数の第1戻値は正常動作時の戻値(*os.File)、第2戻値はエラー時に nil 以外を返します。

ファイルのオープンと読出し

編集

バッファリングなし

編集
ファイルのオープンと読出し(バッファリングなし)
// Package main は、指定されたファイルを読み取り、標準出力に内容を表示するプログラムを提供します。
package main

import (
	"io"
	"log"
	"os"
)

// main 関数は、/etc/hosts ファイルを開き、その内容を読み取って標準出力に書き出します。
// ファイル操作中にエラーが発生した場合、適切にログを出力してプログラムを終了します。
func main() {
	// /etc/hosts ファイルを開く
	f, err := os.Open("/etc/hosts")
	if err != nil {
		// ファイルを開けない場合、エラーメッセージを出力して終了
		log.Fatal(err)
	}
	// ファイルを閉じる処理を defer に登録
	defer f.Close() // ファイルを確実に閉じる

	// バッファを作成してデータを読み込む
	b := make([]byte, 4096) // 4KB のバッファ
	for {
		// ファイルから読み込む
		switch c, err := f.Read(b); {
		// 読み込んだバイト数が 0 の場合、終了
		case c == 0:
			return
		// EOF (End of File) に達した場合、終了
		case err == io.EOF:
			return
		// その他のエラーが発生した場合
		case err != nil:
			log.Fatal(err)
		// 正常に読み込めた場合
		case err == nil:
			// 読み込んだ内容を標準出力に書き込む
			os.Stdout.Write(b[:c])
		// 想定外の状況 (冗長な安全策)
		default:
			panic("???")
		}
	}
}
解説
  • os.Open /etc/hosts ファイルを読み込み専用で開きます。失敗時はエラーを処理。
  • defer f.Close() プログラム終了時に確実にファイルを閉じるための処理。
  • make([]byte, 4096) 読み込みバッファを 4KB 確保。
  • f.Read(b) ファイルを読み込み、結果をバッファに格納。
  • io.EOF ファイルの終端に到達した場合の特別なエラーコード。
  • log.Fatal エラー発生時にログ出力し、即座にプログラムを終了。
  • os.Stdout.Write 標準出力にバッファ内容を書き出す。

バッファリングあり

編集
ファイルのオープンと読出し(バッファリングあり)
// Package main は、指定されたファイルを読み取り、その内容を標準出力に表示するプログラムを提供します。
// バッファ付きリーダーを使ってファイルの内容を行単位で読み取ります。
package main

import (
	"bufio"
	"io"
	"log"
	"os"
)

func main() {
	// /etc/hosts ファイルを開く
	file, err := os.Open("/etc/hosts")
	if err != nil {
		// ファイルを開けない場合、エラーメッセージを出力して終了
		log.Fatal(err)
	}
	// ファイルを閉じる処理を defer に登録
	defer file.Close() // ファイルを確実に閉じる

	// バッファ付きリーダーを作成
	reader := bufio.NewReader(file)

	// ファイルの内容を一行ずつ読み込んで出力
	for {
		// 改行文字で区切られたバイト列を読み込む
		if line, err := reader.ReadBytes('\n'); err != nil {
			// エラーが io.EOF の場合、ファイルの終わり
			if err == io.EOF {
				break // ファイルの終わりに達したのでループを終了
			}
			// それ以外のエラーの場合、エラーログを出力して終了
			log.Fatal(err)
		} else {
			// 読み込んだ行を標準出力に書き出す
			os.Stdout.Write(line)
		}
	}
}
解説
  • os.Open /etc/hosts ファイルを開きます。失敗した場合、エラーメッセージをログに出力し、プログラムを終了します。
  • defer file.Close() プログラムが終了する際にファイルを閉じる処理を登録します。defer は遅延実行されるため、ファイルのクローズを確実に行います。
  • bufio.NewReader(file) bufio.NewReader を使用してバッファ付きリーダーを作成し、ファイルから効率よくデータを読み込みます。
  • reader.ReadBytes('\n') ReadBytes は改行文字 \n までのバイト列を読み込みます。読み込んだデータはバイトスライスとして返されます。
  • io.EOF ファイルの終わりに達した場合に発生するエラーです。このエラーが発生した場合、ループを終了します。
  • os.Stdout.Write(line) 標準出力に読み込んだ行をそのまま書き出します。
特徴

このコードは、ファイルからバッファを使って効率的にデータを読み込み、行単位で処理する方法を示しています。ReadBytes を使うことで、改行ごとに分割されたバイト列を取得し、標準出力に書き出しています。

バッファリング
バッファリングは、複数の機器やプログラムの間でデータを転送する場合に、予め用意した記憶領域(バッファー)に送受信データを一時的に保存する手法で
  1. 処理速度や転送速度の差を補う
  2. 通信の減速や中断に備える

ことを目的としています。

バッファリングすることで、

  1. 動作速度の向上
  2. 入出力要求の回数の削減
  3. ジッターの防止あるいは低減

などが図れます。

バッファーにある未処理のデータを強制的に次の処理に送り出すことを、フラッシュ(flash)と呼びます。

ファイルの作成と書込み

編集

"os" パッケージで定義された関数 os.Create 関数でファイルを作成できます。 os.Create 関数を使用する際、この関数は戻り値を2つ返します(多値返却)。 os.Create 関数の第1戻値は正常動作時の戻値(*os.File)、第2戻値はエラー時に nil 以外を返します。

ファイルの作成と書込み
// Package main は、新しいファイルを作成し、そこにテキストを書き込むプログラムを提供します。
// ファイル作成時や書き込み時にエラーが発生した場合、適切なエラーメッセージを出力します。
package main

import (
	"log"
	"os"
)

func main() {
	// "file-create-test.txt" という名前の新しいファイルを作成
	f, err := os.Create("file-create-test.txt")
	if err != nil {
		// ファイル作成に失敗した場合、エラーメッセージをログに出力して終了
		log.Fatal(err)
	}
	// ファイルを閉じる処理を defer に登録
	defer f.Close()

	// ファイルに文字列 "TEST TEXT\n" を書き込む
	if _, err := f.Write([]byte("TEST TEXT\n")); err != nil {
		// 書き込みに失敗した場合、エラーメッセージをログに出力して終了
		log.Fatal(err)
	}
}
解説
  • os.Create("file-create-test.txt") os.Create は指定されたファイル名で新しいファイルを作成します。もしファイルが既に存在する場合、上書きされます。ファイル作成に失敗した場合、エラーメッセージをログに出力し、プログラムを終了します。
  • defer f.Close() defer を使用して、ファイルのクローズを遅延実行します。これにより、関数終了時に必ずファイルが閉じられます。
  • f.Write([]byte("TEST TEXT\n")) Write メソッドを使用して、指定されたバイトスライス(ここでは "TEST TEXT\n")をファイルに書き込みます。書き込みに失敗した場合、エラーメッセージをログに出力し、プログラムを終了します。
特徴

このプログラムは、ファイルの作成から書き込み、そしてファイルのクローズ処理を行います。defer を使ってファイルクローズ処理を遅延させることで、関数終了時に必ずファイルが閉じられることを保証しています。エラーが発生した場合は、log.Fatal によって即座にエラーメッセージが出力され、プログラムは終了します。

脚註

編集