📝

[Go] Defined typeとType alias

2024/02/04に公開

Go には、独自の型を定義するのに Defined type (Named type) と 型エイリアス (Type alias) の 2 つの定義方法があります。
かく言う僕は、普段 Defined type しか使わないのもあり、この 2 つの型定義方法の違いを知りませんでした。
今回は、自分用のメモも兼ねて、この 2 つの定義法の違いを記していこうと思います。

Defined type (Named type とも言うらしい)

僕は基本的には普段この Defined type しか使っていません。

// こんな書き方
type DefinedType int

特徴としては下記の認識です。

  • プリミティブな型 (上記ではint) とは全く別の型になる。
  • 上記故に型チェックに向いている (DefinedType型の変数にint型の値を代入しようとするとコンパイルエラーが起きる)。
  • レシーバの型として定義可能 (メソッドを生やせる)。
    • バリデーション用メソッドなどを定義して、ValueObject のように扱える。

型エイリアス (Type alias)

// こんな書き方
type AliasType = int

特徴としては下記の認識です。

  • プリミティブ型 (上記ではint) と同じ型として使用できる。
  • 上記故に型チェックに向いていない (AliasType型の変数にint型の値を代入可能)。
  • レシーバの型として定義不可能 (メソッドを生やせない)。

違い (コードで)

こでまで述べた Defined type と Alias type の特徴をもとに 2 つの違いをコードでまとめると、下記の感じです。

package main

import "fmt"

type DefinedType int
type AliasType = int

func inclement(a, b int) int {
	return a + b
}

func main() {
	var d DefinedType = 1
	var a AliasType = 1
	fmt.Printf("increment result: %d", inclement(d, 2)) // コンパイルエラー
	fmt.Printf("increment result: %d", inclement(a, 2)) // 可

	n := 1
	n = DefinedType(n) // コンパイルエラー
	n = AliasType(n)   // 可
}

// 可
func (d DefinedType) Validate() {
	fmt.Println("some validation done")
}

// レシーバの箇所でコンパイルエラー
func (a AliasType) Validate() {
	fmt.Println("some validation done")
}


一応 PlayGround のリンクも貼っておきます。

最後に

これを教えてくださった先輩エンジニアに感謝です。
Type alias の使い所が個人的にあまり掴めていないです。

参考

非常に参考になりました。

GitHubで編集を提案

Discussion