英文:
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
&{0 <nil>}
<nil>
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 < 10; i++ {
foo(&b)
}
vs
var b *bar
for i := 0; i < 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论