ルール
  1. AIの書いた文章ではなく自分で書くこと
  2. AIから教えてもらったことをそのまま鵜呑みにしないで、必ず他の情報(一次情報かどうかは問わない)も調べた上で記述すること
  3. 可能な限り、経験として得た知識について記載すること。事後的に経験として得たものでも可とする

Goの型について

最近Goを本格的に勉強し始めた。これまでGoで何かアプリケーションを開発した経験はあるが、基礎から勉強をし直すということでA Tour of Goを取り組んだ。その中で、Goのinterfaceについて面白かったのでまとめることにした。

interface

Goではinterfaceは公称型ではなく構造的部分型として扱われる。一方、structは公称型として扱われる。 また、interfaceは明示的に準拠せずとも、型のシグネチャが一致していれば自動的に準拠される。 動的型付け言語におけるダックタイピングのようなことがGoのInterfaceではコンパイル時に保証することができる。

package main

import "fmt"

type Movable interface {
	move(spped int)
}

type Vehicle struct {
}

func (*Vehicle) move(speed int) {
	fmt.Println("Vehicle moves at", speed, "km.")
}

type Trolley struct{}

func (*Trolley) move(speed int) {
	fmt.Println("Trolley moves at", speed, "km.")
}

func main() {
	var movable Movable = &Vehicle{} // *Vehicleはmove(speed:)を実装しているので自動的にMovableに準拠する
	movable.move(30)
	movable = &Trolley{} // *TrolleyもVehicleと同様に自動的にMovableに準拠する
	movable.move(10)
}

一方、interface{}型という型もGo言語では定義されていて、これはメソッドを一つも持たないinterfaceである。つまり、全ての型はinterface{}に準拠されるので、他の言語でいうany型と同様な扱いになる。 また、Go 1.18からany型がinterface{}のエイリアスとして事前定義された(参考)ので、直感的にany型を利用できるようになった。

嬉しいこと

個人的には、interfaceも定義上は名前があるので公称型(Nominal Type)である方が嬉しいと思う。型がNominalでないと例えば値オブジェクトを実装する際にTypeScriptのようにBranded Typesを実装するように複雑になる懸念があるからだ。 しかし、Goではinterfaceは構造的部分型であるものの、structについては公称型である。 なので、値オブジェクトについてはstructで実装すればシンプルに実装できる。一方、型は暗黙的にinterfaceに準拠するという仕様はメソッドのinterfaceの影響範囲が大きいことを示していると感じるので、今後理解を深めていく中で感覚を掴んでいきたい。