エンジニアになりたい人募集!X(旧Twitter)からフォローしたらリプライで質問常時OK!

【ステップ6】Go言語でのコンソールからの入力と出力

はじめに

本記事は全30ステップで学ぶGolangをテーマにしたGolang学習フローステップ6です。
この記事へ直接訪問された方は、ぜひ下記の記事を参考に自身の理解度をふまえて学習を開始してみてください。

【全30ステップ】Golangで始めるプログラミング学習

前回までのあらすじ

前回のステップでは、Go言語の基本的な演算子と式について学びました。算術演算子、比較演算子、論理演算子の使い方と、Go言語特有の演算子について理解を深めました。今回は、これらの知識を活用しながら、プログラムとユーザーがやり取りする方法、つまりコンソールからの入力と出力について学んでいきます。

【ステップ5】Go言語の基本的な演算子と式

Go言語の標準入出力

Go言語では、fmtパッケージを使用して標準入出力を扱います。このパッケージは、フォーマット済みの入出力機能を提供しています。

またGithubからリポジトリをクローンした方は各項目に記載の sampleXexercisesX がコードとリンクしています。

1. 標準出力

fmt.Println関数を使用して、コンソールに文字列や変数の値を出力できます。

標準出力を使ったサンプルと実行結果: sample1

最も基本となるコンソール出力 fmtPrintln を使ったサンプルを紹介します

go
package main

import "fmt"

func main() {
    name := "Alice"
    age := 25
    fmt.Println("Name:", name, "Age:", age)
}
result
Name: Alice Age: 25

fmtパッケージにはPrintを冠する物が複数あり、使い分ける必要がありますが今は最も使うPrintlnを覚えましょう。

2. フォーマット済み出力

fmt.Printf関数を使用すると、フォーマット指定子を用いてより細かく出力をコントロールできます。

出力フォーマットを指定したサンプルと実行結果: sample2

文章に変数の中身を含めたいケースはたくさんあります。そんなときに使えるのがこれですので、マスターしましょう!

go
package main

import "fmt"

func main() {
    name := "Bob"
    age := 30
    height := 175.5

    fmt.Printf("Name: %s, Age: %d, Height: %.1f cm\n", name, age, height)

    pi := 3.14159
    fmt.Printf("Pi is approximately %.2f\n", pi)
}
result
Name: Bob, Age: 30, Height: 175.5 cm
Pi is approximately 3.14

主なフォーマット指定子には次の物があります。

  • %s: 文字列
  • %d: 整数
  • %f: 浮動小数点数
  • %t: ブール値
  • %v: 任意の値(デフォルトフォーマット)

よく使うテクニックはに次の物があります。

go
num := 3
fmt.Printf("数値をゼロパディングして表示する: %03d", num) // 数値をゼロパディングして表示する: 003
num = 13
fmt.Printf("数値をゼロパディングして表示する:%03d", num)  // 数値をゼロパディングして表示する: 013

任意の桁数に前ゼロをつけて調整するいわゆるゼロパディング処理が簡単にできます。

要件としても頻出しますし、当ブログへの検索ワードとしても結構数があるので抑えておくと良いでしょう!

3. 標準入力

fmt.Scan関数を使用して、ユーザーからの入力を受け取ることができます。

標準入力を使ったサンプルと実行結果: sample3

プログラムは時に利用者の入力を元に動作する必要があります。
そんな時に使われるのがこの標準入力です。

go
package main

import "fmt"

func main() {
    var name string
    var age int

    fmt.Print("Enter your name: ")
    fmt.Scan(&name)

    fmt.Print("Enter your age: ")
    fmt.Scan(&age)

    fmt.Printf("Hello, %s! You are %d years old.\n", name, age)
}
result
Enter your name: Charlie
Enter your age: 35
Hello, Charlie! You are 35 years old.

注意: fmt.Scanは空白文字で区切られた入力を読み取ります。複数の単語を含む文字列を読み取るには、fmt.Scanlnbufio.NewReaderを使用する必要があります。

エラーハンドリング

入力関数は通常、成功したかどうかを示すエラー値を返します。これを使ってエラーハンドリングを行うことができます。

入力時のエラーハンドリングのサンプルと実行結果: sample4

