前面的文章提到过,golang是一门强类型的语言。即数据在使用前必须明确标识所属的数据类型。为了让golang中的slice和map 可以像Python中的list和dict一样可以存储任意数据。我们用空接口interface{}来代表任意类型的数据。

  • MySlice := make([]interface{},0)
  • MyMap := make(map[string]interface{})

写入是存储是没问题,查看一下存储的数据类型

package main

import (
"fmt"
"reflect"
)

func main() {
// 定义一个空接口为值的map
MyMap := make(map[string]interface{})

// 写入嵌套map类型的数据
MyMap["Name"] = "wgw"
MyMap["age"] = 18
MyMap["Info"] = map[string]interface{}{
"addr": "china",
"Id": 1234,
}

fmt.Println("MyMap的类型", reflect.TypeOf(MyMap))
fmt.Println("通过反射获知的age的值类型", reflect.TypeOf(MyMap["age"]))
}

运行结果

% go run main.go
MyMap的类型 map[string]interface {}
通过反射获知的age的值类型 int // 从这里得知,存入的时候,age是当int类型放进去的

取出的时候能否像Python一样方便呢 ?进一步验证一下

package main

import (
"fmt"
)

func main() {
// 定义一个空接口为值的map
MyMap := make(map[string]interface{})

// 写入嵌套map类型的数据
MyMap["Name"] = "wgw"
MyMap["age"] = 18
MyMap["Info"] = map[string]interface{}{
"addr": "china",
"Id": 1234,
}

// 既然MyMap["age"]的值是int类型,尝试把两个数字相加
x := 1
x = x + MyMap["age"]
fmt.Println(x)
}

运行结果,直接报错。错误提示是 int类型的数据 与 interface{}类型的MyMap["age"] 两个类型不一致,所以不能相加。

% go run main.go
# command-line-arguments
./main.go:25:6: invalid operation: x + MyMap["age"] (mismatched types int and interface{})


断言

空接口interface{}比较特殊,它代表任意类型。如上面的MyMap例子,reflect.TypeOf()反映的该变量的值"理论上,应该是的"数据类型int。但是int类型也属于空接口类型的一种。当MyMap["age"]的值被取出时,也就被标记为interface{}。当下一步运算要使用该值的时候,此时这个值到底是个啥,需要明确一下。断言其实就是起到断定的作用,就相当于告诉程序,这个值就当xx类型用,就这么定了。断言有2个使用方式

package main

import "fmt"


func main() {
var x interface{}
x = 1
//在interface类型的变量后面加".(type)"来断言变量当什么类型数据使用
// 这里把x 当int类型使用,不安全断言
asser_int_x := x.(int) + 1
fmt.Println("断言x类型为<int>计算结果 ", asser_int_x)

var y float32 = 2.22
// 安全断言,获取断言成功状态,返回值是bool
if asser_float_x, ok := x.(float32); !ok {
fmt.Println("x 不能转换为 float32 模式", ok)
} else {
asser_float_x = asser_float_x + y
fmt.Println("断言x类型为<int>计算结果 ", asser_float_x)
}
}

运行结果

% go run main.go
断言x类型为<int>计算结果 2
x 不能转换为 float32 模式 false


回到上面例子,正确获取空接口数据的方式

package main

import "fmt"

func main() {
// 定义一个空接口为值的map
MyMap := make(map[string]interface{})

// 写入嵌套map类型的数据
MyMap["Name"] = "wgw"
MyMap["age"] = 18
MyMap["Info"] = map[string]interface{}{
"addr": "china",
"Id": 1234,
}

// 做一个取值相加的简单计算
x := 1
// 尝试把两个数字相加
x = x + MyMap["age"].(int)
fmt.Println("断言后age相加的结果为:", x)

//同样的道理,嵌套字段 MyMap["Info"] 的类型是 map[string]interface{}
// 要获取这个嵌套字段的下面的Id的内容
// 子map下面的value有多种类型,继续断言子map中的value类型是空接口
MyInfo := MyMap["Info"].(map[string]interface{})
// 断言Id字段的类型是int
MyInfoId := MyInfo["Id"].(int)
y := 4321
y = y + MyInfoId
fmt.Println("断言后Id相加的结果为:", y)
}

运行结果

% go run main.go
断言后age相加的结果为: 19
断言后Id相加的结果为: 5555