0

golang中关于map的创建初始化问题

 2 years ago
source link: https://www.yangyanxing.com/article/create-map-in-golang.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

之前写python 脚本比较多,对于python中的字典类型数据,创建非常简单,很灵活,但是在golang中有时却很不习惯,从而造成一些困扰。 本文记录一下在golang中创建map的一些细节问题。

golang的变量分为值类型与引用,值类型包括整型、浮点型、bool型、string 数组、结构体 变量地址中直接保存值,对于值类型的变量,声明以后,如果不赋值,那么变量的值为该类型的零值,如整型为0, bool类型为false,golang 的引用类型包括 slice、map、channel、function、pointer 等,如果没有赋值则为nil, 对于nil的变量,是不可以直接使用的。

值类型变量的创建

值类型的数据可以通过var xxx type 来声明,声明的时候可以不赋值,如果不赋值就是默认的零值,也可以使用短变量声明的方式,a := xxx, 这里golang会自己根据后面的值来判断变量的类型.

func main() {
	var s string
	var i int
	ii := false
	fmt.Println(s, i, ii, &s, &i, &ii)
}

以上代码 s为"", i为0,ii为 false,是bool类型。

对于值类型的数据,无论它是否显示的进行初始化,我们在尝试打印它的地址的时候,都可以正常的获取到地址,即变量的地址不是nil

创建map的几种方式

  1. 使用var 方式 使用 var m map[string]int 来声明一个map[string]int 类型的变量,我们来打印一下该变量的内存地址,为 0x0
func main() {
	var m map[string]int
	if m == nil {
		fmt.Println("m is nil")
	}

	fmt.Printf("%p\n", m)
}

当判断是否为nil时,打印出来了 m is nil

当尝试给nil的map 进行赋值时,会直接崩溃 m["age"] = 18, 当执行这段代码时就会panic。

  1. new 方式 new(Type) 方式返回的是*Type, 返回的是一个指针,这里的指针已经不是空指针了,是有具体的内存地址了
func main() {

	m := new(map[string]int)
	if m == nil {
		fmt.Println("m is nil")
	}

	fmt.Printf("%p\n", m)
	fmt.Println(*m)
}

这里判断m==nil 失败.

但是依然不能给这个 m 赋值, (*m)["age"]=18 依然提示是向nil map 赋值, 需要将 m 指向一个具体的值后才可以正常的赋值

func main() {

	m := new(map[string]int)
	*m = map[string]int{}

	(*m)["name"] = 18
	fmt.Println(*m)
}
  1. make 方式
func main() {

	m := make(map[string]int)
	fmt.Printf("%p\n", m)
	fmt.Println(m)
	m["age"] = 9
	fmt.Println(m)
	fmt.Printf("%p\n", m)
}

使用make方式可以返回一个声明并初始化的变量,对于这个变量,我们可以对其进行直接操作。 上面代码输出为

0xc00006e180
map[]
map[age:9]
0xc00006e180
  1. 声明的时候并初始化 这种方式是比较传统的,可以将其想象成 var s string = "name"
func main(){
  var m = map[string]int{} //这里的{} 不能少
  m["age"] = 18
  fmt.Pringln(m)
}

json 中的应用

有很多时候,我们将json进行反序列化的时候,会转成结构体或者map,

func main() {
	jstr := `{"name":"yangyanxing", "age": 18}`
	var m map[string]interface{}
	mm := make(map[string]interface{})
	var mmm = map[string]interface{}{}
	var mmmm = new(map[string]interface{})
	json.Unmarshal([]byte(jstr), &m)
	json.Unmarshal([]byte(jstr), &mm)
	json.Unmarshal([]byte(jstr), &mmm)
	json.Unmarshal([]byte(jstr), mmmm)
	fmt.Println(m)
	fmt.Println(mm)
	fmt.Println(mmm)
	fmt.Println(*mmmm)
}

上面四种方式初始化map对象,在json.Unmarshl 方法都可以将json 转为map,注意使用new 返回的本身就是指针了,就不用再用& 取地址符了,其实即使用的取地址符,也可以得到相同的结果。

面试官:Golang 的 new 与make 区别是什么?


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK