There is a serialize() function in php that serializes arrays into strings for storage and transmission.
If you want to deserialize this string, you only need a simple unserialize() function in php. But it's not so easy in golang. It takes a lot of effort to write a lot of code.
At this time, I just want to sigh that php is really the best language in the world.
I have encountered such a problem in today's development that I need to use golang to parse php serialized strings, find a parsing package on github, but find that the result of parsing is an interface {} type.
Suddenly, I couldn't get started. I always thought that the data was actually a map, but after parsing, I got an interface {}, which let me use it.
Feeling that you need to use type assertion, but not very good, so go to the community to ask, hoping that the big guys can give an answer.
It really works.
Next, paste the code:
package main import ( "github.com/yvasiyarov/php_session_decoder/php_serialize" "fmt" "log" ) func main() { // Serialized strings 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";}}}` // Deserialize decoder := php_serialize.NewUnSerializer(str) if result, err := decoder.Decode(); err != nil { panic(err) } else { // Type assertions are made here decodeData, ok := result.(php_serialize.PhpArray) if !ok { log.Println(err) } // After assertion, you can get the content name := decodeData["name"] age := decodeData["age"] fmt.Println(name, age) // The underlying data still needs to be asserted again friends, ok := decodeData["friends"].(php_serialize.PhpArray) if !ok { log.Println(err) } // Once the assertion is successful, internal data can be obtained 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) } } }
It can be roughly understood that the type of a variable is what it is, the type of assertion is made, and the result is obtained after the assertion.
How to determine the type of a variable?
Print it out: fmt.Printf("%T", verb)
% T This placeholder shows the type of variable
Here is another example:
package main import ( "github.com/yvasiyarov/php_session_decoder/php_serialize" "fmt" "log" ) func main() { // Serialized strings 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";}}}` // Deserialize decoder := php_serialize.NewUnSerializer(str) result, err := decoder.Decode() if err != nil { panic(err) } // Type Asserts 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]) } } }
The above two demo s can achieve results, but they are written differently.
Later, I was introduced and got another bag, which can also achieve the effect:
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"]) } }
The type of all the results parsed by this package is map[interface{}]interface {}, so it's easier to be rude when making type assertions.
Below are my questions on segmentfault and stack overflow. The demo example above is also from the answers of the big guys in the questions. Interested to see:
segmentfault:https://segmentfault.com/q/1010000010690732
stackoverflow:https://stackoverflow.com/questions/45705930/how-to-get-values-from-a-interface-in-golang/