Goの型エイリアスと型定義の違い
はじめに
皆さんどうも! しろね ✨️ です!
Go では、型を宣言するときにAlias declarationsとType definitionsの 2 つの宣言方法があります。この 2 つは同じ『型』を定義するという動作に見えますが、掘り下げると全く違う挙動をしています。今回は改めてこれについてまとめてみたいと思います。
Alias declarations (型エイリアス)
Alias declarations は日本語に訳すと別名宣言となり、以下のようにして宣言します。
type Number = int
Type definitions (型定義)
Type definitions は日本語に訳すと型定義となり、以下のようにして宣言します。
type Number int
型エイリアスと型定義の違い
型エイリアスと定義型ではできることが大きく変わってきます。以下で詳しく掘り下げていこうと思います。
代入時の挙動
定義型では、たとえ同じ型から派生した型だとしてもそのまま代入することはできません。
type Number int
var num1 int
var num2 Number
// Error!
num2 = num1
型エイリアスの場合は、同じ型から派生している場合代入することができます。
type Number = int
var num1 int
var num2 Number
// OK!
num2 = num1
メソッドの定義
定義型では、メソッドを宣言できますが、型エイリアスではできません。
type Number = int
// Error!
func (n Number) Something() { /* do something */ }
type Number int
// OK!
func (n Number) Something() { /* do something */ }
どのように使い分けるべき?
定義型が適している場合
ほとんどの場合、定義型で十分です。特に、メソッドの宣言は定義型でしかできないため、そういった場合には定義型を用いるべきです。
型エイリアスが適している場合
リファクタリング時などに型名を変更したい場合などに、型エイリアスを用いると良いです。他にも、サードパーティーのライブラリが型を定義していない場合などに、自分のプロジェクト内で有効な型を追加する場合などにも使うことができます。(クロージャを引数に受け取るような関数は、引数の型が定義されていない場合がある。)
func Something(fn func()) { /* do something */ }
type SomethingFn = func()
var fn SomethingFn
Something(fn)
上記のSomething
関数はfunc()
の関数を引数に取ります。こういった型に名前をつけたくなることは往々にして存在しますが、このときに定義型で行おうとすると、引数の型が合っていないと怒られてしまいます。こういった場合に、型エイリアスを使うと良いです。
まとめ
Go の型定義の方法について 2 種類まとめてみました。誰かの参考になったのならとても嬉しいです!特に、Go1.24.0 からは型エイリアスにもジェネリクスが使えるようになるなどより便利になりました。これからはリファクタリング時などにももう少し積極的に型エイリアスを使いたいなと思います。
ではまた次回!
Discussion