入力処理は常に開発者の意図した値が受け取れるとは限りません。
間違って入力してしまった(タイポ)だけではなく、悪意を持ってプログラムを破壊するための入力をする人もいます。

それらに対して適切な処理をすることも重要となってきます。

go
package main

import (
    "fmt"
    "log"
)

func main() {
    var age int

    fmt.Print("Enter your age: ")
    _, err := fmt.Scan(&age)
    if err != nil {
        log.Fatal("Error reading age:", err)
    }

    fmt.Printf("You are %d years old.\n", age)
}

実践的な演習問題

問1:年齢を計算するプログラムを作成してください: exercises1

ユーザに名前と生年月日(年、月、日)を入力してもらい、その人の年齢を計算して表示するプログラムを作成してください。
現在の日付は time.Now() で取得できます。

クリックして答えを見る
go
package main

import (
	"fmt"
	"log"
	"time"
)

func main() {
	var year, month, day, age int
	var err error
	fmt.Println("生まれた年を入力してください")
	_, err = fmt.Scan(&year)
	if err != nil {
		log.Fatalln("生まれた年の入力にエラーがあります:", err)
	}
	fmt.Println("生まれた月を入力してください")
	_, err = fmt.Scan(&month)
	if err != nil {
		log.Fatalln("生まれた月の入力にエラーがあります:", err)
	}
	fmt.Println("生まれた日を入力してください")
	_, err = fmt.Scan(&day)
	if err != nil {
		log.Fatalln("生まれた日の入力にエラーがあります:", err)
	}
	birthdate := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.Local)
	curYear, curMonth, curDay := time.Now().Local().Date()
	age = curYear - year
	// 誕生日を超えていない場合は-1する
	if curMonth < birthdate.Month() || (curMonth == birthdate.Month() && curDay < birthdate.Day()) {
		age--
	}
	fmt.Println(fmt.Sprintf("あなたは%d歳です", age))
    
}

誕生日を超えているかどうかはifを用いて判断します。こちらはステップ7で学習する内容なのでできていなくても問題ありません。

問2:簡単な計算機プログラムを作成してください: exercises2

ユーザーに2つの数値と演算子(+, -, *, /)を入力してもらい、結果を表示します。
発展:ゼロ除算のエラーハンドリングも行ってください(ステップ7での学習内容を含みます)

クリックして答えを見る
go
package main

import (
	"fmt"
	"log"
)

func main() {
	var num1, num2 int
	var res int
	var operator string
	var err error
	
	fmt.Println("数値1を入力してください")
	_, err = fmt.Scan(&num1)
	if err != nil {
		log.Fatalln("数値1の入力にエラーがあります:", err)
	}
	fmt.Println("数値2を入力してください")
	_, err = fmt.Scan(&num2)
	if err != nil {
		log.Fatalln("数値2の入力にエラーがあります:", err)
	}
	fmt.Println("演算子を入力してください(+,-.*,/)")
	_, err = fmt.Scan(&operator)
	if err != nil {
		log.Fatalln("演算子の入力にエラーがあります:", err)
	}
	
	if num2 == 0 && operator == "/" {
		log.Fatalln("ゼロでの除算はできません")
	}
	
	switch operator {
	case "+":
		res = num1 + num2
	case "-":
		res = num1 - num2
	case "*":
		res = num1 * num2
	case "/":
		res = num1 / num2
	default:
		log.Fatalln("演算子の入力が不正です")
	}
	fmt.Println(fmt.Sprintf("%d %s %d = %d です", num1, operator, num2, res))
}

ゼロ除算の判定はifを用いて行います。こちらはステップ7での学習内容なので、出来ていなくても大丈夫です。
入力2の数値と演算子を確認することで判断できますね!

サンプルと演習問題の動くコードを公開!

Githubにて各ステップのコードを公開しています。cloneして動かしてみたり、手を入れて理解を深めてください。
ぜひStarでの評価をお願いします!

次のステップへのつながり

コンソールからの入力と出力の基本を理解したことで、ユーザーとやり取りする対話的なプログラムを作成できるようになりました。次のステップでは、条件分岐(if文)について学びます。これにより、プログラムの流れを制御し、異なる条件に応じて異なる動作をするプログラムを作成できるようになります。

【ステップ7】Go言語での条件分岐、if文の基礎

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)