Go の関数とメソッドの書き方の違い
関数とメソッド
関数もメソッドも、引数を与えるとそれに基づいた計算結果を返却する。プログラム内で何度も登場する処理を共通化して再利用可能なものにしている。ただし、メソッドはオブジェクト指向において使われる言葉である。オブジェクト指向は、関連するデータとメソッド(手続き)を束ねたオブジェクトという概念を規定する。オブジェクト指向のメソッドと比較すると、関数というのは何らかのオブジェクトに属しているものではない。
Goの関数とメソッド
Goでは関数とメソッドを両方定義し利用できる。
関数
関数は
func 関数名(引数) 戻り値の型 { 処理 return 戻り値 }
の形で定義し、main
関数の中で
関数名(引数(実際に計算させたい値))
の形で呼び出す。
メソッド
メソッドはオブジェクト指向のものなので、メソッドを使う場合はオブジェクトが必要である。ここでのオブジェクトは構造体(struct
)をもとに定義したレシーバである。
まず構造体を定義する。
type 構造体名 struct{ メンバ }
上の構造体定義をベースとして、以下のようにメソッドを定義する。func
で始まるが、関数と違い、すぐそのあとにはカッコが来る。レシーバはメソッドを呼び出される対象である。カッコ内を見るとわかる通りレシーバはあたかも構造体のように定義されている。処理の中身では処理対象の変数はレシーバもしくのメンバとして参照される(レシーバを構造体としてレシーバ.メンバ
のように扱う)。ここは後程出てくるサンプルを見てもらったほうがイメージがわかりやすい。
func (レシーバ名 定義した構造体名) メソッド名() メソッドの戻り値の型 { 処理 return 戻り値 }
メソッドで実際に計算するときは、main
関数の中で構造体のインスタンスを定義し*1、
構造体インスタンス名 := 構造体名{メンバの具体的な数値}
下記のように計算する。関数をイメージするとカッコ内に数値が入っていないのでどんな値を渡しているかわからないように見えるが、実際にメソッドに渡したい値は構造体を定義したときに決まっているので、それで計算できるわけである。
構造体インスタンス名.メソッド名()
サンプル
2つのint
型の数値を加算するプログラム(func-method.go)を考える。以下の例では関数を使ったパターンとメソッドを使ったパターンの両方が記載されている(結果はどちらも同じ)。ただし、Goでは構造体のメンバにメソッドを定義することができないため、メソッドは構造体とは別に定義する。
myaddfunc
が関数であり、引数に3,4
という数値を与えて結果を計算している。
一方、int
型の構造体mystruct
を定義したのち、X
というレシーバに対し、myaddmethod()
というメソッドを定義している。main
関数の中でX1
という構造体を定義し、構造体のメンバに3
と4
を代入してから、X1.myaddmethod()
という形で実際の処理を行う。
package main import "fmt" // define function func myaddfunc(a, b int) int { return a + b } // define struct and method type mystruct struct{ a, b int } func (X mystruct) myaddmethod() int { return X.a + X.b } // main func main() { // use function fmt.Println(myaddfunc(3, 4)) // use method X1 := mystruct{3, 4} fmt.Println(X1.myaddmethod()) }
計算結果は以下。
$ go run .\func-method.go 7 7
参考にしたもの
わわわIT用語辞典 > 違いの分かるピヨピヨ > 「関数」と「メソッド」の違い
*1:もちろんvarで宣言してから、メンバを別の式で代入してもよい。