fkm blog

software開発に関することを書いていきます

Goのtypeで遊ぶ

こんな関数があったとする.

func GetById(userId string) User {
}

引数が文字列なので, 間違ってオブジェクトIDを入れてしまうかもしれない. そしてそれはコンパイル時にはわからない.

なので, UserIDという型を用意して, 間違いを防ごうと考えた.

package user
type UserID interface {
    // stringとして取り出せるようにする
    String() string
}

package impl
func GetById(userId user.UserID) User {
}

interfaceだと実際に使う時は実装が必要なので, Javaとかだったらこんな風にImplクラスを作るのかな?

package impl
type UserIDImpl struct {
    value string
}
func (u *UserIDImpl) String() string {
    return u.value
}

func GetById(userId user.UserID) User {
}

// 呼び出し側. idはstring型
user := GetById(&impl.UserIDImpl{ value: id})

Goだとstringに別名を付けれるので, こう書ける.

package impl

type UserID string
func (u *UserID) String() string {
    // キャスト
    return string(u)
}

func GetById(userId user.UserID) User {
}

// 呼び出し側. idはstring型
user := GetById(impl.UserID(id))

呼び出し元でUserID(id)のようにキャストが必要なのが面倒か?