在php中有一个 serialize() 函数 可以把数组序列化成字符串进行存储和传输
如果想反序列化这种字符串,在php中只需要一个简单的unserialize() 函数就可以完成了.但是在golang中可就没有这么容易了,非得费个九牛二虎之力,写上不少代码才行。
这时候只想感叹一下,php真的是世界上最好的语言啊!
我就在今天的开发中遇到了这么个问题,需要使用golang去解析php序列化的字符串,在github上找了个解析的包,但是发现解析之后的结果是个interface{}类型。
顿时我就无从下手了,总在想数据实际上是一个map,但是解析后得到一个interface{} , 这让我怎么用啊
感觉需要用类型断言,但又不太会用,遂去社区问一下吧,期望大佬们能给个答案。
实际上确实很管用。
下面贴一下代码:
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])
}
}
}
上面两个demo都可以达到效果,只是写法不同。
后面我又经人介绍,得到了另外一个包,也能达到效果:
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