前回のパッケージの関数とメソッド周りに引き続き、Go言語の構造体周りを見ていく。

Go言語のパッケージの関数とメソッドについて


Qtのコードを見ていると、NewQMAinWIndowやらSetLayoutといったNew~、Set~という記述をよく見かける。これを理解するためには、構造体の仕組みをおさらいした方がよさそうなので、もう一度構造体について詳しくみていくことにする。

Go言語でQtのQGroupBoxを使ってみる


構造体は、一つの変数にどのような値のセットをもつか厳格に決めてしまうものである。

構造体 - Wikipedia

Go言語で構造体


例えば、名前と苗字と性別をもったPerson構造体を作ってみる。

今回のコードのディレクトリ構造は下記の通り

dir
├── main.go
└── pac
    └── pac.go

まず、下記のコードを入力してPeson構造体を定義したpackageファイルを用意する。

package pac

type Person struct {
	Name    string
	Reading string
	Gender  string
}

次に、main.goでPerson構造体を持った変数にデータを入力して表示してみる。

package main

import (
	"fmt"

	"./pac" //手動で呼び出す
) 

func main() {
	//各フィールドの値が空のPerson構造体を持ったperson変数を作成する
	person := new(pac.Person)

	//person変数の各フィールドに値を入れる
	person.Name = "ryoko"     
	person.Reading = "saito"
	person.Gender = "F"
	fmt.Println(person)
}

実行すると

&{ryoko saito F}

と表示される

この場合、上記と全く同じ表示をする方法として、maim.goに下記のように入力する方法もある。

※pac.Personの頭にある&の意味はここではまだ触れないので省略

//読み込むときに値を指定して読み込む方法
person := &pac.Person{Name: "ryoko", Reading: "saito", Gender: "F"}



次に、小文字で構造体のフィールド名を決める場合の方法を書く。

Go言語ではパッケージ内の関数名や構造体のフィールド名を大文字で始めるかの有無によってコードの振る舞いが変わってくる。


下記のように小文字でフィールド名を書いて

type Person struct {
	name    string
	reading string
	gender  string
}

main.goで

package main

import (
	"fmt"

	"./pac" //手動で呼び出す
) 

func main() {
	//各フィールドの値が空のPerson構造体を持ったperson変数を作成する
	person := new(pac.Person)

	//person変数の各フィールドに値を入れる
	person.name = "ryoko"     
}

小文字のnameフィールドに直接値を入れようとすると下記のエラーが発生してしまう。

person.name undefined (cannot refer to unexported field or method name)

パッケージにある構造体で小文字から始まるフィールドを他のパッケージ内で使用するとエラーになる。

小文字のフィールドにアクセスするために、自分でパッケージ内に関数(メソッド)を作る。下記のように小文字で作成したパッケージ内にメソッドを作ってみる。構造体を呼び出して、各値が空のフィールドを作って返す。

package pac

type Person struct {
	name    string
	reading string
	gender  string
}

func NewPerson() *Person {
	return new(Person)
}

//構造体Personからnameフィールドの値を取得する関数
//p *PersonのpはPerson型の構造体の値が入った変数
func (p *Person) GetName() string {  
	return p.name
}

//構造体personのnameフィールドに第一引数に入っている文字列をセットする
func (p *Person) SetName(name string) {  
	//p.nameのpはすでに用意した構造体。右辺のnameはSetNameの第一引数
	p.name = name
}

main.goのmain関数内での各フィールドへの値の入れ方は、

package main

import (
	"fmt"

	"./pac"
)

func main() {
	//下記のコードはperson := new(pac.Person)と同義
	person := pac.NewPerson()
	//person.name = "ryoko"
	person.SetName("ryoko")
	fmt.Println(person)
}

となる。