fmt パッケージ入門ガイド
多くの人が Go 言語に入門する際、公式サイトのfmt.Println("Hello World")
から始めることが多いです。この記事では、fmt
パッケージが他にどのようなことができるのかを詳しく見ていきましょう。
Go 言語では、fmt パッケージを使用してフォーマットされた入出力操作を行うことがよくあります。ほとんどの場合、Print...、Sprint...、Errorf などの少数の関数しか使用せず、一般的なプレースホルダーのみを使いますが、これは fmt パッケージの他の特性を理解する必要がないことを意味しません。
fmt パッケージの概要#
fmt パッケージは、C 言語に似たフォーマットされた入出力関数を実装しています。
Print 系列関数#
func Print(a ...interface{}) (n int, err error)
func Printf(format string, a ...interface{}) (n int, err error)
func Println(a ...interface{}) (n int, err error)
Print 系列関数は、内容を標準出力に出力します。Print 関数は内容を直接出力し、Printf はフォーマットされた出力をサポートし、Println は毎回出力する内容の後に改行文字を追加します。
例えば:
fmt.Print("123")
fmt.Printf("%d", 456)
fmt.Print("789")
fmt.Printf("%d\n", 123)
fmt.Println("123")
fmt.Println("456")
出力:
123456789123
123
456
Sprint 系列関数#
func Sprint(a ...interface{}) string
func Sprintf(format string, a ...interface{}) string
func Sprintln(a ...interface{}) string
Sprint 系列関数は、内容を文字列として出力します。違いは、Sprint が内容を直接出力し、Sprintf が後ろの内容を対応するプレースホルダーにマッピングし、Sprintln が内容の後に改行文字を追加することです。
例えば:
s1 := fmt.Sprint("123")
s2 := fmt.Sprintf("name:%s,age:%d", "Lixin", 21)
s3 := fmt.Sprintln("456")
fmt.Println(s1, s2, s3)
出力:
123 name:Lixin,age:21 456
Fprint 系列関数#
func Fprint(w io.Writer, a ...interface{}) (n int, err error)
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
Fprint 系列関数は、内容を io.Writer インターフェースを実装した変数に出力します。一般的な使い方は、ファイルに内容を書き込むことですが、端末に出力することもできます(あまり一般的ではありません)。
例えば、標準出力に内容を書き込む:
fmt.Fprintln(os.Stdout, "標準出力に内容を書き込む")
fileObj, err := os.OpenFile("./output.txt", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
panic(err)
}
name := "Lixin"
// 開いたファイルハンドルに内容を書き込む
fmt.Fprintf(fileObj, "ファイルに情報を書き込む\nname: %s\nage: %d", name, 21)
出力される内容は:
標準出力に内容を書き込む
ファイル output.txt
の内容は:
ファイルに情報を書き込む
name: Lixin
age: 21
Errors#
Errorf は Printf に似ていますが、その文字列を含むエラーを返します。
通常、私たちはこのようなエラーを返します:
var err error
// ...
return fmt.Errorf("Error: %v", err)
Scan 系列関数#
func Scan(a ...interface{}) (n int, err error)
func Scanf(format string, a ...interface{}) (n int, err error)
func Scanln(a ...interface{}) (n int, err error)
Scan 系列関数は、標準入力からテキストをスキャンし、format パラメータで指定された形式に基づいて対応する値を a... のパラメータにマッピングします。
Scan 関数は空白で入力値を区別し、Scanf は format で値を区別し、Scanln は改行でスキャンを停止します。
例えば:
var name string
var age int
fmt.Scanln(&name, &age)
fmt.Printf("name: %s, age: %d", name, age)
入力 Lixin 21
、出力:
name: Lixin, age: 21
Scanf の例:
var name string
var age int
fmt.Scanf("name:%s age:%d", &name, &age)
fmt.Printf("name: %s, age: %d", name, age)
入力 name:Lixin age:21
、出力:
name: Lixin, age: 21
Fscan 系列関数#
func Fscan(r io.Reader, a ...interface{}) (n int, err error)
func Fscanln(r io.Reader, a ...interface{}) (n int, err error)
func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)
Fscan 系列関数は、標準入力からデータを読み取ることができます。例えば、ファイルやコマンドラインからの入力です。
ファイルから内容を読み取る場合:
var s string
f, _ := os.OpenFile("./output.txt", os.O_CREATE|os.O_RDWR, 0644)
reader := bufio.NewReader(f)
fmt.Fscan(reader, &s)
fmt.Printf("読み取った文字列は:%s", s)
もしファイル output.txt
の内容が file.Outputn ame: Lixinage: 21
であれば、出力は 読み取った文字列は:file.Outputn
になります。なぜなら、Fscan はデフォルトで空白を区切り文字として使用し、空白の後の内容を認識できないからです。
標準入力から内容を読み取る場合は、以下のコードを使用できます:
var s string
reader := bufio.NewReader(os.Stdin)
fmt.Fscan(reader, &s)
fmt.Printf("あなたの入力内容は:%s", s)
入力 Hello, Lixin
、出力 あなたの入力内容は:Hello
、同様にこの関数は空白を認識できません。
Fscanln 関数は改行文字でスキャンを停止し、Fscanf は Scanf に似ており、対応する改行文字をマッピングするために使用されます。この 2 つの関数の使い方は似ています。
また、ここで bufio パッケージの ReadString 関数についても触れておきます。この関数は指定された io.Reader から 1 行の文字列を読み取り、指定された区切り文字に達するまで読み取ります。関数のシグネチャは以下の通りです:
func (b *Reader) ReadString(delim byte) (string, error)
例えば、ファイル output.txt
の最初の行を読み取り、空白を区切り文字として使用する場合は、次のように書けます:
f, _ := os.OpenFile("./output.txt", os.O_RDWR, 0644)
reader := bufio.NewReader(f)
line, err := reader.ReadString(' ')
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("読み取った文字列は:%s", line)
もしファイル output.txt
の内容が file.Outputn ame: Lixinage: 21
であれば、出力は 読み取った文字列は:file.Outputn
になります。なぜなら、ReadString は空白に出会った時点で読み取りを停止するからです。
Sscan 系列関数#
func Sscan(str string, a ...interface{}) (n int, err error)
func Sscanln(str string, a ...interface{}) (n int, err error)
func Sscanf(str string, format string, a ...interface{}) (n int, err error)
Sscan は、文字列からデータを読み取り、指定された変数にフォーマットするための関数です。
例えば:
str := "1 2 3"
var a, b, c int
n, err := fmt.Sscan(str, &a, &b, &c)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("読み取った数は %d 個で、それぞれ:%d,%d,%d", n, a, b, c)
この関数を実行すると、出力は:
読み取った数は 3 個で、それぞれ:1,2,3
Go 言語のfmt
パッケージには、フォーマットされた出力に使用できる一般的なプレースホルダーがいくつかあります。以下は、いくつかの一般的なプレースホルダーとその使用方法です:
%v
:汎用のプレースホルダーで、任意の型の値をフォーマットできます。値の型に応じて適切な形式が自動的に選択されます。%d
:整数型(符号付き整数および符号なし整数)をフォーマットするために使用されます。%f
:浮動小数点数型をフォーマットするために使用されます。%s
:文字列型をフォーマットするために使用されます。%t
:ブール型をフォーマットするために使用されます。%c
:文字型をフォーマットするために使用されます。%p
:ポインタ型をフォーマットするために使用されます。
以下は、これらのプレースホルダーを使用する方法を示すいくつかの例です:
name := "Lixin"
age := 21
pi := 3.14159
isStudent := true
fmt.Printf("Name: %s, Age: %d\n", name, age) // 出力:Name: Lixin, Age: 21
fmt.Printf("Pi: %.2f\n", pi) // 出力:Pi: 3.14
fmt.Printf("Is student: %t\n", isStudent) // 出力:Is student: true
フォーマットされた文字列では、プレースホルダーはパーセント記号 %
の後に文字が続く形で表されます。%d
や %f
などのプレースホルダーの後に追加のパラメータを加えてフォーマットの方法を制御することができます。例えば、%f
プレースホルダーは .2
を使用して浮動小数点数を小数点以下 2 桁に制限できます。
Printf
関数の他にも、Sprintf
やFprintf
などの関数でもこれらのプレースホルダーを使用できます。Sprintf
関数はフォーマットされた結果を文字列として返し、Fprintf
関数はフォーマットされた結果を指定されたio.Writer
に書き込みます。
result := fmt.Sprintf("Name: %s, Age: %d", name, age)
fmt.Println(result) // 出力:Name: Lixin, Age: 21
file, _ := os.Create("output.txt")
fmt.Fprintf(file, "Name: %s, Age: %d", name, age)
file.Close()
まとめ#
これらはfmt
パッケージで一般的なプレースホルダーとその使用方法です。具体的な詳細については公式サイトを参照してください。そこには非常に詳しく書かれています。