在“Go”中,星号(*)有什么作用?

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

What does the asterisk do in "Go"?

问题

我一直在阅读并试图理解Go网站上的示例,我一直遇到一种特殊的星号字符,就像这样的示例:

s := "hello"
if s[1] != 'e' {
    os.Exit(1)
}
s = "good bye"
var p *string = &s
*p = "ciao"

另外,我刚刚注意到,&s是什么意思?它是按引用赋值吗(我可能在用PHP的说法)?

英文:

I've been going through and trying to understand the examples on the Go website and I keep coming across a special asterisk character in examples like this:

s := "hello"
if s[1] != 'e' {
    os.Exit(1)
}
s = "good bye"
var p *string = &s
*p = "ciao"

Also, I just noticed, what's with the &s? Is it assignment by reference (I might be using PHP talk here)?

答案1

得分: 156

* 附加到类型 (*string) 表示指向该类型的指针。

* 附加到赋值语句中的变量 (*v = ...) 表示间接赋值。也就是说,改变变量所指向的值。

* 附加到变量或表达式 (*v) 表示指针解引用。也就是说,获取变量所指向的值。

& 附加到变量或表达式 (&v) 表示引用。也就是说,创建指向变量值或字段的指针。

英文:

* attached to a type (*string) indicates a pointer to the type.

* attached to a variable in an assignment (*v = ...) indicates an indirect assignment. That is, change the value pointed at by the variable.

* attached to a variable or expression (*v) indicates a pointer dereference. That is, take the value the variable is pointing at.

& attached to a variable or expression (&v) indicates a reference. That is, create a pointer to the value of the variable or to the field.

答案2

得分: 75

我猜它的意思和C语言中一样

p是一个指向字符串的指针

语句var p *string = &s会将s对象的地址赋给p

下一行*p = "ciao"会改变s的内容

请参考这个链接Language Design FAQ

有趣的是,没有指针算术运算

> 为什么没有指针算术运算?
> 安全性。没有指针算术运算,
> 可以创建一种永远无法得到错误地址的语言。
> 编译器和硬件技术已经发展到了一个地步,
> 使用数组索引的循环可以和使用指针算术运算的循环一样高效。
> 此外,缺乏指针算术运算可以简化垃圾收集器的实现。

英文:

Im guessing it means the same as in C

p is a pointer to a string

The statement var p *string = &s would assign the address of the s object to p

Next line *p = "ciao" would change the contents of s

See this link from the Language Design FAQ

Interestingly, no pointer arithmetic

> Why is there no pointer arithmetic?
> Safety. Without pointer arithmetic
> it's possible to create a language
> that can never derive an illegal
> address that succeeds incorrectly.
> Compiler and hardware technology have
> advanced to the point where a loop
> using array indices can be as
> efficient as a loop using pointer
> arithmetic. Also, the lack of pointer
> arithmetic can simplify the
> implementation of the garbage
> collector.

答案3

得分: 43

Go lang 地址、指针和类型:

s := "hello"      // 字符串类型
t := "bye"        // 字符串类型
u := 44           // 整数类型
v := [2]int{1, 2} // 数组类型
q := &s           // 指针类型

所有这些 Go 变量在内存中都有一个 地址。它们之间的区别是字符串类型保存字符串值,整数类型保存整数值,指针类型保存地址。因此,即使保存地址的变量也有自己的内存地址。

指针:

在变量名前添加 & 可以得到它的地址。或者可以这样理解,"这是我的地址,这样你就知道在哪里找到我了"。

// 创建 p 类型的指针(只能指向字符串)并将值赋给 s 的地址
var p *string = &s // 类型为 *string
// 或者
q := &s // 简写形式,同样的效果

在指针变量前添加 * 可以将指针解引用为它所持有的地址。或者可以这样理解,"将动作传递给我的值所在的地址"。

*p = "ciao"   // 修改 s,而不是 p,p 的值仍然是 s 的地址

// j := *s    // 错误,s 不是指针类型,没有地址可以传递动作
// p = "ciao" // 错误,不能改变为字符串类型

