Goの関数とメソッドの違いを解説する

thumnail
2020-03-04

何となく「関数」「メソッド」という単語をごっちゃに使っており、いい加減このように適当に用語を使うのを辞めたいと思った。その違いをまとめこの記事で言語化してみる。

構文の違い

関数の場合

関数は引数の型をあらかじめ宣言する。次のコードを見て欲しい。

type Person struct {
    Name string
    Age  int
}

func makeNewPerson(name string, age int) \*Person {
    return &Person{
        Name: name,
        Age:  age,
    }
}

name, ageのstring型の引数を取ると指定して関数を宣言しなければいけない。

メソッドの場合

メソッドの場合はレシーバと呼ばれるClassのようなデータを引数に取る。メソッド名の前にレシーバを記述する。次のコードを見て欲しい。

func (p *Person) isOlder() bool {
    return p.Age > 65
}

ポインタのPerson型をレシーバとして指定し、isOloderという名前のメソッドを定義した。このように関数名の前にレシーバが指定されていればそれメソッドだ。

呼び出し方の違い

関数の場合

関数を呼び出す場合は関数名に()をつけて、中に引数を与えるだけだ。

p := makeNewPerson("katuo", 50)

メソッドの場合

メソッドの場合はメソッド名の前にレシーバーを付与する必要がある。

p := makeNewPerson("katuo", 50)
fmt.Println(p.isOlder()) // false

isOlderメソッドのレシーバはポインタのPerson型だったので、一度、Person型の変数を定義した上でその変数をレシーバとして指定し、isOlderメソッドを呼び出している。

メソッドチェーン

メソッドに用意されている構文

メソッドにはメソッドチェーンと呼ばれる、連続してメソッドを呼び出せる仕組みがある。次のコードを見て欲しい。

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func (p *Person) addName(name string) *Person {
    p.Name = name
    return p
}

func (p *Person) addAge(age int) *Person {
    p.Age = age
    return p
}

func main() {
    p := &Person{}

    p = p.addName("katuo").addAge(50) // メソッドチェーン

    fmt.Println(\*p) // {katuo 50}
}

addName, addAgeというメソッドを定義した後、23行目でメソッドチェーンを使って1行で2つのメソッドを呼び出すことができる。メソッドチェーンを使うことでコードを可読性向上に繋がる。

今回の記事では次のサイトを参考にした。 https://medium.com/golangspec/interfaces-in-go-part-i-4ae53a97479c

KATUBLO

Copyright since 2018 KATUO All Rights Reserved.