メソッド
構造体を含むデータに紐づけた関数のことをメソッドという。
型に紐づくメソッドを作成する
構造体にメソッドを作成して呼び出してみる。まず、int型のXとYを持つ構造体Vertexを宣言する。
引数が構造体Vertexの変数v、返り値がint型のArea関数を作る。この関数は。「v.X*v.Y」を返す。main関数で変数vを初期化してArea関数を実行すると12が表示される。
type Vertex struct {
int X,Y
}
func Area(v Vertex) int {
return v.X * v.Y
}
func main() {
v := Vertex{3, 4}
fmt.Println(Area(v))
}
//以下のように表示される
12
次に関数Areaを構造体Vertexに結び付けたメソッドとして定義する。
メソッド作成時は「func (v Vertex) Area() int」のように、funcのあとに()をつけてそのなかにレシーバーと呼ばれる引数の名前と型を指定する。これにより、Vertex型のレシーバーvを持ち、返り値がint型のAreaメソッドが作成される。レシーバーが型とメソッドを紐づける役割を持つ。
メソッドを呼び出すためには、「v.Area()」のようにメソッドを結び付けた構造体の変数とメソッド名を.でつないで実行する。
type Vertex struct {
X,Y int
}
func (v Vertex) Area() int { //メソッドを定義
return v.X * v.Y
}
func main() {
v :={3,4}
fmt.Println(v.Area()) //メソッドを実行
}
//以下のように出力される
12
※メソッドを使う利点
関数を使う場合関数名を把握していないと関数が使えないが、メソッドとして作成すると、「v.Area()」ように構造体とメソッドの紐づけがコードからわかりやすくなる。また、構造体さえわかればVSCodeなどの機能でメソッド名が補完されて表示されるようになるというメリットもある。
ポインタレシーバと値レシーバ
メソッドで紐づけられた構造体の値を変えたい場合は、メソッド作成時にレシーバーにを付ける。
ここでは、ScaleというVertexのメソッドを「func (v Vertex) Scala(i int)」のように書いて作成し、XとYの値を書き換えてみる。iのintという引数を取り、メソッドの中でXとYそれぞれの値を「v.X = v.Xi」「v.Y = v.Yi」と書き換える
func (v *Vertex) Scale (i int) {
v.X = v.X * i
v.Y = v.Y * i
}
func main() {
v := Vertex{3,4}
v.Scale(10)
fmt.Println(v.Area())
}
//以下のように出力される
1200
Scaleメソッドを実行しAreaメソッドでXとYの積を表示すると、1200になるため、ScaleメソッドでXとYの値が書き換えられていることが分かる。
レシーバにポインタの*を書くことで、Vertexに紐づけられたScaleというメソッド内で構造体の中身を書き換えることができる。これをポインタレシーバという。
一方で、レシーバに*を書かない場合は、構造体の参照ではなく値をコピーして渡しているので、値レシーバという。
Newで初期化時の処理を実行する
Pythonにおける__initi__のような、初期化時に実行される処理(コンストラクタ)は、GoではNewという関数を作成して行う。
New関数を作成する。まず、VertexのXとYを小文字に置き換える。小文字にすることで他のパッケージから操作することはできず、このパッケージ内からのみ書き換えができるようになる
type Vertex struct {
x,y int
}
次にNew関数の作成を行う。引数にint型のx,y、返り値に*Vertex(Vertexのポインタ)を設定し、処理にはreturn &Vertex{x,y}と書く。この実行をすると1200が表示される
func New(x,y int) *Vertex{
return &Vertex{x,y}
}
func main() {
v := New(3,4)
v.Scale(10)
fmt.Println(Area())
}
//以下のように表示される
1200
構造体以外の型のメソッド
typeを使うと、組み込み型に新しい名前を付けた独自の型を作ることが可能で、その独自の型にメソッドを持たせることができる。ここでは、int型にMyintという別の名前を付けて新しい型を作る。
また、作成したMyint型にint型の返り値を返すDoubleメソッドを作成してiに2をかけた値をint型で返す。
tyope Myint int
func (i Myint) Double() int {
return int(i * 2)
}
func main() {
myInt := Myint(10)
fmt.Println(myInt.Double())
}
//以下のように出力される
20
学習に使用した教材
・『入門】Golang基礎入門 + 各種ライブラリ + 簡単なTodoWebアプリケーション開発(Go言語)』M.A EduTech
https://www.udemy.com/course/golang-webgosql/?utm_medium=udemyads&utm_source=bene-msa&utm_campaign=responsive&utm_content=top-1&utm_term=general&msclkid=81e2f24a32cc185d275d953d60760226&couponCode=NEWYEARCAREERJP
・『シリコンバレー一流プログラマーが教える Goプロフェッショナル大全』酒井 潤 (著)
https://www.amazon.co.jp/%E3%82%B7%E3%83%AA%E3%82%B3%E3%83%B3%E3%83%90%E3%83%AC%E3%83%BC%E4%B8%80%E6%B5%81%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%83%BC%E3%81%8C%E6%95%99%E3%81%88%E3%82%8B-Go%E3%83%97%E3%83%AD%E3%83%95%E3%82%A7%E3%83%83%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%AB%E5%A4%A7%E5%85%A8-%E9%85%92%E4%BA%95-%E6%BD%A4/dp/4046070897