[Go言語]structにinterfaceを埋め込んで,動的に入れ替えるパターン

August 3, 2014

この記事はQiitaの記事をエクスポートしたものです。内容が古くなっている可能性があります。

正直,何に使えるのよくわかりませんが,以下のようにすると動的にinterfaceの実装方法を変更できることに気づきました.

structの匿名フィールド(埋め込み)として,interfaceを設定すると,そのstructも埋め込んだinterfaceを実装していることになります.埋め込んだinterfaceは匿名フィールドなので,型名でアクセスして入れ替えることができます.

以下の例では,fmt.Stringerインタフェースの実装を動的に変更しています.

  • Go Playgroundで実行する

    package main
    
    import (
    	"fmt"
    	"strings"
    )
    
    type StringerFunc func() string
    
    func (sf StringerFunc) String() string {
    	return sf()
    }
    
    type Person struct {
    	fmt.Stringer
    	FirstName string
    	LastName  string
    	Age       int
    }
    
    func NewPerson(firstName, lastName string, age int) (p *Person) {
    	p = &Person{
    		nil,
    		firstName,
    		lastName,
    		age,
    	}
    
    	p.Stringer = StringerFunc(func() string {
    		return fmt.Sprintf("%s %s (%d)", p.FirstName, p.LastName, p.Age)
    	})
    
    	return
    }
    
    func (p *Person) SetStringer(sf func(p *Person) string) {
    	p.Stringer = StringerFunc(func() string {
    		return sf(p)
    	})
    }
    
    func main() {
    	p := NewPerson("Taro", "Yamada", 20)
    	fmt.Println(p)
    	p.SetStringer(func(p *Person) string {
    		return fmt.Sprintf("%s, %s (%d)", strings.ToUpper(p.LastName), p.FirstName, p.Age)
    	})
    	fmt.Println(p)
    }

上記のプログラムを実行すると,以下のような結果になります.

Taro Yamada (20)
YAMADA, Taro (20)

なんか面白いことに使えそうですが,今のところ思いつきませんでした. なにか思いついた方はぜひ教えて下さい.