メインコンテンツにスキップ
モジュール 8 · レッスン 3 / 5コース内の 38/50~14 min
モジュールのレッスン (3/5)

`io` と `os`: ファイルとストリーム

Go でのファイルとストリームの読み取りと書き込みは、os (開く、作成、メタデータ、プロセス) と io (バイト ソースを抽象化する Reader/Writer インターフェイス) という 2 つの補完的なパッケージを中心に展開します。

ファイルの読み取りと書き込み: ショートカット

小さいファイルや構成ファイルの場合は、1 回の呼び出しで十分です。

Go
data, err := os.ReadFile("input.txt")        // returns []byte
if err != nil {
    return err
}
fmt.Println(string(data))

err = os.WriteFile("out.txt", []byte("ciao"), 0644)

os.ReadFile が開き、すべてをメモリに読み取って閉じます。数 MB までは完璧です。それ以上に、ストリーミングの方が優れています。

ストリーミング用にファイルを開く

大きなファイルまたは増分アクセスの場合は、ファイルを開いて defer を使用して閉じます。

Go
f, err := os.Open("big.txt")        // read-only
if err != nil {
    return err
}
defer f.Close()

buf := make([]byte, 4096)
for {
    n, err := f.Read(buf)
    if n > 0 {
        process(buf[:n])
    }
    if err == io.EOF {
        break
    }
    if err != nil {
        return err
    }
}

os.Open は読み取り専用で開きます。書き込むには、os.Create (存在する場合は切り捨てられます) または os.O_APPEND | os.O_CREATE | os.O_WRONLY のようなフラグを付けた os.OpenFile(path, flag, perm) を使用します。

io.Reader および io.Writer: ユニバーサル インターフェイス

Go
type Reader interface { Read(p []byte) (n int, err error) }
type Writer interface { Write(p []byte) (n int, err error) }

標準ライブラリが io.Reader を受け入れる場合はどこでも、ファイル (*os.File)、文字列 (strings.NewReader)、*bytes.Buffer、HTTP 応答 (resp.Body)、解凍器を渡すことができます。io.Writer についても同様です。

Go
// Copy from a Reader to a Writer (e.g. download → file).
n, err := io.Copy(dst, src)

io.Copy はバイト パイプラインの主力製品であり、バッファリングと EOF を正しく処理します。 io.ReadAll(r) は、EOF までのすべてを []byte に読み取ります。

os.Args: CLI 引数

os.Args は文字列のスライスです。インデックス 0 はプログラム名で、実引数の 1 から始まります。

Go
func main() {
    if len(os.Args) < 2 {
        fmt.Fprintln(os.Stderr, "uso: prog <nome>")
        os.Exit(1)
    }
    fmt.Println("ciao", os.Args[1])
}

より構造化された解析 (フラグ、デフォルト、ヘルプ) を行うには、stdlib の flag パッケージ、または cobra などの外部ライブラリを使用します。

os.Stdin、os.Stdout、os.Stderr

これらは 3 つのグローバル *os.File です。io.Reader または io.Writer が受け入れられる場合はどこでも、それらを渡すことができます。

Go
fmt.Fprintln(os.Stderr, "log diagnostico")
io.Copy(os.Stdout, os.Stdin)  // echo

演習

運動#go.m8.l3.e1
試行回数: 0読み込み中…

最初のコマンドライン引数 (os.Args[1]) を出力します。見つからない場合は、「manca argomento」を印刷して戻ります。

エディターを読み込み中…

3 回の試行後に解決策が利用可能になります

運動#go.m8.l3.e2
試行回数: 0読み込み中…

os.WriteFile (権限 0644) を使用して、文字列「ciao」をファイル「out.txt」に書き込みます。エラーを処理します。

エディターを読み込み中…

3 回の試行後に解決策が利用可能になります

Quiz#go.m8.l3.e3
準備完了

os.Args のプログラム名のインデックスは何ですか?

Go
fmt.Println(os.Args[???])
回答の選択肢