Dragon Arrow written by Tatsuya Nakaji, all rights reserved animated-dragon-image-0164

go言語 メソッド

updated on 2020-10-31

メソッド


基本構文

func (レシーバ) メソッド名(引数) {
  // 処理
}


レシーバ

  • メソッドに関連付けられた変数
    • メソッド呼び出し時には通常の引数と同じような扱いになる
      • コピーが発生する
    • ポインタを用いることでレシーバへの変更を呼び出し元に伝えることができる
      • レシーバがポインタの場合もドットでアクセスする


package main

type T int

func (t *T) f() { println("hi") }

func main() {
    var v T
    // 以下の2行は同じ意味
    (&v).f()
    v.f()
}

(コンソール出力)

hi

hi


例: ユーザー定義型のレシーバー

package main
import "fmt"
type Hex int
func (h Hex) String() string {
    // %x 基数16で表現する 10以上の数には小文字(a-f)を使用
    return fmt.Sprintf("%x", int(h)) // fmt.Sprintfはfmt.Printfと違い、標準出力ではなくフォーマットした結果を文字列で返す
}
func main() {
    // 100をHex型として代入
    var hex Hex = 100
    // Stringメソッドを呼び出す
    fmt.Println(hex.String()) // 100=>16*6+1*4なので、16進数で64

    hex = 160
    fmt.Println(hex.String()) // 160=>16*10+1*0なので、16進数でa0

    hex = 200
    fmt.Println(hex.String()) // 200=>16*13+1*8なので、16進数でc8
}

(コンソール出力)

64

a0

c8


例: ポインタ型のレシーバ

package main

import "fmt"

type User struct {
    Name string
}

// メソッド(ポインタレシーバ)
func (u *User)setName() {
    u.Name = "gopher"
}

func main() {
    u := new(User)
    u.setName()
    fmt.Println(u.Name) //=> gopherが出力される。
}

(コンソール出力)

gopher


例: 配列型のレシーバ

package main

import "fmt"

type Vector2D [2]float32


func (v Vector2D) Add(n Vector2D) Vector2D {
    return Vector2D{n[0] + v[0], n[1] + v[1]}
}


func main() {
    v1 := Vector2D{1.5, -1.0}
    v2 := Vector2D{2.2, 4.4}
    fmt.Println(v1.Add(v2))
}

(コンソール出力)

[3.7 3.4]


例: ポインタ型のレシーバ

package main
type MyInt int
func (n *MyInt) Inc() { *n++ }
func main() {
    var n MyInt
    println(n) // 0
    // ポインタを用いたメソッドの呼び出しでは、&は省略しても良い
//     (&n).Inc()
    n.Inc()
    println(n) // 1
}

(コンソール出力)

0

1


メソッド値


メソッドも値として扱える

  • レシーバは束縛された状態


メソッドを値として扱う例

package main

import "fmt"

type Hex int

func (h Hex) String() string {
    return fmt.Sprintf("%x", int(h))
}

func main() {
    // 100をHex型として代入
    var hex Hex = 100
    // メソッド値として代入
    f := hex.String
    fmt.Println(f())
}

(コンソール出力)

64


メソッド式


メソッドを表す式

レシーバを第1引数とした関数になる


package main

import "fmt"

type Hex int

func (h Hex) String() string {
    return fmt.Sprintf("%x", int(h))
}

func main() {
    // 100をHex型として代入
    var hex Hex = 100

    // メソッド値
   // f := hex.String
    // fmt.Println(f())

    // メソッド式
    f := Hex.String
    fmt.Printf("%T\n%s\n", f, f(hex))
}

(コンソール出力)

func(main.Hex) string 

64