In golang, what is the difference between & and *

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

In golang, what is the difference between & and *

问题

&* 在 Go 语言中有什么区别?能否提供使用 &* 的示例来说明它们的区别?根据我所了解,它们都与访问变量的内存位置有关,但我不确定何时使用 &*

& 是取地址操作符,用于获取变量的内存地址。它返回一个指向变量的指针。例如,如果有一个变量 x&x 将返回 x 的内存地址。

* 是指针解引用操作符,用于访问指针指向的变量。它将一个指针转换为指向的值。例如,如果有一个指针 p*p 将返回指针 p 所指向的值。

下面是一个示例,演示了 &* 的使用:

package main

import "fmt"

func main() {
    x := 10
    p := &x     // 获取变量 x 的内存地址
    fmt.Println(p) // 输出 x 的内存地址
    fmt.Println(*p) // 输出指针 p 所指向的值

    *p = 20       // 修改指针 p 所指向的值
    fmt.Println(x) // 输出修改后的 x 的值
}

在上面的示例中,我们首先使用 & 获取变量 x 的内存地址,并将其赋值给指针 p。然后,我们使用 *p 访问指针 p 所指向的值,并输出它。接下来,我们修改指针 p 所指向的值为 20,并输出变量 x 的值,可以看到 x 的值也被修改了。

希望这个例子能帮助你理解 &* 的区别和用法。

英文:

Can someone explain the difference between & and * in GO lang and provide examples of when & and * would be used to illustrate the difference? From what I have read, they both relate to accessing a variables memory location however I'm not sure when to use & or *.

答案1

得分: 75

这是一个非常简单的示例,说明了&*的用法。请注意,*可以用于两个不同的目的:1)声明一个变量为指针;2)解引用指针。

package main

import "fmt"

func main() {
    b := 6

    var b_ptr *int // *int 用于声明变量 b_ptr 为指向 int 的指针

    b_ptr = &b     // b_ptr 被赋予变量 b 存储位置的地址

    // 上述两行的简写形式是:
    // b_ptr := &b

    fmt.Printf("b_ptr 的地址:%p\n", b_ptr)

    // 我们可以使用 *b_ptr 来获取存储在 b_ptr 地址上的值
    // 这被称为解引用指针
    fmt.Printf("b_ptr 存储的值:%d\n", *b_ptr)
}

结果:

b_ptr 的地址:0xc82007c1f0
b_ptr 存储的值:6
英文:

Here is a very simple example, that illustrates how & and * are used. Note that * can be used for two different things 1) to declare a variable to be a pointer 2) to dereference a pointer.

package main

import "fmt"

func main() {
	b := 6 

	var b_ptr *int // *int is used to declare variable
	               // b_ptr to be a pointer to an int

	b_ptr = &b     // b_ptr is assigned the value that is the
                   // address of where variable b is stored

	// Shorthand for the above two lines is:
	// b_ptr := &b

	fmt.Printf("address of b_ptr: %p\n", b_ptr)

	// We can use *b_ptr to get the value that is stored
	// at address b_ptr, known as dereferencing the pointer
	fmt.Printf("value stored at b_ptr: %d\n", *b_ptr)
	
}

Result:

address of b_ptr: 0xc82007c1f0
value stored at b_ptr: 6

答案2

得分: 27

这帮助我更好地理解了,你可以在playground中运行这段代码并稍微调试一下,看看它的行为如何。链接在这里:https://play.golang.org/p/c7jxLJkdRDd(如果链接在将来被停用,只需复制粘贴下面的代码)

package main

import (
	"fmt"
)

