在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, 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{},所以做类型断言的时候可以简单粗暴一些

下面是我在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 类型断言的学习的更多相关文章

  1. golang类型断言

    一.介绍 类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型,就需要使用类型断言 例子: package main import "fmt" func main(){ ...

  2. [Go] golang类型断言

    类型断言有点像向下转型,接口类型转到具体的实现实例类型上类型断言是一个使用在接口值上的操作.语法上它看起来像x.(T)被称为断言类型,这里x表示一个接口的类型和T表示一个类型 package main ...

  3. [Golang学习笔记] 06 程序实体3 类型断言和类型转换

    类型断言: 语法:<目标类型的值>,<布尔参数> := <表达式>.( 目标类型 ) // 安全类型断言<目标类型的值> := <表达式>. ...

  4. golang学习笔记:Interface类型断言详情

    原文链接:https://www.2cto.com/kf/201712/703563.html 1. 用于判断变量类型 demo如下: switch t := var.(type){ case str ...

  5. [golang] go的typeswitch guard(类型区别)语法和type assertion(类型断言)语法

    最近在实现golang,看到个go的特性语法: typeswitch guard. typeswitch guard语法如下: package main import "fmt" ...

  6. Golang的类型断言

    类型断言即判断一个变量是不是某个类型的实例,这个经常用在判断接口的类型,基本的格式: y, ok := x.(type) 上面的语句用于判断变量x是不是type类型,有两种结果: x是type类型的变 ...

  7. Golang之interface(多态,类型断言)

    多态用法 package main //一种事物的多种形态,都可以按照统一的接口进行操作 //多态 import ( "fmt" "math/rand" &qu ...

  8. Go的类型断言解析

    经常地我们对一个接口值的动态类型是不确定的,如方法的形参为接口类型时,此时就需要检验它是否符合我们需要的类型.类型断言是一个使用在接口值上的操作.断言类型的语法:x.(T),这里x表示一个接口的类型, ...

  9. Go语言的类型转换和类型断言

    https://my.oschina.net/chai2010/blog/161418 https://studygolang.com/articles/9335  类型转换.类型断言和类型切换 ht ...

随机推荐

  1. iOS有关图片处理的总结 (四)------图片的饱和度,亮度,对照度。

    在做图片处理的时候.会遇到调节图片的饱和度的问题,这里就要用到Core Image这个框架,Core Image是一个非常强大的框架. 它能够让你简单地应用各种滤镜来处理图像,比方改动鲜艳程度, 色泽 ...

  2. 关于Oracle处理DDL和DML语句的事务管理

    SQL主要程序设计语言 数据定义语言DDL(Data Definition Language) 如 create.alter.drop, 数据操作语言DML(Data Munipulation Lan ...

  3. ASP.NET Core 使用 Redis 客户端

    Mac OS 安装 Redis(用于连 Redis 服务器,方便查看数据):https://redis.io/topics/quickstart wget http://download.redis. ...

  4. python decorator 进阶

    上一篇文章开始的时候提到 “一般来说,装饰器是一个函数,接受一个函数(或者类)作为参数,返回值也是也是一个函数(或者参数)” 有一般情况,就有特殊情况.第一种特殊情况:装饰器可能也是一个类:第二种特殊 ...

  5. javaWeb超链接(href)请求-特殊字符处理

    写在前面: 最近在项目中,遇到一个问题,在点击一个超链接时,页面报错.通过浏览器调试就可以知道发送的请求参数是不完整的,因为参数中含有特殊字符.所以就报错啦~~ 原代码,不能正确发送含有特殊字符的参数 ...

  6. 【java】HashMap、Map、Set、HashMap.put()、HashMap.keySet()、HashMap.entrySet()、Map.Entry内部类

    package com.tn.hashMap; public class Student { private String id; private String name; public Studen ...

  7. springboot 结合mybatis

    MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML ...

  8. iOS 写给iOS开发者的React Native学习路线(转)

    我是一名iOS开发者,断断续续一年前开始接触React Native,最近由于工作需要,专职学习React Native也有一个多月了.网络上知识资源非常的多,但能让人豁然开朗.迅速学习的还是少数,我 ...

  9. VS2012 未找到与约束ContractName Microsoft.VisualStudio.Text.ITextDocumentFactoryService

    最近新换了系统还真是问题多多呀!! 系统更新补丁后打开 VS2012 ,新建C#项目的时候出现这个问题 VS2012 未找到与约束ContractName Microsoft.VisualStudio ...

  10. Add to List 349. Intersection of Two Arrays

    Given two arrays, write a function to compute their intersection. Example:Given nums1 = [1, 2, 2, 1] ...