goでMapを定義したときに
そのkeyとvalueを逆にする方法を紹介します。
例えば、以下のようにprotoで定義された型からアプリケーション上で定義したmodelに
マッピングするために、Mapを用いることがあるかと思うのですが、
proto->modelのMapからmodel->protoのMapを生成する方法を紹介します。
具体的には次のようなケースを想定しています。
// 以下のようなMapから
var protpToModelMap = map[v1.PaymentMethod]paymentmethod.PaymentMethod{
v1.Credit: paymentmethod.Credit,
v1.PayPay: paymentmethod.PayPay,
v1.AuPay: paymentmethod.AuPay,
v1.RakutenPay: paymentmethod.RakutenPay,
}
// 次のようなMapを作成したい時
var modelToProtoMap = map[paymentmethod.PaymentMethod]v1.PaymentMethod{
paymentmethod.Credit: v1.Credit,
paymentmethod.PayPay: v1.PayPay,
paymentmethod.AuPay: v1.AuPay,
paymentmethod.RakutenPay: v1.RakutenPay,
}
次のような関数でKeyとValueを逆にしたMapを作成できます。
// ReverseMap keyとValueを入れ替えたMapを作成する
func ReverseMap[T, S ~string | ~int](m map[T]S) map[S]T {
n := make(map[S]T, len(m))
for k, v := range m {
if existKey, ok := n[v]; ok {
panic(fmt.Sprintf("重複したkeyが存在します key:%v",existKey))
}
n[v] = k
}
return n
}
var modelToProtoMap = ReverseMap(protpToModelMap)
補足
引数で受け取るMapのkeyとvalueのジェネリクスの型に
~
がついているのは Underlying Type と呼ばれているもので
基礎となる型がintである型を要求していることを意味しています。
この~
がないとgoのenumを使うときに定義される独自タイプ(例:type PaymentMethod int
)を引数として渡すことができなくなってしまいます。