了解学习golang类型断言


本文摘自php中文网,作者藏色散人,侵删。

下面由golang教程栏目给大家介绍golang类型断言,希望对需要的朋友有所帮助!

在php中有一个 serialize() 函数 可以把数组序列化成字符串进行存储和传输

如果想反序列化这种字符串,在php中只需要一个简单的unserialize() 函数就可以完成了.但是在golang中可就没有这么容易了,非得费个九牛二虎之力,写上不少代码才行。

这时候只想感叹一下,php真的是世界上最好的语言啊!

我就在今天的开发中遇到了这么个问题,需要使用golang去解析php序列化的字符串,在github上找了个解析的包,但是发现解析之后的结果是个interface{}类型。

顿时我就无从下手了,总在想数据实际上是一个map,但是解析后得到一个interface{} , 这让我怎么用啊

感觉需要用类型断言,但又不太会用,遂去社区问一下吧,期望大佬们能给个答案。

实际上确实很管用。

下面贴一下代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

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这个占位符可以显示变量的类型

下面还有个示例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

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都可以达到效果,只是写法不同。

后面我又经人介绍,得到了另外一个包,也能达到效果:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

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类型断言的详细内容,更多文章请关注木庄网络博客!!

相关阅读 >>

docker 概述

手撸golang go与微服务 saga模式之9 小结/gitee源码

golang map有什么用

golang 创建型设计模式 抽象工厂

golang ide有哪些

ubuntu下安装golang

聊聊dapr的consistent hash

手撸golang 行为型设计模式 迭代器模式

手撸golang spring ioc/aop 之2

golang程序设计——数据容器

更多相关阅读请进入《golang》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...