以下は、golang チュートリアル コラムからの golang 型アサーションの紹介です。困っている友人に役立つことを願っています。
PHP には、配列を文字列にシリアル化して保存および送信できる Serialize() 関数があります。
この種類の文字列を逆シリアル化したい場合、必要なのは単純な関数だけですphp では unserialize() 関数を完了できますが、golang ではそう簡単ではなく、多大な労力と大量のコードを記述する必要があります。
このときはため息をつきたくなるのですが、php は本当に世界で最高の言語です。
今日の開発中にこのような問題が発生しました。PHP でシリアル化された文字列を解析するには golang を使用する必要がありました。github で解析パッケージを見つけましたが、解析後の結果がインターフェイス型であることがわかりました。{ }
どこから始めればよいのか、突然わかりませんでした。データは実際にはマップだといつも思っていましたが、解析するとインターフェースが得られました。{}。どうやって使用すればよいですか?
型アサーションを使用する必要があるのですが、その使用方法がわからないので、コミュニティに行って質問し、偉い人が答えてくれることを期待しました。
実際には非常にうまく機能します。
以下のコードを貼り付けます:
package main import ( "github.com/yvasiyarov/php_session_decoder/php_serialize" "fmt" "log" ) func main() { // 序列化后的字符串 str := `a:3:{s:4:"name";s:3:"tom";s:3:"age";s:2:"23";s:7:"friends";a:2:{i:0;a:1:{s:4:"name";s:5:"jerry";}i:1;a:1:{s:4:"name";s:4:"jack";}}}` // 反序列化 decoder := php_serialize.NewUnSerializer(str) if result, err := decoder.Decode(); err != nil { panic(err) } else { // 此处进行类型断言 decodeData, ok := result.(php_serialize.PhpArray) if !ok { log.Println(err) } // 断言后,即可获取内容 name := decodeData["name"] age := decodeData["age"] fmt.Println(name, age) // 内层数据仍需再次断言 friends, ok := decodeData["friends"].(php_serialize.PhpArray) if !ok { log.Println(err) } // 断言成功后即可获取内部数据 for _,v := range friends { fmt.Printf("type:%T, value:%+v\n", v,v ) friend, ok := v.(php_serialize.PhpArray) if !ok { log.Println(err) } friendName := friend["name"] fmt.Println(friendName) } } }
大まかに理解すると、変数の型が何であれ、どのような種類のアサーションが行われ、アサーションの後に結果が得られるかがわかります
変数の型を判断するにはどうすればよいですか?
出力します: fmt.Printf("%T",verb)
%T プレースホルダーは変数の型を表示できます
以下に別の例があります:
package main import ( "github.com/yvasiyarov/php_session_decoder/php_serialize" "fmt" "log" ) func main() { // 序列化后的字符串 str := `a:3:{s:4:"name";s:3:"tom";s:3:"age";s:2:"23";s:7:"friends";a:2:{i:0;a:1:{s:4:"name";s:5:"jerry";}i:1;a:1:{s:4:"name";s:4:"jack";}}}` // 反序列化 decoder := php_serialize.NewUnSerializer(str) result, err := decoder.Decode() if err != nil { panic(err) } // 类型断言 t := result.(php_serialize.PhpArray) strVal := php_serialize.PhpValueString(t["name"]) fmt.Println(strVal) switch t := result.(type) { default: fmt.Printf("unexpected type %T\n", t) case php_serialize.PhpArray: fmt.Println(t) fmt.Println(t["name"]) fmt.Println(t["age"]) switch f := t["friends"].(type) { default: fmt.Printf("unexpected type %T\n", t) case php_serialize.PhpArray: fmt.Println(f) fmt.Println(f[0]) fmt.Println(f[1]) } } }
上記の 2 つのデモはどちらも効果を実現できますが、作成方法が異なります。
その後、別のパッケージを紹介されましたが、これも次のような効果をもたらしました。
package main import ( "fmt" "log" "github.com/wulijun/go-php-serialize/phpserialize" ) func main() { str := `a:3:{s:4:"name";s:3:"tom";s:3:"age";s:2:"23";s:7:"friends";a:2:{i:0;a:1:{s:4:"name";s:5:"jerry";}i:1;a:1:{s:4:"name";s:4:"jack";}}}` decodedRes, err := phpserialize.Decode(str) if err != nil { panic(err) } //fmt.Printf("%T\n", decodedRes) //type is map[interface{}]interface{} //type assert decodedData, ok := decodedRes.(map[interface{}]interface{}) if !ok { fmt.Printf("unexpected type %T\n", decodedRes) } fmt.Println(decodedData["name"]) fmt.Println(decodedData["age"]) //fmt.Printf("%T\n", decodedData["friends"]) // type is map[interface{}]interface{} // type assert friendsRes, ok := decodedData["friends"].(map[interface{}]interface{}) if !ok { fmt.Printf("unexpected type %T\n", decodedData["friends"]) } for _,v := range friendsRes { //fmt.Printf("type: %T, val: %#v\n", v,v) // type is map[interface{}]interface{} friend, ok := v.(map[interface{}]interface{}) if !ok { fmt.Printf("unexpected type %T\n", decodedData["friends"]) } //fmt.Printf("type: %T, val: %#v\n", friend,friend) // type is map[interface{}]interface{} fmt.Println(friend["name"]) } }
このパッケージによって解析されたすべての結果の型は、map[interface{}]interface{ } です。型アサーションを行うときは、より単純かつ大まかに行うことができます。
以上がgolang の型アサーションについて学ぶの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。