func main() {

	var a = 5
	var p = &a // 通过引用复制
	var x = a  // 通过值复制

	fmt.Println("a =", a)   // a =  5
	fmt.Println("p =", p)   // p =  0x10414020
	fmt.Println("*p =", *p) // *p =  5
	fmt.Println("&p =", &p) // &p =  0x1040c128
	fmt.Println("x =", x)   // x =  5

	fmt.Println("\n Change *p = 3")
	*p = 3
	fmt.Println("a =", a)   // a =  3
	fmt.Println("p =", p)   // p =  0x10414020
	fmt.Println("*p =", *p) // *p =  3
	fmt.Println("&p =", &p) // &p =  0x1040c128
	fmt.Println("x =", x)   // x =  5

	fmt.Println("\n Change a = 888")
	a = 888
	fmt.Println("a =", a)   // a =  888
	fmt.Println("p =", p)   // p =  0x10414020
	fmt.Println("*p =", *p) // *p =  888
	fmt.Println("&p =", &p) // &p =  0x1040c128
	fmt.Println("x =", x)   // x =  5

	fmt.Println("\n Change x = 1")
	x = 1
	fmt.Println("a =", a)   // a =  888
	fmt.Println("p =", p)   // p =  0x10414020
	fmt.Println("*p =", *p) // *p =  888
	fmt.Println("&p =", &p) // &p =  0x1040c128
	fmt.Println("x =", x)   // x =  1
	
	&p = 3 // 错误:不能将值3赋给&p,因为&p是变量a的地址
}
英文:

This helped me understand better, you can run the code in playground and play with it a bit to see how it behaves link here: https://play.golang.org/p/c7jxLJkdRDd (if link is deactivated in the future just copy paste the code below)

package main
import (
"fmt"
)
func main() {
var a = 5
var p = &a // copy by reference
var x = a  // copy by value
fmt.Println("a = ", a)   // a =  5
fmt.Println("p = ", p)   // p =  0x10414020
fmt.Println("*p = ", *p) // *p =  5
fmt.Println("&p = ", &p) // &p =  0x1040c128
fmt.Println("x = ", x)   // x =  5
fmt.Println("\n Change *p = 3")
*p = 3
fmt.Println("a = ", a)   // a =  3
fmt.Println("p = ", p)   // p =  0x10414020
fmt.Println("*p = ", *p) // *p =  3
fmt.Println("&p = ", &p) // &p =  0x1040c128
fmt.Println("x = ", x)   // x =  5
fmt.Println("\n Change a = 888")
a = 888
fmt.Println("a = ", a)   // a =  888
fmt.Println("p = ", p)   // p =  0x10414020
fmt.Println("*p = ", *p) // *p =  888
fmt.Println("&p = ", &p) // &p =  0x1040c128
fmt.Println("x = ", x)   // x =  5
fmt.Println("\n Change x = 1")
x = 1
fmt.Println("a = ", a)   // a =  888
fmt.Println("p = ", p)   // p =  0x10414020
fmt.Println("*p = ", *p) // *p =  888
fmt.Println("&p = ", &p) // &p =  0x1040c128
fmt.Println("x = ", x)   // x =  1
&p = 3 // error: Cannot assign to &p because this is the address of variable a
}

答案3

得分: 8

它们是相反的。如规范中的“地址运算符”部分所解释的:

对于类型为T的操作数x,地址操作&x会生成一个指向x的类型为*T的指针。[...]

对于指针类型*T的操作数x,指针间接引用*x表示由x指向的类型为T的变量。如果xnil,则尝试评估*x将导致运行时恐慌。

换句话说:&接受一个变量(或其他可寻址的实体)并返回指向它的指针,而*接受一个指针并返回它所指向的东西(除非它为nil,表示它不指向任何东西)。

英文:

They are the opposite. As explained in the "Address operators" section of the spec:

> For an operand x of type T, the address operation <code>&amp;x</code> generates a pointer of type *T to <code>x</code>. [&hellip;]
>
> For an operand x of pointer type *T, the pointer indirection *x denotes the variable of type T pointed to by x. If x is nil, an attempt to evaluate *x will cause a run-time panic.

In other words: &amp; takes a variable (or other addressable entity) and returns a pointer that points to it, whereas * takes a pointer and returns the thing that it points to (unless it's nil, meaning it doesn't point to anything).

答案4

得分: 7

&amp; 是取地址运算符。* 在某些情况下表示指针,在其他情况下被用作“解引用运算符”。

