new和make

   #首先搞清楚几个问题


  1.声明:只是规定了变量的类型和名字,而没有进行内存分配。
  2.定义:不仅规定了变量的类型和名字,而且进行了内存分配,也可能会对变量进行初始

             化。

---------------------------------------------------------------------------------------------------------------------
  3.初始化:在定义之后赋值为初始化(所以在初始化时或者说前面就已经分配内存了)

                 当对象在创建时获得了一个特定值。

  4.赋值:擦除原有的值,并赋予新值。

     (两者的区别其实就是在创建时给值,还是创建后给值。)

在C++中

int a; //声明并定义a

extern int a; //extern表示声明但不定义a。

extern int a = 2; //任何包含了显示初始化的声明就成了定义

int a = 2; //初始化

a = 3; //赋值

 注:   在一个程序中,变量只能定义一次,却可以声明多次。
        定义分配存储空间,而声明不会。定义完之后才能初始化,所以初始化的时候已经分配          内存

一.new和make区别

1.变量的声明:

var i int
var s string

       变量的声明我们可以通过var关键字,然后就可以在程序中使用。当我们不指定变量的默认值时,这些变量的默认值是他们的零值,比如int类型的零值是0,string类型的零值是"",引用类型的零值是nil。

     


      对于上述例子中的两种类型的声明,我们可以直接使用,对其进行赋值输出。但是如果我们换成引用类型呢?

2.实例描述:

	/*
			var x *int
			*x = 8
			fmt.Println(*x)
		上述指针值为nil,这样直接赋值,会造成程序发生panic
	*/
	var p int
	var x *int
	x = &p
	*x = 8
	fmt.Println(*x)
	//将已经存在的变量p,用它的指针地址 对变量x指针进行地址初始化
	//这样才能正确赋值,而当上述情况,不存在变量时我们应该怎么处理呢?这就可以用到new了

	//一.new篇
	//new是用来进行分配内存的内置函数,应用场景:new可以对不是已经存在的变量进行赋值(引用类型除外)并内存清零
	var t *int
	//fmt.Println(*t)//直接进行取指针值为nil的变量值,会出现panic
	fmt.Println(t) //nil
	t = new(int)
	fmt.Println(*t) //0
	fmt.Println(t)  //0xc000018098
	//可以发现 初始化t其指针值为nil,nil值是不能直接赋值的,会出现panic。而当用new其变量指向新分配的类型为int的指针,其指针地址的值为0xc000018098,这个指针指向的内容的值是0
	//注意:new不同指针类型其零值是不同的 实例如下:
	var y *int
	var z *string
	var b *[5]int
	y = new(int)
	z = new(string)
	b = new([5]int)
	fmt.Println(*y, *z, *b) //0 空值 [0,0,0,0,0]
	fmt.Print(y, z, b)      //0xc0000180f0 0xc00004c250 &[0 0 0 0 0]

	//用new进行赋值
	//1 数组(arrays)赋值
	av := new([5]int)
	fmt.Printf("av: %p %#v \n", &av, av) //av: 0xc000074018 &[5]int{0, 0, 0, 0, 0}
	(*av)[1] = 8
	fmt.Printf("av: %p %#v \n", &av, av) //av: 0xc000006028 &[5]int{0, 8, 0, 0, 0}
	//2 切片(slice)赋值
	//ar := new([]int)
	//fmt.Printf("av: %p %#v \n", &ar, ar) //av: 0xc000074018 &[]int(nil)
	//(*ar)[0] = 8
	//fmt.Printf("av: %p %#v \n", &ar, ar) //panic: runtime error: index out of range

	//而引用类型不能用new进行初始化分配内存该怎么办呢? 这里就用到了make

	//二.make篇
	//make 可以进行开辟内存,并且可以初始化类型零值
	var a *[]int
	fmt.Printf("地址:%p,完整结构:%#v", &a, a) //地址:0xc000006038,完整结构:(*[]int)(nil)
	d := make([]int, 5)                 //分配了内存空间,并初始化了零值
	fmt.Printf("地址:%p,完整结构:%#v", &d, d) //地址:0xc000004078,完整结构:[]int{0, 0, 0, 0, 0}
	c := make(map[string]string)
	fmt.Printf("地址:%p,完整结构:%#v", &c, c) //地址:0xc000006040,完整结构:map[string]string{}

	//make与new的结合运用
	var ddd *map[string]string
	fmt.Printf("ddd: %p %#v \n", &ddd, ddd) //ddd: 0xc042004028 (*map[string]string)(nil)
	ddd = new(map[string]string)
	fmt.Printf("ddd: %p %#v \n", &ddd, ddd) //ddd: 0xc000006028 &map[string]string(nil)
	//(*ddd)["b"] = "b"
	/*这里是不可以的,因为silce、map、channel类型也属于引用类型,go会给引用类型初始化为nil,nil是不能直接赋值的。并且不能用new分配内存。无法直接赋值。*/
	
    *ddd = make(map[string]string)
	(*ddd)["a"] = "a"
	fmt.Printf("ddd: %p %#v \n", &ddd, ddd) //ddd: 0xc042004028 &map[string]string{"a":"a"}

总结:

共同点:都可以在堆上进行内存分配

不同点:
      1.make只用于slice、map以及channel的分配内存和初始化;而new用于类型的内存分 

        配,并且内存置为零。对于引用类型的变量,声明时不会自动初始化,还要手动分配内

        存空间,否则会空指针或invalid memory address,对于值类型的声明时会自动分配内            存并初始化为零值。所以在我们编写程序的时候,就可以根据自己的需要很好的选择

         了。
      2.make返回的类型是 引用类型本身,而new返回的类型是指定类型的指针(指向指定类            型的内存地址)

二.为什么make不返回指针?

       因为 golang其内置类型slice,map,channel 本身就是引用类型,内置结构就自带了指针,所以make不需要返回指针

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值