Go練習問題3-☆1:レベル3の文法を総復習しよう

記事内に商品プロモーションを含む場合があります

Go言語の初心者向け問題3-☆1:レベル3の文法を総復習しよう

この問題を解くために必要な知識:
レベル1~2の知識関数の定義と呼び出し関数の戻り値と複数の戻り値関数の可変長引数無名関数(匿名関数)クロージャ構造体の定義コンストラクタ関数構造体の埋め込みメソッドの定義とレシーバインターフェース型アサーション型スイッチ

<<前の問題 問題集Top 次の問題>>

Go練習問題3-☆1:レベル3の文法を総復習しよう




レベル3で学習した全ての文法について、身についているか確認しましょう。

この問題の要件

以下のコードをコピーし、コメントに従って完成させましょう。

package main

import (
    "fmt"
)

// 基本的な情報を持つ構造体
/*【穴埋め問題1】 
ここにBasicInfoという構造体を作成し、name(string型)とage(int型)というフィールドを持たせるコードを書いてください。
*/

// メソッドを定義(レシーバはBasicInfo型)
/*【穴埋め問題2】
ここにBasicInfo型のレシーバを持つShowBasicInfoメソッドを作成し、名前と年齢を表示するコードを書いてください。
*/

// 職業を追加するための構造体
/*【穴埋め問題3】
ここにJobInfoという構造体を作成し、jobTitle(string型)とsalary(int型)というフィールドを持たせるコードを書いてください。
*/

// 構造体の埋め込みを使ってBasicInfoとJobInfoを持つEmployee構造体を作成
/*【穴埋め問題4】
ここにEmployeeという構造体を作成し、BasicInfoとJobInfoを埋め込むコードを書いてください。
*/

// メソッドを定義(レシーバはEmployee型)
/*【穴埋め問題5】
ここにEmployee型のレシーバを持つShowEmployeeInfoメソッドを作成し、BasicInfoとJobInfoの情報を表示するコードを書いてください。
*/

// 複数の戻り値を返す関数
/*【穴埋め問題6】
ここにaddAndSubtractという関数を作成し、2つの整数を受け取り、それらの和と差を返すコードを書いてください。
*/

// 可変長引数を使用する関数
/*【穴埋め問題7】
ここにsumという関数を作成し、可変長引数を使用して整数の合計を返すコードを書いてください。
*/

func main() {
    // Employee構造体の初期化
    /*【穴埋め問題8】
    ここにEmployee構造体を初期化し、BasicInfoに名前と年齢を、JobInfoに職業と給料を代入するコードを書いてください。
    */

    // Employeeの情報を表示
    /*【穴埋め問題9】
    ここにShowEmployeeInfoメソッドを呼び出してEmployeeの情報を表示するコードを書いてください。
    */

    // 関数で複数の戻り値を取得
    /*【穴埋め問題10】
    ここにaddAndSubtract関数を呼び出し、結果をsumResultとdiffResultに格納するコードを書いてください。
    その結果を表示するコードも書いてください。
    */

    // 可変長引数を使った関数の呼び出し
    /*【穴埋め問題11】
    ここにsum関数を呼び出して、合計値をtotalSumに格納し、その結果を出力するコードを書いてください。
    */

    // 無名関数(匿名関数)の使用
    /*【穴埋め問題12】
    ここに無名関数を使って「こんにちは、匿名関数です!」というメッセージを出力するコードを書いてください。
    */

    // クロージャの使用
    /*【穴埋め問題13】
    ここにincrementという関数を使ってクロージャを生成し、カウントを表示するコードを書いてください。
    */

    // 型アサーションの例
    /*【穴埋め問題14】
    ここに型アサーションを使って、変数iの型がstringかどうかを判定し、成功したらその値を表示するコードを書いてください。
    */

    // 型スイッチの例
    /*【穴埋め問題15】
    ここに型スイッチを使って、変数xの型を判定し、その結果に応じてメッセージを表示するコードを書いてください。
    */
}

 

*****↓↓正解コードの実行結果の例↓↓*****

名前: 太郎, 年齢: 30
職業: エンジニア, 給料: 5000000円
和: 15, 差: 5
合計: 15
無名関数からのメッセージ: こんにちは、匿名関数です!
クロージャでのカウント: 1
クロージャでのカウント: 2
型アサーション成功: 型アサーションの例
xはint型です。値: 42

解答例と解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

package main

import (
    "fmt"
)

// 基本的な情報を持つ構造体
type BasicInfo struct {
    name string
    age  int
}

// メソッドを定義(レシーバはBasicInfo型)
func (b BasicInfo) ShowBasicInfo() {
    fmt.Printf("名前: %s, 年齢: %d\n", b.name, b.age)
}

// 職業を追加するための構造体
type JobInfo struct {
    jobTitle string
    salary   int
}

// 構造体の埋め込みを使ってBasicInfoとJobInfoを持つEmployee構造体を作成
type Employee struct {
    BasicInfo // 埋め込み
    JobInfo   // 埋め込み
}

// メソッドを定義(レシーバはEmployee型)
func (e Employee) ShowEmployeeInfo() {
    e.ShowBasicInfo() // 埋め込まれた構造体のメソッドを呼び出し
    fmt.Printf("職業: %s, 給料: %d円\n", e.jobTitle, e.salary)
}

// 複数の戻り値を返す関数
func addAndSubtract(a, b int) (int, int) {
    return a + b, a - b
}

// 可変長引数を使用する関数
func sum(nums ...int) int {
    total := 0
    for _, num := range nums {
        total += num
    }
    return total
}

