LoginSignup
8
6

More than 5 years have passed since last update.

Go言語:「インタフェースへのポインタ」ではまった

Posted at

前書き

Go とデザインパターンの並行勉強がてら、Builder パターンを書いてみたらちょっと詰まったので覚書き。
外部パッケージに定義したインタフェースを実装してみたらうまく動かなかったので、インタフェースとポインタについて調べてみた。

Builder パターン

足したり引いたりするだけの、GoF Builder の最低限の実装(だと思う)。
NewDirector でインスタンスを生成し、Construct で実行。

builder.go
package builder

type builder interface {
  Add(num float64)
  Sub(num float64)
  GetResult() string
}

type Director struct {
  builder builder
}

func NewDirector(b builder) Director {
  d := Director{b}
  return d
}

func (d *Director) Construct() {
  b := d.builder
  b.Add(100)
  b.Sub(50)
  b.Add(100)
}

builder パッケージを main.go で実装し、Director で実行結果を得る。
SumBuilder は Builder インタフェースを実装した実体。

main.go
package main

import (
  "fmt"
  "strconv"
  "./builder"
)

type Director builder.Director

type SumBuilder struct {
  sum float64
}

func NewSumBuilder() *SumBuilder {
  s := &SumBuilder{0}
  return s
}

func (s *SumBuilder) Add(num float64) {
  s.sum += num
}

func (s *SumBuilder) Sub(num float64) {
  s.sum -= num
}

func (s *SumBuilder) GetResult() string {
  sumStr := strconv.FormatFloat(s.sum, 'g', 8, 64)
  return "Sum: " + sumStr + "."
}


func main() {
  sumbuilder := NewSumBuilder()
  director := builder.NewDirector(sumbuilder)
  director.Construct()

  str := sumbuilder.GetResult()
  fmt.Printf("%v\n", str)
}

実行するとちゃんと Sum: 150 が出力される。

躓きポイント

前述の builder.go は修正後のコード。修正前はこんな感じ。

builder.go(修正前)

/* 省略 */

type Director struct {
  builder *builder
}

func NewDirector(b *builder) *Director {
  d := &Director{b}
  return d
}

func (d *Director) Construct() {
  b := *d.builder
  b.Add(100)
  b.Sub(50)
  b.Add(100)
}

ポイントは Director がメンバで持っている builder インタフェースをポインタで持っていたこと。
どうやらインタフェースのポインタはインタフェースとしての機能を持てないということらしい。
つまりインタフェースの機能を実装した実体のポインタを渡してもインタフェースとしては振る舞えないので意味がない、ということだ。

結論

結局のところは、ポインタについてもっとちゃんと考えましょうね、というお話でした。

参考

Go言語のインターフェイスとポインタについての小実験
http://d.hatena.ne.jp/eel3/20140915/1410788174

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6