在Go语言中使用new和var的区别

huangapple go评论85阅读模式
英文:

Use of new vs var in Go

问题

你有一个带有参数的函数,参数是一个指向某种类型的指针。

type bar struct{...}

func foo(arg *bar)

在以下两种情况下有什么区别吗:

var b bar
foo(&b)

b := new(bar)
foo(b)

使用new关键字会创建一个分配。

英文:

You have a function with an argument, a pointer to a type.

type bar struct{...}

func foo(arg *bar)

Is there any difference between:

var b bar
foo(&b)

and

b := new(bar)
foo(b)

The use of new creates an allocation.

答案1

得分: 14

不,没有区别,与C语言相反,Go语言明确表示可以给一个在本地创建的变量提供指针。

根据文档

注意,与C语言不同,返回本地变量的地址是完全可以的;变量相关的存储在函数返回后仍然存在。

英文:

No, there is no difference, as, contrary to C, Go explicitly states that you can give a pointer to a locally created variable.

From the documentation :

> Note that, unlike in C, it's perfectly OK to return the address of a
> local variable; the storage associated with the variable survives
> after the function returns

答案2

得分: 5

两者都应该表示指向同一个对象的指针,该对象使用相同的默认值进行初始化。

规范中提到:

> 在

type T struct { i int; f float64; next *T }
t := new(T)

> 之后,以下条件成立:

t.i == 0
t.f == 0.0
t.next == nil

> 同样,在

var t T

也是如此:

> 对复合字面量取地址(§地址运算符)会生成指向该字面量值的唯一实例的指针。

var pointer *Point3D = &Point3D{y: 1000}
英文:

Both should represent the same pointer to the same object initialized with the same default value.

The spec does mention:

> After

type T struct { i int; f float64; next *T }
t := new(T)

> the following holds:

t.i == 0
t.f == 0.0
t.next == nil

> The same would also be true after

var t T

Also:

> Taking the address of a composite literal (§Address operators) generates a pointer to a unique instance of the literal's value.

var pointer *Point3D = &Point3D{y: 1000}

答案3

得分: 1

一个将空指针赋值,另一个将指针赋值为一个零初始化的结构体。在一个链表样式的例子中:

type Node struct { 
  Data int
  Next *Node
}

用上述两种方式创建一个节点

var node1 = new(Node)
var node2 *Node

打印这些变量会得到

&{0 <nil>}
<nil>

这意味着如果你尝试这样做

fmt.Println(node1.Data)
fmt.Println(node2.Data)

第一个将打印出0,第二个将抛出一个空指针解引用异常并且引发恐慌。

英文:

One assigns a nil pointer, the other assigns a pointer to a zero initialized struct. In a linked list style example:

type Node struct { 
  Data int
  Next *Node
}

Create a node in each of the mentioned ways

var node1 = new(Node)
var node2 *Node

Printing the variables gives

&amp;{0 &lt;nil&gt;}
&lt;nil&gt;

This means that if you were to try to do this

fmt.Println(node1.Data)
fmt.Println(node2.Data)

The first will print out 0, the second will throw a nil pointer dereference exception and panic.

答案4

得分: -4

在某些情况下存在差异。new(T),顾名思义,返回一个类型为T的新实例,而var b T是一个单一的实例,一次性的(直到其生命周期结束,即超出范围,不可访问...)。

考虑以下循环:

var b bar
for i := 0; i < 10; i++ {
    foo(&b)
}

var b *bar
for i := 0; i < 10; i++ {
    b = new(b)
    foo(b)
}

在后一种情况下,如果foo例如将其arg存储在某个容器中,则会导致存在10个bar实例,而前一种情况只有一个变量b

另一个区别在于性能。变量b可能是一个完全静态的全局变量,或者通常位于某个函数/方法调用记录的静态已知偏移量处(通常是堆栈帧的一个花哨名称)。然而,new(如果没有被编译器优化掉)是一个内存分配器调用。这样的调用会消耗一些非零时间。如果在循环中进行,并且实际上并不需要,那么它可能会导致某些代码路径的明显减速。

英文:

There are a differences in certain situations. new(T), as the name implies, returns a, well, new instance of type T, while var b T is a single instance, once and forever (err, actually until end of its lifetime == going out of scope, not reachable...).

Consider this loop

var b bar
for i := 0; i &lt; 10; i++ {
    foo(&amp;b)
}

vs

var b *bar
for i := 0; i &lt; 10; i++ {
    b = new(b)
    foo(b)
}

In the later case, if foo for example stores its arg in some container, results in 10 instances of bar existing while the former case with only one - in variable b.

Another difference is in the performance. The variable b would be either a fully static global variable or will typically sit at a statically known offset in some function/method invocation record (a fancy name for usually a stack frame). new OTOH, if not optimized out by the compiler, is a memory allocator call. Such call will cost some nonzero time. If made in a loop and not actually necessary, then it can make noticeable slowdown of some code path.

huangapple
  • 本文由 发表于 2012年9月8日 17:11:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/12329493.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定