p = &t        // 修改 p,现在指向 t 的地址
//p = &u      // 错误,不能改变为 *int 类型

// 创建 r 类型的指针(指向指针,该指针指向字符串)并将值赋给 p 的地址
var r **string = &p // 简写形式:r := &p

w := (  r == &p) // (r 的值为 p 的地址)w = true
w =  ( *r == p ) // (*r 的值为 p 的值 [t 的地址])w = true
w =  (**r == t ) // (**r 的值为 t 的值)w = true

// 创建 n 类型的指针(指向字符串)并将值赋给 t 的地址(解引用 p)
n := &*p
o := *&t // 无意义的翻转,等同于:o := t

// 将 y 指向数组 v
y := &v
z := (*y)[0] // 解引用 y,获取第一个元素的值,赋给 z(z == 1)

在这里运行 Go 代码:http://play.golang.org/p/u3sPpYLfz7

英文:

Go lang Addresses, Pointers and Types:

s := "hello"      // type string
t := "bye"        // type string
u := 44           // type int
v := [2]int{1, 2} // type array
q := &s           // type pointer

All these Go variables have an address in memory. The distinction between them is string types hold string values, int types hold integer values, and pointer types hold addresses. So even variables that hold addresses have their own memory address.

Pointers:

Adding & before a variable name evaluates to it's address. Or think, "here's my address so you know where to find me."

// make p type pointer (to string only) and assign value to address of s
var p *string = &s // type *string
// or
q := &s // shorthand, same deal

Adding * before a pointer variable dereferences the pointer to the address it is holding. Or think, "pass the action on to the address which is my value."

*p = "ciao"   // change s, not p, the value of p remains the address of s

// j := *s    // error, s is not a pointer type, no address to redirect action to
// p = "ciao" // error, can't change to type string

p = &t        // change p, now points to address of t
//p = &u      // error, can't change to type *int

// make r type pointer (to a pointer which is a pointer to a string) and assign value to address of p
var r **string = &p // shorthand: r := &p

w := (  r == &p) // (  r evaluates to address of p) w = true
w =  ( *r == p ) // ( *r evaluates to value of p [address of t]) w = true
w =  (**r == t ) // (**r evaluates to value of t) w = true

// make n type pointer (to string) and assign value to address of t (deref'd p)
n := &*p
o := *&t // meaningless flip-flop, same as: o := t

// point y to array v
y := &v
z := (*y)[0] // dereference y, get first value of element, assign to z (z == 1)

Go Play here: http://play.golang.org/p/u3sPpYLfz7

答案4

得分: 20

这是我看到的。不同的措辞可能会帮助某人更好地理解它(您可以复制粘贴该代码并检查输出):

package main

import (
	"fmt"
)

func main() {
	// 声明一个类型为 "int" 的变量,其默认值为 "0"
	var y int

	// 打印 y 的值为 "0"
	fmt.Println(y)

	// 打印 y 的地址,类似于 "0xc42008c0a0"
	fmt.Println(&y)

	// 声明一个类型为 "int 指针" 的变量
	// x 只能保存类型为 "int" 的变量的地址
	var x *int

	// 不能简单地将 y 赋值给 x,比如 "x = y",因为这会引发错误,
	// 因为 x 的类型是 "int 指针",而 y 的类型是 "int"

	// 将 y 的地址 "0xc42008c0a0" 赋值给 x
	x = &y

	// 打印 x 的值为 "0xc42008c0a0",这也是 y 的地址
	fmt.Println(x)

	// 打印 x 的地址,类似于 "0xc420030028"
    // (x 和 y 有不同的地址,显然)
	fmt.Println(&x)

	// x 的类型是 "int 指针",保存的是一个类型为 "int" 的变量的地址,该变量的值为 "0",类似于 x -> y -> 0;
	// 通过 x 打印 y 的值为 "0"(解引用)
	fmt.Println(*x)

	// 通过 x 改变 y 的值
	*x = 1; /* 等同于 */ y = 1

	// 打印 y 的值为 "1"
	fmt.Println(y); /* 等同于 */ fmt.Println(*x)
}
英文:

That's how I see it. Different phrasing might help someone to understand it better (you can copy paste that code and examine the output):

