たなしょのメモ

日々勉強していることをつらつらと

Goの学習メモ6

本日のGo

連続更新は難しい。

 ポインタレシーバ

ある宣言した型のメモリにアクセスして値を変更する処理。

package main

import (
    "fmt"
    "math"
)

type Vertex struct {
    X, Y float64
}

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v *Vertex) Scale(f float64) {
    v.X = v.X * f
    v.Y = v.Y * f
}

func main() {
    v := Vertex{3, 4}
    v.Scale(10)
    fmt.Println(v.Abs())
}

Vertex宣言した2つの値に10をかけているのだろう。
最終的に30と40になってAbs関数を実行している。

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v *Vertex) Scale(f float64) {
    v.X = v.X * f
    v.Y = v.Y * f
}

func main() {
    v := Vertex{3, 4}
    v.Scale(10)
    fmt.Println(v.Abs())
}

Vertex型に値を代入してるか、Vertexのポインタ型に値を代入しているかがわかる。

package main

import "fmt"

type Vertex struct {
    X, Y float64
}

func (v *Vertex) Scale(f float64) {
    v.X = v.X * f
    v.Y = v.Y * f
}

func ScaleFunc(v *Vertex, f float64) {
    v.X = v.X * f
    v.Y = v.Y * f
}

func main() {
    v := Vertex{3, 4}
    v.Scale(2)
    ScaleFunc(&v, 10)

    p := &Vertex{4, 3}
    p.Scale(3)
    ScaleFunc(p, 8)

    fmt.Println(v, p)
}

&VertexでVertexのポインタ型を宣言して初期化している。

p := &Vertex{4, 3}

ScaleFuncの引数は ScaleFunc(v *Vertex, f float64) なのでpを引数に設定する場合はScaleFunc(p, 8)のようにvと違って&をつけない。

ファンクションの宣言のさせ方次第でポインタで与えなくては値を与えるのかそうでないのかが変わるのね。

package main

import (
    "fmt"
    "math"
)

type Vertex struct {
    X, Y float64
}

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func AbsFunc(v Vertex) float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func main() {
    v := Vertex{3, 4}
    fmt.Println(v.Abs())
    fmt.Println(AbsFunc(v))

    p := &Vertex{4, 3}
    fmt.Println(p.Abs())
    fmt.Println(AbsFunc(*p))
}

この状態だとポインタのことを意識しないで値を出力できる。

func (v Vertex) Abs() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
fmt.Println(v.Abs())
fmt.Println(p.Abs())

この状態だとポインタの中身を意識して出力させてないといけない。
変数vのVertex型のときはvで変数の中身が取り出せるが、変数pのVertexポインタ型のときは*pで変数の中身を取り出す。

func AbsFunc(v Vertex) float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
fmt.Println(AbsFunc(v))
fmt.Println(AbsFunc(*p))