所以基本上,如果你执行 p := &amp;SomeType{},取地址运算符被用来返回使用复合字面量语句 SomeType{} 创建的对象的地址,如果我将其移除,我将不再有一个引用,而是直接将值分配给 p。在这种情况下,p 将是一个 *SomeType,因为我取的是该类型的地址。如果我在类型前面加上 *,我就将其指定为该类型的指针。

现在剩下的最后一种用法是作为解引用运算符,我在 Go 中的经验中并不经常使用它,但在 C 和 C++ 中它非常常见。它用于返回实际值,最常用于赋值。例如,如果我有一个 p,它是一个 *SomeType,而我想在本地分配一个 SomeType 的实例,那么我需要以下语句 someType := *p,这样值就会被分配给我的值类型。

希望这个解释有所帮助。这并不是最技术性的解释,而是为了提供对常见用法的理解。

英文:

&amp; is the address of operator. * represent a pointer in some cases, in others it is used as the 'dereference operator'.

So basically, if you do p := &amp;SometType{} the address of operator is used to return the address of the object created with the composite literal statement SomeType{} if I were to remove it, I would no longer have a reference and instead be assigning the value directly to p. In this case p will be a *SomeType because that is the types who's address I took. If I declare a type with * in front of it, I'm designating it as a pointer to that type.

Now the last remaining use is as a the deference operator, you don't use this much in Go in my experience but it was super common in C and C++. This is used to return the actual value rather, it's most often leverage for assignment. Because like if I have p and it is a *SomeType and locally I want to assign to an instance of SomeType then I'll need the following statement someType := *p so that the value is assigned to my value type.

Hope that explanation helps. It's not the most technical one, rather my goal is to provide understanding of the common uses.

答案5

得分: 7

&amp; 将一个变量转换为指针。

* 从指针指向的位置获取存储的值。

对于类型,var *type 表示 "*var 是类型 type 的值"(如果没有变量,则表示 "type 的指针")。

英文:

&amp; makes a pointer from a variable.

* "fetches" the value stored where a pointer points to.

For types, var *type means "*var is of the type type" (and without a variable, it simply means "a pointer to something of type".

答案6

得分: 0

  • &amp; 用于操作数的右侧,返回地址(实际)值。
  • * 用于操作数的左侧,解析地址值。
    type V struct {
    	E map[string]string
    }
    
    // Caller 接收解析后的值
    func New() *V {
        // 返回结构体的地址
    	return &V{E: make(map[string]string)} 
    }
英文:
  • &amp; is Used on the right side of the operand to return the address (actual) value.
  • * is Used on the left side of the operand to resolve the address value.
    type V struct {
E map[string]string
}
//Caller recieves the resolved value
func New() *V {
//Returns the address of the struct
return &amp;V{E: make(map[string]string)} 
}

答案7

得分: -1

b *int
// 创建变量

*b = 5
// 赋值

fmt.Println(*b)
// 获取值

英文:

<b>b *int </b>
// creating variable

<b>*b = 5</b>
// assigning value

<b>fmt.Println(*b)</b>
// getting value

答案8

得分: -7

&和*主要用于函数中:

package main
import (
"fmt"
)
type Person struct {
name     string
ageYears int
areDays  int
}
func main() {
john := Person{name: "John", ageYears: 46}
toDays(&john)
fmt.Println(john) //{John 46 16790}
toDays2(john)
fmt.Println(john) //{John 46 16790}
}
func toDays(p *Person) {
p.areDays = p.ageYears * 365
}
func toDays2(p Person) {
p.areDays = -1
}
英文:

& and * is used mainly in functions:

package main
import (
&quot;fmt&quot;
)
type Person struct {
name     string
ageYears int
areDays  int
}
func main() {
john := Person{name: &quot;John&quot;, ageYears: 46}
toDays(&amp;john)
fmt.Println(john) //{John 46 16790}
toDays2(john)
fmt.Println(john) //{John 46 16790}
}
func toDays(p *Person) {
p.areDays = p.ageYears * 365
}
func toDays2(p Person) {
p.areDays = -1
}

huangapple
  • 本文由 发表于 2015年10月21日 01:17:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/33242850.html
匿名

发表评论

匿名网友

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

确定