コンテンツにスキップ

Go/Standard library/fmt

出典: フリー教科書『ウィキブックス(Wikibooks)』

fmtパッケージの概要

[編集]

fmtパッケージは、Go言語において最も頻繁に使用されるパッケージの一つです。このパッケージは、フォーマットされた入出力機能を提供し、テキストの出力、入力、文字列の整形などを行うことができます。

fmtパッケージの主な機能:
  • 標準出力への出力
  • 動詞を使用した文字列整形
  • 標準入力からの読み取り
  • 文字列の作成と変換

基本的な出力関数

[編集]

Print系関数

[編集]

fmtパッケージには、出力を行うための3つの基本的な関数があります。

package main

import "fmt"

func main() {
	// Print - 引数を出力(改行なし)
	fmt.Print("Hello")
	fmt.Print("World")
	// 出力: HelloWorld

	// Println - 引数を出力して改行
	fmt.Println("Hello")
	fmt.Println("World")
	// 出力:
	// Hello
	// World

	// Printf - 動詞を使用
	name := "太郎"
	age := 25
	fmt.Printf("名前: %s, 年齢: %d\n", name, age)
	// 出力: 名前: 太郎, 年齢: 25
}

各関数の特徴

[編集]
  • Print(): 引数をそのまま出力し、改行は行いません
  • Println(): 引数を出力した後に改行を追加します
  • Printf(): 動詞を使用して、より柔軟な出力が可能です

動詞

[編集]

Printf関数で使用する動詞(verbs)は、出力の形式を制御する重要な機能です。

基本的な動詞

[編集]
package main

import "fmt"

func main() {
	// 一般的な値の出力
	fmt.Printf("%v\n", 42)  // 42
	fmt.Printf("%+v\n", 42) // +42
	fmt.Printf("%#v\n", 42) // 42
	fmt.Printf("%T\n", 42)  // int

	// 文字列
	fmt.Printf("%s\n", "Hello") // Hello
	fmt.Printf("%q\n", "Hello") // "Hello"
	fmt.Printf("%x\n", "Hello") // 48656c6c6f

	// 整数
	fmt.Printf("%d\n", 42) // 42
	fmt.Printf("%b\n", 42) // 101010
	fmt.Printf("%o\n", 42) // 52
	fmt.Printf("%x\n", 42) // 2a
	fmt.Printf("%X\n", 42) // 2A

	// 浮動小数点数
	fmt.Printf("%f\n", 3.14159)   // 3.141590
	fmt.Printf("%.2f\n", 3.14159) // 3.14
	fmt.Printf("%e\n", 3.14159)   // 3.141590e+00
	fmt.Printf("%g\n", 3.14159)   // 3.14159

	// ブール値
	fmt.Printf("%t\n", true) // true

	// ポインタ
	x := 42
	fmt.Printf("%p\n", &x) // 0xc0000140a8(メモリアドレス)
}
動詞の詳細
指定子 説明
%v デフォルトフォーマット 42, "hello"
%+v 構造体のフィールド名付き {Name:太郎 Age:25}
%#v Go構文表現 []string{"a", "b"}
%T 型情報 int, string
%s 文字列 hello
%q クォート付き文字列 "hello"
%d 10進数 42
%b 2進数 101010
%o 8進数 52
%x 16進数(小文字) 2a
%X 16進数(大文字) 2A
%f 浮動小数点数 3.141590
%e 指数表記(小文字) 3.141590e+00
%E 指数表記(大文字) 3.141590E+00
%g 短い方の%fまたは%e 3.14159
%G 短い方の%fまたは%E 3.14159
%t ブール値 true
%p ポインタ 0xc0000140a8

幅と精度の指定

[編集]

動詞には、出力の幅や精度を指定することができます。

package main

import "fmt"

func main() {
	// 幅の指定
	fmt.Printf("|%5d|\n", 42)  // |   42|
	fmt.Printf("|%-5d|\n", 42) // |42
	fmt.Printf("|%05d|\n", 42) // |00042|

	// 浮動小数点の精度指定
	fmt.Printf("%.2f\n", 3.14159)  // 3.14
	fmt.Printf("%8.2f\n", 3.14159) // 3.14(幅8、精度2)

	// 文字列の幅指定
	fmt.Printf("|%10s|\n", "Hello")  // |     Hello|
	fmt.Printf("|%-10s|\n", "Hello") // |Hello
	fmt.Printf("|%.3s|\n", "Hello")  // |Hel|
}

Sprint系関数

[編集]

Sprint系関数は、出力する代わりに文字列を返します。

package main

import "fmt"

func main() {
	// Sprint - 文字列として返す
	str1 := fmt.Sprint("Hello", "World")
	fmt.Println(str1) // HelloWorld

	// Sprintln - 改行付きで文字列として返す
	str2 := fmt.Sprintln("Hello", "World")
	fmt.Println(str2) // Hello World\n

	// Sprintf - 動詞を使用
	name := "太郎"
	age := 25
	str3 := fmt.Sprintf("名前: %s, 年齢: %d", name, age)
	fmt.Println(str3) // 名前: 太郎, 年齢: 25
}

Fprint系関数

[編集]

Fprint系関数は、指定したio.Writerに出力を行います。

package main

