golang genericsでswitch-caseをする
はじめに
Go言語では1.18でgenericsの機能が入ってくるので勉強していたのですが引数に型パラメータがあった場合どのようにswitchするのか気になったので備忘録を残します
引数の型が interface{}
のとき
proposalに書いてるswitch文を見てみるとcase
の部分で型パラメータが使われている点以外、引数は interface{}
になっており、普段go言語を書いている通りの記述になると思います
Generic types as type switch cases - Type Parameters Proposal
type Mystruct struct { fieldA string } func Switch[T any](v interface{}) (T, bool) { switch v := v.(type) { case T: return v, true default: var zero T return zero, false } } func main() { x, ok := Switch[string]("string") if ok { fmt.Println(x) // string } y, ok := Switch[Mystruct](Mystruct{fieldA: "a"}) if ok { fmt.Println(y) // {a} } }
https://gotipplay.golang.org/p/nQJNsMiwkzh
引数の型が型パラメータの場合
では、関数の引数の型が型パラメータだった場合にどのようにswitchを使うのかをprosalから探してみます
サンプルコードがありました。(※少しだけコードを変更しています)
Identifying the matched predeclared type - Type Parameters Proposal
type Float interface { ~float32 | ~float64 } func NewtonSqrt[T Float](v T) (int, T) { var iterations int switch (interface{})(v).(type) { case float32: iterations = 4 case float64: iterations = 5 default: // panic: unexpected type main.MyFloat panic(fmt.Sprintf("unexpected type %T", v)) } return iterations, v } type MyFloat float32 func main() { iterations, x := NewtonSqrt(MyFloat(64)) fmt.Println(iterations) fmt.Println(x) }
https://gotipplay.golang.org/p/te5gOiFyx2I
proposalを読んでみると以下のように書いてありました
The design doesn't provide any way to test the underlying type matched by a
~T
constraint element.
つまり、現時点 (2022/1/29)ではunderlying typeのswitch文は書けそうにありません。
しかし、あくまでunderlying typeのときの話なので、今度はMyFloat
ではなくfloat型を関数に渡してみた結果無事に結果が表示されました。
最後に
type switchに関するproposalが出ているので、将来的にやりたいことはできるのではと思っています
これからもproposalやリリース情報は追った方がよさそうです