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.

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

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

ブックマーク

参考図書

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

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

reviewed by Spiegel on 2018-12-11 (powered by PA-APIv5)


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