Go语言中New函数可以用来创建map吗


前言

一个简单的面试题


一、new函数可以创建引用类型吗?

大家都知道go语言中,New(T)是分配内存的内建函数,对于一个已经存在的变量可对其指针进行赋值 ,可以分配任意类型的数据。而引用类型map,slice,channel 是通过make函数来创建。这个题主要是想问New函数是否可以创建引用类型。

答案是可以创建引用类型的,至于能不能用就是另外一回事了,看几个例子吧。

二、示例

1. 声明map

代码如下(示例):

package _3review

import (
	"fmt"
	"testing"
)

func TestNewMap(t *testing.T) {
	var intMap map[string]int // 声明map,没有分配内存的空映射
	fmt.Printf("intMap: %p %#v \n", &intMap, intMap) //intMap: 0xc000012058 map[string]int(nil)
	intMap["test"] = 1
	fmt.Println(intMap) // panic: assignment to entry in nil map
}

当声明map不为其分配内存时候,intMap仅仅是个没有分配内存的空映射,map[string]int(nil)可以看到,map中的元素是nil,并不是0值,此时不能直接赋值,因为没内存。

2. new创建map

代码如下(示例):

package _3review

import (
	"fmt"
	"testing"
)

func TestNewMap(t *testing.T) {
	nMap := new(map[string]int)                // 声明map,为map分配内存!返回的是指向map的指针
	fmt.Printf("nMap: %p %#v \n", &nMap, nMap) // nMap: 0xc0000a4048 &map[string]int(nil)
	(*nMap)["test"] = 1                        // (*nMap)解引用,为map添加元素,因为new函数创建map返回的是指针类型*hmap,需要通过解引用访问指针指向的值。
	fmt.Println(nMap)                          // 依然是空指针,因为map里面元素对象是nil,并未初始化,所以无法赋值
}

使用new(map[string]int) 来创建map,new函数为map分配了内存,并返回指向该内存的指针。这种情况下,nMap 是一个指向 map[string]int 类型的指针变量。然而,new 函数返回的指针指向的内存仍然是未初始化的因此 nMap 的值为指向一个空的映射的指针

所以New创建引用类型,只为其分配内存,不能够初始化零值,无法直接使用。接下来看看make函数。

3. make创建map

func TestMakeMap(t *testing.T) {
	m := make(map[string]int)
	fmt.Printf("m: %p %#v \n", &m, m) //m: 0xc0000a4048 map[string]int{}
	m["test"] = 1
	fmt.Printf("m: %p %#v \n", &m, m) //m: 0xc000012058 map[string]int{"test":1}
	// 结论:make不仅可以开辟一个内存,并且能给这个内存类型初始化零值
}

可以看到make函数为引用类型开辟了空间,并且初始化了零值,可以直接使用。

4. new和make一起创建map

func TestNewMakeMap(t *testing.T) {
	var mv *map[string]int
	fmt.Printf("mv: %p %#v \n", &mv, mv) //mv: 0xc0000a4048 (*map[string]int)(nil)

	mv = new(map[string]int)
	fmt.Printf("mv: %p %#v \n", &mv, mv) // mv: 0xc0000a4048 &map[string]int(nil)

	*mv = make(map[string]int)
	(*mv)["test"] = 1
	fmt.Printf("mv: %p %#v \n", &mv, mv) // mv: 0xc0000a4048 &map[string]int{"test":1}
}

这个case意思是说,要想用new函数创建一个可用的引用类型,需要这么做:

  • 先声明一个指针类型map;
  • 用内置New(T)为这个指针类型的map分配内存;mv 的值为指向一个空的映射的指针;
  • 使用make函数对指针指向的空映射做初始化操作。

如此就可以使用new来创建可用的引用类型,看上去有点复杂,所以才推荐使用make来创建引用类型。


总结

简单总结下,以及这种题怎么回答。

  • new(T)可以为任意类型的数据分配内存,当使用new(T)创建引用类型时,引用类型初始化为nil,对于nil是不能被赋值的。这时需要使用make来初始化零值。
  • make不仅可以开辟一个内存,还能给这个内存的类型初始化其零值。对于引用类型推荐使用make来创建。

make和new的区别?

  • make和new都是golang用来分配内存的内建函数,且在堆上分配内存,make即分配内存,也初始化内存。new只是分配内存,并没有初始化内存。
  • make返回的还是引用类型本身;而new返回的是指向类型的指针。
  • make只能用来分配及初始化引用类型(map,slice,channel); 而new可以分配任意类型的数据。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言map是一种引用类型,所赋值操作会进行浅拷贝,即只会复制指向底层数据的指针,并不会复制底层数据本身。如果需要进行深拷贝,可以通过以下方法实现: 1. 手动复制元素: - 创建一个新的空map。 - 遍历原始map的键值对,将每个键值对复制到新map。 - 这样就创建了一个新的map,其的键值对是原始map键值对的副本。 示例代码: ```go originalMap := map[string]int{"a": 1, "b": 2, "c": 3} // 进行深拷贝 newMap := make(map[string]int) for key, value := range originalMap { newMap[key] = value } // 修改原始map的值 originalMap["a"] = 100 fmt.Println(originalMap) // 输出 map[a:100 b:2 c:3] fmt.Println(newMap) // 输出 map[a:1 b:2 c:3] ``` 2. 使用第三方库: - 可以使用一些第三方库来实现深拷贝,例如`github.com/mitchellh/copystructure`库提供了`copystructure.Copy()`函数,可以用于深拷贝map及其他复杂数据结构。 示例代码: ```go import ( "github.com/mitchellh/copystructure" ) originalMap := map[string]int{"a": 1, "b": 2, "c": 3} // 进行深拷贝 newMap, err := copystructure.Copy(originalMap) if err != nil { // 错误处理 } // 修改原始map的值 originalMap["a"] = 100 fmt.Println(originalMap) // 输出 map[a:100 b:2 c:3] fmt.Println(newMap) // 输出 map[a:1 b:2 c:3] ``` 无论是手动复制元素还是使用第三方库,都可以实现map的深拷贝操作。根据实际需求选择适合的方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值