golang 类型断言的学习
来源:互联网 发布:mysql恢复数据库 编辑:程序博客网 时间:2024/05/21 11:44
在php中有一个 serialize() 函数 可以把数组序列化成字符串进行存储和传输
如果想反序列化这种字符串,在php中只需要一个简单的unserialize() 函数就可以完成了.但是在golang中可就没有这么容易了,非得费个九牛二虎之力,写上不少代码才行。
这时候只想感叹一下,php真的是世界上最好的语言啊!
我就在今天的开发中遇到了这么个问题,需要使用golang去解析php序列化的字符串,在github上找了个解析的包,但是发现解析之后的结果是个interface{}类型。
顿时我就无从下手了,总在想数据实际上是一个map,但是解析后得到一个interface{} , 这让我怎么用啊
感觉需要用类型断言,但又不太会用,遂去社区问一下吧,期望大佬们能给个答案。
实际上确实很管用。
下面贴一下代码:
package mainimport ("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 mainimport ("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 mainimport ("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 assertdecodedData, 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 assertfriendsRes, 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{},所以做类型断言的时候可以简单粗暴一些
下面是我在segmentfault和stackoverflow上面的提问,我上面的示例demo也是来源于问题中大佬们的回答,有兴趣可以看下:
segmentfault:https://segmentfault.com/q/1010000010690732
stackoverflow:https://stackoverflow.com/questions/45705930/how-to-get-values-from-a-interface-in-golang/
- golang 类型断言的学习
- golang学习之Interface类型断言
- golang,使用类型断言的一个例子
- golang类型断言
- golang 断言 + 类型转换
- golang类型断言使用方法
- golang: 类型转换和类型断言
- golang: 类型转换和类型断言
- golang: 类型转换和类型断言
- GoLang 类型转换和类型断言
- java断言的学习
- java断言的学习
- Junit断言的学习
- 断言的学习
- golang学习之--struct类型
- Golang--interface断言
- golang显示数据的类型
- golang基础-接口、接口嵌套、类型断言、接口与结构体_接口等转换
- kettle7.0 Error connecting to database: (using class org.gjt.mm.mysql.Driver)
- 查找
- 学习文档接触到的知识VER
- Oracle 如何在线添加ASM磁盘
- python 的 scapy库,实现网卡收发包
- golang 类型断言的学习
- mysql数据库引擎切换(InnoDB,MyISAM)
- 创建线程的两种传统方式
- 那些硬着头皮去做的事,终将让你长进
- Red Linux 系统TeamViewer安装
- android开发——分秒计时器(可 开始/暂停/继续/停止)
- (CRC)算法入门引导
- I Hate It (线段树)
- ElasticSearch的Scroll与Scan有何作用?区别?