import (
	"fmt"
	"os"
	"strings"
)

func main() {
	// 標準出力に出力
	fmt.Fprint(os.Stdout, "Hello, World!\n")

	// 標準エラー出力に出力
	fmt.Fprint(os.Stderr, "Error message\n")

	// strings.Builderに出力
	var builder strings.Builder
	fmt.Fprint(&builder, "Hello, ")
	fmt.Fprint(&builder, "World!")
	fmt.Println(builder.String()) // Hello, World!
}

入力関数

[編集]

fmtパッケージには、標準入力から読み取りを行う関数も含まれています。

package main

import "fmt"

func main() {
	var name string
	var age int

	// Scan - 空白区切りで読み取り
	fmt.Print("名前と年齢を入力してください: ")
	fmt.Scan(&name, &age)
	fmt.Printf("名前: %s, 年齢: %d\n", name, age)

	// Scanln - 改行まで読み取り
	var input string
	fmt.Print("一行入力してください: ")
	fmt.Scanln(&input)
	fmt.Printf("入力: %s\n", input)

	// Scanf - フォーマット指定で読み取り
	var x, y int
	fmt.Print("2つの数値を 'x,y' の形式で入力してください: ")
	fmt.Scanf("%d,%d", &x, &y)
	fmt.Printf("x=%d, y=%d\n", x, y)
}

構造体の出力

[編集]

構造体を出力する際の動詞の使い分けを理解することは重要です。

package main

import "fmt"

type Person struct {
	Name string
	Age  int
}

func main() {
	p := Person{Name: "太郎", Age: 25}

	fmt.Printf("%v\n", p)  // {太郎 25}
	fmt.Printf("%+v\n", p) // {Name:太郎 Age:25}
	fmt.Printf("%#v\n", p) // main.Person{Name:"太郎", Age:25}
	fmt.Printf("%T\n", p)  // main.Person
}

エラーハンドリング

[編集]

入力関数を使用する際は、エラーハンドリングを適切に行うことが重要です。

package main

import (
	"fmt"
	"log"
)

func main() {
	var number int

	fmt.Print("数値を入力してください: ")

	if n, err := fmt.Scan(&number); err != nil {
		log.Printf("入力エラー: %v", err)
		return
	} else {

		fmt.Printf("読み取った項目数: %d\n", n)
		fmt.Printf("入力された数値: %d\n", number)
	}
}

カスタムフォーマット

[編集]

独自の型にカスタムフォーマットを実装することも可能です。

package main

import "fmt"

type Point struct {
	X, Y int
}

// String メソッドを実装すると %s や %v で使用される
func (p Point) String() string {
	return fmt.Sprintf("(%d, %d)", p.X, p.Y)
}

func main() {
	p := Point{X: 3, Y: 4}
	fmt.Printf("%s\n", p) // (3, 4)
	fmt.Printf("%v\n", p) // (3, 4)
}

パフォーマンス考慮事項

[編集]

fmtパッケージの使用においては、パフォーマンスを考慮する場面があります。

package main

import (
	"fmt"
	"strings"
)

func main() {
	// 効率的でない例
	result := ""
	for i := range 1000 {
		result += fmt.Sprintf("Item %d\n", i)
	}

	// より効率的な例
	var builder strings.Builder
	for i := range 1000 {
		fmt.Fprintf(&builder, "Item %d\n", i)
	}
	result = builder.String()
}

実践的な使用例

[編集]

ログ出力

[編集]
package main

import (
	"fmt"
	"os"
	"time"
)

func logMessage(level, message string) {
	timestamp := time.Now().Format("2006-01-02 15:04:05")
	fmt.Fprintf(os.Stderr, "[%s] %s: %s\n", timestamp, level, message)
}

func main() {
	logMessage("INFO", "アプリケーション開始")
	logMessage("ERROR", "ファイルが見つかりません")
}

テーブル形式の出力

[編集]
package main

import "fmt"

type Product struct {
	Name  string
	Price int
	Stock int
}

func main() {
	products := []Product{
		{"リンゴ", 100, 50},
		{"バナナ", 80, 30},
		{"オレンジ", 120, 20},
	}

	fmt.Printf("%-10s %5s %5s\n", "商品名", "価格", "在庫")
	fmt.Println("------------------------")

	for _, p := range products {
		fmt.Printf("%-10s %5d %5d\n", p.Name, p.Price, p.Stock)
	}
}

まとめ

[編集]

fmtパッケージは、Go言語における基本的かつ重要なパッケージです。適切に使用することで、読みやすく保守性の高いコードを書くことができます。

重要なポイント:
  • Print系関数の使い分け
  • 動詞の理解
  • エラーハンドリングの重要性
  • パフォーマンスを考慮した使用方法

次の章では、Go言語のエラーハンドリングについて詳しく学習します。

練習問題

[編集]
  1. 以下の出力を生成するプログラムを書いてください:
    名前: 田中太郎
    年齢: 30歳
    身長: 175.5cm
    
  2. 標準入力から2つの整数を読み取り、その和、差、積、商を表示するプログラムを作成してください。
  3. 構造体を定義し、%v、%+v、%#vの違いを確認するプログラムを作成してください。
  4. 1から100までの数値を、5列のテーブル形式で出力するプログラムを作成してください。