func main() {
    // Employee構造体の初期化
    employee := Employee{
        BasicInfo: BasicInfo{name: "太郎", age: 30},
        JobInfo:   JobInfo{jobTitle: "エンジニア", salary: 5000000},
    }

    // Employeeの情報を表示
    employee.ShowEmployeeInfo()

    // 関数で複数の戻り値を取得
    sumResult, diffResult := addAndSubtract(10, 5)
    fmt.Printf("和: %d, 差: %d\n", sumResult, diffResult)

    // 可変長引数を使った関数の呼び出し
    totalSum := sum(1, 2, 3, 4, 5)
    fmt.Printf("合計: %d\n", totalSum)

    // 無名関数(匿名関数)の使用
    func(message string) {
        fmt.Println("無名関数からのメッセージ:", message)
    }("こんにちは、匿名関数です!")

    // クロージャの使用
    increment := func() func() int {
        counter := 0
        return func() int {
            counter++
            return counter
        }
    }

    inc := increment()
    fmt.Println("クロージャでのカウント:", inc())
    fmt.Println("クロージャでのカウント:", inc())

    // 型アサーションの例
    var i interface{} = "型アサーションの例"
    s, ok := i.(string)
    if ok {
        fmt.Println("型アサーション成功:", s)
    }

    // 型スイッチの例
    var x interface{} = 42
    switch v := x.(type) {
    case int:
        fmt.Println("xはint型です。値:", v)
    case string:
        fmt.Println("xはstring型です。値:", v)
    default:
        fmt.Println("xは不明な型です。")
    }
}

正解コードの解説

基本情報構造体の定義

type BasicInfo struct {
    name string
    age  int
}

BasicInfoは名前(name)と年齢(age)を持つシンプルな構造体です。

structはGoでデータをまとめるための型で、オブジェクト指向の「クラス」のように使うことができます。

BasicInfoのメソッド定義

func (b BasicInfo) ShowBasicInfo() {
    fmt.Printf("名前: %s, 年齢: %d\n", b.name, b.age)
}

ShowBasicInfoメソッドは、BasicInfoのデータを表示します。

メソッドのレシーバー((b BasicInfo))によって、このメソッドはBasicInfo型に属することが明示されています。

fmt.Printfは、フォーマットに従って文字列を出力するための関数です。

職業情報構造体の定義

type JobInfo struct {
    jobTitle string
    salary   int
}

JobInfoは職業タイトル(jobTitle)と給料(salary)を持つ構造体です。

これもBasicInfoと同様に、職業に関する情報を1つのデータとしてまとめています。

Employee構造体の定義と構造体の埋め込み

type Employee struct {
    BasicInfo // 埋め込み
    JobInfo   // 埋め込み
}

Employeeは、BasicInfoJobInfoを埋め込んでいます。

Goでは「構造体の埋め込み」を使って、ある構造体のフィールドやメソッドを別の構造体に引き継ぐことができます。

これにより、Employeeは名前・年齢・職業・給料というすべての情報を持つことになります。

Employeeのメソッド定義

func (e Employee) ShowEmployeeInfo() {
    e.ShowBasicInfo()
    fmt.Printf("職業: %s, 給料: %d円\n", e.jobTitle, e.salary)
}

ShowEmployeeInfoは、Employeeの全体の情報(名前、年齢、職業、給料)を表示するメソッドです。

e.ShowBasicInfo()とすることで、Employeeに埋め込まれたBasicInfoのメソッドを呼び出しています。

複数の戻り値を返す関数

この関数は、2つの整数abを受け取り、それらの和と差を返します。

Goでは、1つの関数で複数の戻り値を返すことができ、(int, int)と指定することで和と差の両方を返しています。

可変長引数を持つ関数

func sum(nums ...int) int {
    total := 0
    for _, num := range nums {
        total += num
    }
    return total
}

sum関数は、任意の数の整数を受け取り、その合計を返します。...intという書き方は可変長引数を意味し、引数の数が不定の場合に使います。

Employeeの初期化と情報表示

employee := Employee{
    BasicInfo: BasicInfo{name: "太郎", age: 30},
    JobInfo:   JobInfo{jobTitle: "エンジニア", salary: 5000000},
}
employee.ShowEmployeeInfo()

ここでは、Employeeのインスタンスを初期化し、名前と職業などの情報を設定しています。

そして、ShowEmployeeInfoメソッドを呼び出して情報を表示しています。

無名関数(匿名関数)の使用

func(message string) {
    fmt.Println("無名関数からのメッセージ:", message)
}("こんにちは、匿名関数です!")

無名関数は、名前を持たない関数です。ここでは、その場限りの関数を定義してすぐに呼び出す形で使っています。

クロージャの使用

increment := func() func() int {
    counter := 0
    return func() int {
        counter++
        return counter
    }
}
inc := increment()
fmt.Println("クロージャでのカウント:", inc())
fmt.Println("クロージャでのカウント:", inc())

クロージャは、関数がその外の変数を覚えている機能です。

ここでは、increment関数の中で定義されたcounterがクロージャ内で保持され、呼び出されるたびにcounterの値が増えていきます。

型アサーションの例

var i interface{} = "型アサーションの例"
s, ok := i.(string)
if ok {
    fmt.Println("型アサーション成功:", s)
}

interface{}型は任意の型を受け入れる型です。

型アサーションを使って、その型がstringかどうかを確認し、成功した場合には値を取り出します。

型スイッチの例

var x interface{} = 42
switch v := x.(type) {
case int:
    fmt.Println("xはint型です。値:", v)
case string:
    fmt.Println("xはstring型です。値:", v)
default:
    fmt.Println("xは不明な型です。")
}

型スイッチは、ある変数がどの型かを判定する構文です。

このコードでは、xintstringか、あるいはその他の型かを判断して適切なメッセージを表示しています。

<<前の問題 問題集Top 次の問題>>

この問題への質問・コメント

この問題を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    Go練習問題集へ戻る
    トップページへ戻る