package main

import (
	"fmt"
)

func main() {
	// declare a variable of type "int" with the default value "0"
	var y int

	// print the value of y "0"
	fmt.Println(y)

	// print the address of y, something like "0xc42008c0a0"
	fmt.Println(&y)

	// declare a variable of type "int pointer"
	// x may only hold addresses to variables of type "int"
	var x *int

	// y may not simply be assigned to x, like "x = y", because that 
	// would raise an error, since x is of type "int pointer", 
	// but y is of type "int"

	// assign address of y "0xc42008c0a0" as value to x
	x = &y

	// print the value of x "0xc42008c0a0" which is also the address of y
	fmt.Println(x)

	// print the address of x, something like "0xc420030028" 
    // (x and y have different addresses, obviously)
	fmt.Println(&x)

	// x is of type "int pointer" and holds an address to a variable of 
	// type "int" that holds the value "0", something like x -> y -> 0;
	// print the value of y "0" via x (dereference)
	fmt.Println(*x)

	// change the value of y via x
	*x = 1; /* same as */ y = 1

	// print value of y "1"
	fmt.Println(y); /* same as */ fmt.Println(*x)
}

答案5

得分: 6

*字符在C和Go中都用于定义指针。变量不是存储实际值,而是存储值的地址。&运算符用于获取对象的地址。

英文:

The * character is used to define a pointer in both C and Go. Instead of a real value the variable instead has an address to the location of a value. The & operator is used to take the address of an object.

答案6

得分: 2

我不懂Go语言,但根据语法来看,它似乎与C语言相似 - 那是一个指针。它类似于引用,但更低级且更强大。它包含了所讨论项的内存地址。&a获取变量的内存地址,*a对其进行解引用,获取内存地址上的值。

另外,在声明中的*表示它是一个指针。

所以,是的,就像在PHP中一样,s的值会改变,因为p&s指向同一块内存。

英文:

I don't know Go, but based on the syntax, it seems that its similar to C - That is a pointer. Its similar to a reference, but lower level and more powerful. It contains the memory address of the item in question. &a gets the memory address of a variable and *a dereferences it, getting the value at the memory address.

Also, the * in the declaration means that it is a pointer.

So yes, its like in PHP in that the value of s is changed because p and &s point to the same block of memory.

答案7

得分: 0

在golang中,*表示指针。指针保存了一个值的内存地址。

类型*T是指向T值的指针。它的零值是nil。

var p *int

&操作符生成其操作数的指针。

i := 42
p = &i

*操作符表示指针的底层值。

fmt.Println(*p) // 通过指针p读取i的值
*p = 21         // 通过指针p设置i的值

这被称为“解引用”或“间接引用”。

与C不同,Go没有指针算术运算。

package main

import "fmt"

func main() {
    i, j := 42, 2701

    p := &i         // 指向i
    fmt.Println(*p) // 通过指针读取i的值
    *p = 21         // 通过指针设置i的值
    fmt.Println(i)  // 查看i的新值

    p = &j         // 指向j
    *p = *p / 37   // 通过指针将j除以37
    fmt.Println(j) // 查看j的新值
}
英文:

The * in golang as pointers. A pointer holds the memory address of a value.

The type *T is a pointer to a T value. It's zero value is nil.

var p *int

The & operator generates a pointer to its operand.

i := 42
p = &i

The * operator denotes the pointer's underlying value.

fmt.Println(*p) // read i through the pointer p
*p = 21         // set i through the pointer p

This is known as "dereferencing" or "in directing".

Unlike C, Go has no pointer arithmetic.

package main

import "fmt"

func main() {
	i, j := 42, 2701

	p := &i         // point to i
	fmt.Println(*p) // read i through the pointer
	*p = 21         // set i through the pointer
	fmt.Println(i)  // see the new value of i

	p = &j         // point to j
	*p = *p / 37   // divide j through the pointer
	fmt.Println(j) // see the new value of j
}

huangapple
  • 本文由 发表于 2010年8月24日 08:08:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/3552626.html
匿名

发表评论

匿名网友

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

确定