Go 1.9 と Type Alias

遅ればせながらの記事で申し訳ないが Go 1.9 がリリースされた。

詳しい内容はリリースノートを見ていただくとして,今回の目玉は type alias 機能だろう。

まず type キーワードを使った簡単な足し算を書いてみる。

package main

import (
    "fmt"
)

type Num1 int

func (n1 Num1) Add(n2 Num1) Num1 {
    return n1 + n2
}

func main() {
    n1 := Num1(1)
    n2 := Num1(2)
    fmt.Println(n1.Add(n2))
}

実行結果は 3 と出力されるはずである。 ここで “type Num2 Num1” と記述を追加し,この型を使って足し算を行ってみる。

package main

import (
    "fmt"
)

type Num1 int

func (n1 Num1) Add(n2 Num1) Num1 {
    return n1 + n2
}

type Num2 Num1

func main() {
    n1 := Num2(1)
    n2 := Num2(2)
    fmt.Println(n1.Add(n2))
}

これを実行しようとすると

n1.Add undefined (type Num2 has no field or method Add)

とコンパイルエラーになる。 何故か。 Num1Num2 は異なる型だからだ。 型 Num1 に紐付いている関数 Add() は,型 Num2 には紐付かない。 継承されないわけだ(Num1 へキャストはできる)。

では今度は “type Num2 = Num1” と記述を変更してみる。

package main

import (
    "fmt"
)

type Num1 int

func (n1 Num1) Add(n2 Num1) Num1 {
    return n1 + n2
}

type Num2 = Num1

func main() {
    n1 := Num2(1)
    n2 := Num2(2)
    fmt.Println(n1.Add(n2))
}

今度はコンパイルエラーにならず 3 と出力される。 この “type Num2 = Num1” という構文が type alias を指し,この記述によって Num1Num2全く同じ型 として扱われる1

なんでこんな妙ちきりんな言語仕様が追加されたかというと,実はこれ,リファクタリングの為に設けられたのである。

Go now supports type aliases to support gradual code repair while moving a type between packages. The type alias design document and an article on refactoring cover the problem in detail.
via Go 1.9 Release Notes

もともと Go 言語はリファクタリングを厚遇する言語と言える。 たとえば「構造的部分型(structural subtyping)」などはその最たる例だろう。

まぁ,あまり積極的に使う機能ではないかもしれないが,こういうこともできると覚えておくといいだろう。

ブックマーク

参考図書

photo
Java言語で学ぶリファクタリング入門
結城 浩
SBクリエイティブ 2007-01-26 (Release 2014-03-12)
eBooks Kindle版
ASIN: B00I8AT1EU
評価     

結城浩さんによる「リファクタリング本」の Kindle 版。意外にも Java 以外でも応用できる優れもの。

reviewed by Spiegel on 2018-12-11 (powered by amazon-item v0.2.0)


  1. 全く同じ型なので継承関係はなく,別名定義した型に独自に関数を紐付けることはできない。ちなみに別パッケージの型に対しても別名定義が可能である: type Time = time.Time