hakeの日記

Windows環境でプログラミングの勉強をしています。

Go言語 - 構造体とメソッド

Go言語1.5が公開されたので入替。


構造体とメソッド使用方法の勉強。
注意点として、ポインタ経由で参照渡しされた構造体のフィールドへのアクセス時に *p.hoge のようにアスタリスクをつけるとエラーになる。

package main

import "fmt"

type Test struct{
	Num int              // 先頭が大文字のフィールドはpublic(外部からアクセス可)
	Str string
}

func (t Test) SetStr1(s string){
	t.Str = s                       // tは値渡し(コピー)なのでオリジナルは変更されない。
}

func (t *Test) SetStr2(s string){
	t.Str = s                       // tは参照渡し
}                                       // 左辺を *t.Str とするとエラー


func NewTest(i int, s string) *Test{    // 新しいTest型構造体への参照を返す関数
	return &Test{
		i,
		s,      // '}'を改行する場合は、ここにカンマが必要
	}
}


func main() {

	// 構造体Test型の宣言と、初期化
	var a Test = Test{1,"foo"}              // フィールドの宣言順で初期化
	var b Test = Test{Str: "bar", Num: 2}   // フィールド名を指定して初期化、順番は無関係
	var p *Test = &Test{3, "baz"}           // ポインタで作成した構造体を参照
	q := NewTest(4, "qux")                  // 関数で構造体を作成
	fmt.Printf("type of q : %T\n", q)       //->  type of q : *main.Test
                                                //     q はTEST型構造体へのポインタ



	// フィールド値のリード
	fmt.Println("Num :", a.Num, "String :", a.Str) //-> Num : 1 String : foo
	fmt.Println("Num :", b.Num, "String :", b.Str) //-> Num : 2 String : bar
	fmt.Println("Num :", p.Num, "String :", p.Str) //-> Num : 3 String : baz
	fmt.Println("Num :", q.Num, "String :", q.Str) //-> Num : 4 String : qux

	// フィールド値の変更
	a.Str = "hoge"
	p.Str = "piyo"      //  左辺を *p.Str とするとエラーになる。
	fmt.Println("Num :", a.Num, "String :", a.Str) //-> Num : 1 String : hoge
	fmt.Println("Num :", p.Num, "String :", p.Str) //-> Num : 3 String : piyo


	// レシーバの値渡しメソッド(レシーバのフィールド値を変更できない)
	a.SetStr1("hello")
	fmt.Println("Num :", a.Num, "String :", a.Str) //-> Num : 1 String : hoge


	// レシーバの参照渡しメソッド(レシーバのフィールド値を変更できる)
	a.SetStr2("hello")
	fmt.Println("Num :", a.Num, "String :", a.Str) //-> Num : 1 String : hello
	p.SetStr2("good bye")
	fmt.Println("Num :", p.Num, "String :", p.Str) //-> Num : 3 String : good bye
}