- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章golang中make和new的区别示例详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
本文主要给大家介绍了关于golang中make和new区别的相关内容,分享出来供大家参考学习,话不多说了,来一起看看详细的介绍:
new 和 make 都可以用来分配空间,初始化类型,但是它们确有不同.
new(T) 返回的是 T 的指针 。
new(T) 为一个 T 类型新值分配空间并将此空间初始化为 T 的零值,返回的是新值的地址,也就是 T 类型的指针 *T,该指针指向 T 的新分配的零值.
1
2
3
4
5
6
7
8
|
p1 := new(int)
fmt.Printf("p1 --> %#v \n ", p1) //(*int)(0xc42000e250)
fmt.Printf("p1 point to --> %#v \n ", *p1) //0
var p2 *int
i := 0
p2 = &i
fmt.Printf("p2 --> %#v \n ", p2) //(*int)(0xc42000e278)
fmt.Printf("p2 point to --> %#v \n ", *p2) //0
|
上面的代码是等价的,new(int) 将分配的空间初始化为 int 的零值,也就是 0,并返回 int 的指针,这和直接声明指针并初始化的效果是相同的.
make 只能用于 slice,map,channel 。
make 只能用于 slice,map,channel 三种类型,make(T, args) 返回的是初始化之后的 T 类型的值,这个新值并不是 T 类型的零值,也不是指针 *T,是经过初始化之后的 T 的引用.
1
2
3
4
5
6
7
8
9
10
|
var
s1 []int
if
s1 == nil {
fmt.Printf(
"s1 is nil --> %#v \n "
, s1)
// []int(nil)
}
s2 := make([]int, 3)
if
s2 == nil {
fmt.Printf(
"s2 is nil --> %#v \n "
, s2)
}
else
{
fmt.Printf(
"s2 is not nill --> %#v \n "
, s2)
// []int{0, 0, 0}
}
|
slice 的零值是 nil,使用 make 之后 slice 是一个初始化的 slice,即 slice 的长度、容量、底层指向的 array 都被 make 完成初始化,此时 slice 内容被类型 int 的零值填充,形式是 [0 0 0],map 和 channel 也是类似的.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
var
m1 map[int]string
if
m1 == nil {
fmt.Printf(
"m1 is nil --> %#v \n "
, m1)
//map[int]string(nil)
}
m2 := make(map[int]string)
if
m2 == nil {
fmt.Printf(
"m2 is nil --> %#v \n "
, m2)
}
else
{
fmt.Printf(
"m2 is not nill --> %#v \n "
, m2) map[int]string{}
}
var
c1 chan string
if
c1 == nil {
fmt.Printf(
"c1 is nil --> %#v \n "
, c1)
//(chan string)(nil)
}
c2 := make(chan string)
if
c2 == nil {
fmt.Printf(
"c2 is nil --> %#v \n "
, c2)
}
else
{
fmt.Printf(
"c2 is not nill --> %#v \n "
, c2)
//(chan string)(0xc420016120)
}
|
make(T, args) 返回的是 T 的 引用 。
如果不特殊声明,go 的函数默认都是按值穿参,即通过函数传递的参数是值的副本,在函数内部对值修改不影响值的本身,但是 make(T, args) 返回的值通过函数传递参数之后可以直接修改,即 map,slice,channel 通过函数穿参之后在函数内部修改将影响函数外部的值.
1
2
3
4
5
6
7
|
func modifySlice(s []int) {
s[0] = 1
}
s2 := make([]int, 3)
fmt.Printf(
"%#v"
, s2)
//[]int{0, 0, 0}
modifySlice(s2)
fmt.Printf(
"%#v"
, s2)
//[]int{1, 0, 0}
|
这说明 make(T, args) 返回的是引用类型,在函数内部可以直接更改原始值,对 map 和 channel 也是如此.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
func modifyMap(m map[int]string) {
m[0] =
"string"
}
func modifyChan(c chan string) {
c <-
"string"
}
m2 := make(map[int]string)
if
m2 == nil {
fmt.Printf(
"m2 is nil --> %#v \n "
, m2)
}
else
{
fmt.Printf(
"m2 is not nill --> %#v \n "
, m2)
//map[int]string{}
}
modifyMap(m2)
fmt.Printf(
"m2 is not nill --> %#v \n "
, m2)
// map[int]string{0:"string"}
c2 := make(chan string)
if
c2 == nil {
fmt.Printf(
"c2 is nil --> %#v \n "
, c2)
}
else
{
fmt.Printf(
"c2 is not nill --> %#v \n "
, c2)
}
go modifyChan(c2)
fmt.Printf(
"c2 is not nill --> %#v "
, <-c2)
//"string"
|
很少需要使用 new 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
type Foo struct {
name string
age int
}
var
foo1 Foo
fmt.Printf(
"foo1 --> %#v\n "
, foo1)
//main.Foo{age:0, name:""}
foo1.age = 1
fmt.Println(foo1.age)
foo2 := Foo{}
fmt.Printf(
"foo2 --> %#v\n "
, foo2)
//main.Foo{age:0, name:""}
foo2.age = 2
fmt.Println(foo2.age)
foo3 := &Foo{}
fmt.Printf(
"foo3 --> %#v\n "
, foo3)
//&main.Foo{age:0, name:""}
foo3.age = 3
fmt.Println(foo3.age)
foo4 :=
new
(Foo)
fmt.Printf(
"foo4 --> %#v\n "
, foo4)
//&main.Foo{age:0, name:""}
foo4.age = 4
fmt.Println(foo4.age)
var
foo5 *Foo =
new
(Foo)
fmt.Printf(
"foo5 --> %#v\n "
, foo5)
//&main.Foo{age:0, name:""}
foo5.age = 5
fmt.Println(foo5.age)
|
foo1 和 foo2 是同样的类型,都是 Foo 类型的值,foo1 是通过 var 声明,Foo 的 filed 自动初始化为每个类型的零值,foo2 是通过字面量的完成初始化.
foo3,foo4 和 foo5 是一样的类型,都是 Foo 的指针 *Foo.
但是所有 foo 都可以直接使用 Foo 的 filed,读取或修改,为什么?
如果 x 是可寻址的,&x 的 filed 集合包含 m,x.m 和 (&x).m 是等同的,go 自动做转换,也就是 foo1.age 和 foo3.age 调用是等价的,go 在下面自动做了转换.
因而可以直接使用 struct literal 的方式创建对象,能达到和 new 创建是一样的情况而不需要使用 new.
小结 。
new(T) 返回 T 的指针 *T 并指向 T 的零值.
make(T) 返回的初始化的 T,只能用于 slice,map,channel.
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对我的支持.
原文链接:http://sanyuesha.com/2017/07/26/go-make-and-new/ 。
最后此篇关于golang中make和new的区别示例详解的文章就讲到这里了,如果你想了解更多关于golang中make和new的区别示例详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我知道它们是匿名类型,但我不明白 Razor 语法。在一些文档中,我找到了这样的示例: @Html.Label("Hello", new { htmlAtributes = new { id = "h
关于:new Object(new Array()) 有一个相当基本的问题,我自己确实无法给出答案,我正在寻求建议: 在js中实例化对象时使用如下方法: var obj = new Object();
在eclipse中右击项目时,“新建文件夹”、“新建源文件夹”和“新建包”有什么区别?他们似乎都在做同样的事情,引用文献并没有说太多。 谢谢 最佳答案 新建文件夹 在项目中创建一个新文件夹。 新建源文
几天来我一直在测试 bolt-cms,我试图了解它是如何工作的。 我想知道新页面、新条目和新展示柜之间有什么区别。 我已阅读 this它并没有填补空白。 最佳答案 Pages、Entries 和 Sh
更新:感谢所有的回答。我发现的最干净的解决方案是这个: if ( k(Arrays.asList(new LinkedList<>())); 我有一个递归方法,可以从列表中生成所有“n 选 k”组合。
我现在想知道这些指令是如何分配内存的。 例如,如果我得到代码怎么办: x = new int[5]; y = new int[5]; 如果分配了这些,它在 RAM 中的实际情况如何?是为每个变量保留整
我希望将其写入output.txt而不清除它 - 只是附加到末尾。但是,当我使用以下两种方法时: public void addEmails(ArrayList emails){ for (i
我正在分配内存,稍后将用于构造具有放置 new 的对象。我应该使用 operator new(n),还是应该使用 new unsigned char[n]?为什么? 最佳答案 因素: new[] 必须
基本上,我的问题是以下代码是否有效。 void* mem = operator new(sizeof(T)); T* instance = new(mem) T; delete instance; 如
很抱歉,如果之前有人问过这个问题,但我想就以下两种用法之间的区别提供一个简明的答案。 VS 似乎将它们都接受为有效代码。 private static void doSomeWork() { /
请告诉我这段代码在做什么,它是否创建多维数组(我认为不是)? 代码片段.. var hanoi_peg = new Array( new Array( 5, 4, 3, 2, 1,
这个问题在这里已经有了答案: String intern() behaviour (4 个答案) When should we use intern method of String on Stri
许多人说您应该避免使用 new Object、new Array(),而是使用 {}。 [] 和真/假。 使用字面量构造来获取对象或数组的新实例而不是使用 new 有什么好处?我知道 Crockfor
我正在开发一个存在内存泄漏的开源库。该库是围绕 boost::asio 构建的数据流服务。服务器端使用堆内存管理系统,该系统提供内存以容纳有限数量的 samples,同时它们等待通过 tcp 连接被推
我从以下函数中得到内存泄漏: int ReadWrite(int socket, char *readfile) { FILE *rf = NULL; rf = fopen(readfile,
在考虑类似的事情时 auto x = new T; 标准是否强制要求内存必须来自operator new——类特定的还是全局的?也就是说,如果缺少特定于类的 operator new,则没有办法从除全
只是出于好奇:为什么 C++ 选择 a = new A 而不是 a = A.new 作为实例化对象的方式?后者不是更像是面向对象的吗? 最佳答案 Just out of curiosity: Why
考虑以下代码: typedef SomeType type_t[2]; SomeType * arr1 = new type_t; //new or new[] ??? type_t * arr2
这个问题在这里已经有了答案: Difference between 'new operator' and 'operator new'? (8 个答案) 关闭 8 年前。 面试题:"new"运算符和
我正在为一个应用程序设计界面,以在 TableLayout 中显示从数据库中提取的一些数据。现在,默认 View 是纵向的,它由一个下拉菜单和一个三列的表格组成。当用户切换到横向时,微调器及其选项可以
我是一名优秀的程序员,十分优秀!