質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

Q&A

解決済

1回答

998閲覧

【Go】インターフェース 型アサーションに関して 実際に使用する機会に生まれた疑問 `claims := token.Claims.(jwt.MapClaims)`

nyako

総合スコア45

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

0グッド

0クリップ

投稿2022/09/02 15:00

前提と理解していること

タイプアサーション -> 元の型情報を復活させると認識しております。

下記のコードであれば、do()を呼び出した際に引数がinterface{}で、元々の呼び出しが
do(10)であるとint型がくると分かっているので
処理内で「あ、じゃあiをタイプアサーションしよう」となることは理解出来ます。

Go

1 2func do(i interface{}) { 3 // ii := i * 2 // iはinterface{}型なのでこれが出来ない。 4 ii := i.(int) 5 fmt.Println(ii) // 10 6} 7 8func TypeAssertion() { 9 do(10) 10 do("Hello") // これも対応させるにはswitch typeを使う。 11}

疑問に思ったコード

token.Claims.(jwt.MapClaims)の部分で型アサーションをしています。
なぜjwt.MapClaimsにアサーションできると実装者側は分かるのでしょうか?
上記の例で書いたコードのように呼び出しもとの引数の型などが分かれば対処できそうな気がするのですが、要するに「Claimsだ、じゃあjwt.MapClaimsに型アサーションしよう」となる理由が分かりません。

Go

1 token := jwt.New(jwt.SigningMethodHS256) // *Tokenを返す 2 claims := token.Claims.(jwt.MapClaims) 3 claims["user_id"] = u.ID 4 claims["exp"] = time.Now().Add(time.Hour * 24).Unix()

上記コードで必要な情報

Go

1 2 // Token構造体 ※一部省略しています。 3 type Token struct { 4 Claims Claims 5 } 6 7 type Claims interface { 8 Valid() error 9 } 10 11 type MapClaims map[string]interface{} 12

宜しくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nobonobo

2022/09/02 15:32

どのjwtライブラリの話でしょうか?
guest

回答1

0

ベストアンサー

"github.com/dgrijalva/jwt-go"と仮定して解答します。

以下のようにNewした時のデフォルトClaimsはMapClaimsだからです。

https://github.com/dgrijalva/jwt-go/blob/dc14462fd58732591c7fa58cc8496d6824316a82/token.go#L33-L35

func New(method SigningMethod) *Token { return NewWithClaims(method, MapClaims{}) }

投稿2022/09/02 15:38

nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nyako

2022/09/02 16:01

ありがとうございます!なんのパッケージか載せるの忘れていました。 以下流れとお聞きしたい追加点があります。 1, `MapClaims{}`を空のインターフェースを引数で渡す その実際の型は`map[string]interface{}` 2, 受け取る側の関数`NewWithClaims(method SigningMethod, claims Claims)`の第二引数はclaims型 == interface{}型なのでなんでも受け取ることが出来る ※ ここでは構造体にメソッドがあることを保証する型とは関係なしの別のことという理解であっていますでしょうか? 3, 型アサーションをする interface型 から 元の型にしてあげる `claims := token.Claims.(jwt.MapClaims) claims["user_id"] = u.ID ` ということでしょうか。 ただそもそもこのような`NewWithClaimsがインターフェース型を引数にとってまた戻すという実装があるのはなぜでしょうか? この場面であればキーバリューでmapが来ることがわかっているのにわざわざインターフェース型にして再度元に戻すという意味があまり理解出来ません...。 よろしくお願い致します。
nobonobo

2022/09/02 22:49

インターフェースでは元の型がなんであるかはあまり関係ありません。 どんなメソッドを持っているかです。元の型がmap[string]interface{}であることは一旦忘れましょう。 Claimsインターフェースは「Valid() error」というメソッドを持っていることを要求するインターフェースです。MapClaims型も「Valid() error」メソッドが生えていると思います。 claimsに渡される引数は「Valid() error」メソッドを持っていさえすれば基本的に処理可能です。 MapClaims型に戻している場面はちょっと例外的な使われ方なのかなと思います。 Goの複数の型が同じように使えるという部分にはこういうインターフェースを経由する使い方が一般的です。 そうすることで多様な内部構成をもつコンテナを一様に扱う処理に投げ込めるのです。
nyako

2022/09/03 12:05

ありがとうございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問