【问题标题】:What is the meaning of '*' and '&'?'*' 和 '&' 是什么意思?
【发布时间】:2016-07-03 17:42:42
【问题描述】:

我正在做http://tour.golang.org/。谁能向我解释一下这个函数第 1、3、5 和 7 行,尤其是 '*' 和 '&' 的作用?通过在函数声明中提及它们,它们应该/期望做什么?一个玩具例子:

    1: func intial1(var1 int, var2 int, func1.newfunc[]) *callproperfunction {
    2:
    3:    addition:= make ([] add1, var1)
    4:    for i:=1;i<var2;i++ {
    5:       var2 [i] = *addtother (randomstring(lengthofcurrent))
    6:    }
    7:    return &callproperfunction {var1 int, var2 int, func1.newfunc[], jackpot}
    8: }

它们似乎是我们在 C++ 中的指针。但我无法将这些概念与我们这里的概念联系起来。换句话说,当我在 Go 的函数声明中使用 '*' 和 '&' 时会做什么。

我知道引用和取消引用是什么意思。我不明白我们如何在 Go 中使用指向函数的指针?例如第 1 行和第 7 行,这两行是做什么的?声明了名为 intial1 的函数返回一个指针?在第 7 行,我们使用 return 函数带参数调用它。

【问题讨论】:

  • 那些指针,就像我们在 C++ 中一样。
  • 它们是指针。您可以访问golang-book.com/books/intro/8 了解有关指针的更多信息。
  • @turhanco,我知道他们是指针。但例如第 5 行和第 7 行是做什么的?它们是函数而不是变量。
  • @David,您的示例看起来不像是有效的 Go 代码。写一个合适的例子,理想情况下可以在 golang.org 上运行。但无论如何,Go 指针与 C++ 中的指针几乎相同。你得到一个带有&amp; 的指针并用* 取消引用它。 * 也用于声明指针类型。就像在 C++ 中一样。
  • @creker,我的问题在第 1 行和第 7 行,其中使用了 callproperfunction,但我无法理解这两行的作用。

标签: go


【解决方案1】:

这可能是 Go 中最令人困惑的事情之一。基本上有3种情况你需要了解:

&amp; 运算符

&amp; 在您想要获取变量的内存地址时放在变量前面。

* 运算符

* 放在一个变量前面,该变量保存一个内存地址并解析它(因此它是&amp; 运算符的对应物)。它去获取指针指向的东西,例如*myString.

myString := "Hi"
fmt.Println(*&myString)  // prints "Hi"

或者更有用的是,类似

myStructPointer = &myStruct
// ...
(*myStructPointer).someAttribute = "New Value"

* 在 Type 前面

* 放在 type 前面时,例如*string,它成为类型声明的一部分,所以你可以说“这个变量包含一个指向字符串的指针”。例如:

var str_pointer *string

所以令人困惑的是* 真的被用于两个独立的(尽管相关的)事物。星号可以是运算符类型的一部分。

【讨论】:

  • 这是IMO最好的解释,应该是选择的答案
  • 我认为 fmt.Println(*&String) 应该是 fmt.Println(*&myString) 。除此之外:很好的解释。
  • @Everett 我认为 * 在类型前面,你应该给出类似于其他两种情况的可靠示例。
【解决方案2】:

您的问题与给出的示例不太匹配,但我会尽量直截了当。

假设我们有一个名为 a 的变量,它保存整数 5 和另一个名为 p 的变量,它将是一个指针。 这就是*&amp; 发挥作用的地方。

用它们打印变量可以产生不同的输出,所以这完全取决于你的情况和你的使用情况。 使用*&amp; 可以节省您的代码行数(这在小型项目中并不重要)并使您的代码更加美观/可读。

&amp; 返回以下变量的内存地址

* 返回以下变量的 (它应该保存变量的内存地址,除非你想得到奇怪的输出和可能的问题,因为你'正在访问您计算机的 RAM)

var a = 5
var p = &a // p holds variable a's memory address
fmt.Printf("Address of var a: %p\n", p)
fmt.Printf("Value of var a: %v\n", *p)

// Let's change a value (using the initial variable or the pointer)
*p = 3 // using pointer
a = 3 // using initial var

fmt.Printf("Address of var a: %p\n", p)
fmt.Printf("Value of var a: %v\n", *p)

总而言之,当使用 * 和 & 时,请记住 * 用于设置您指向的变量的值,而 & 是您指向/想要指向的变量的地址。

希望这个答案有帮助。

【讨论】:

  • 简单地说 & 将指向没有值的变量,而 * 将指向其中有值的变量
【解决方案3】:

那些指针,就像我们在 C++ 中一样。

区别在于:

  • 总是使用.,即pointer.method(),而不是-&gt;

  • 没有悬空指针。返回指向局部变量的指针是完全有效的。 Golang 将确保对象的生命周期,并在不再需要时对其进行垃圾回收。

  • 可以使用new() 或通过创建对象object{} 并使用&amp; 获取其地址来创建指针。

  • Golang 不允许指针算术(数组不会衰减为指针)和不安全的强制转换。所有向下转换都将使用变量的运行时类型进行检查,当实例类型错误时,panic 或返回 false 作为第二个返回值,具体取决于您是否实际采用第二个返回类型。

【讨论】:

  • 此外,默认情况下 Go 不允许不兼容类型之间的指针算术和强制转换(类型转换)。我会说 Go 中的指针更像 Java/C# 中的引用,而不是 C++ 中的指针
  • Go 中没有强制转换——它有类型转换。
  • (我最接近 Go 指针的比较点是 C# ValueType 指针。Java 和 C# object 引用还增加了额外的功能(如虚拟方法)和成本(如对象头)。 )
  • @twotwotwo,对象引用就像 Go 中的接口。它们还支持动态调度和额外开销(接口值也有指向底层类型的指针)
  • @creker 是的,都是真的。
【解决方案4】:

这是迄今为止理解@Everett 答案中解释的所有三种情况的最简单方法

func zero(x int) {
  x = 0
}
func main() {
  x := 5
  zero(x)
  fmt.Println(x) // x is still 5
}

如果您需要在函数内部更改变量,则将内存地址作为参数传递,并使用此内存地址的指针永久更改变量。

注意示例中 int 前面 * 的使用。这里只是表示作为参数传递的变量是int类型的地址。

func zero(xPtr *int) {
  *xPtr = 0
}
func main() {
  x := 5
  zero(&x)
  fmt.Println(x) // x is 0
}

【讨论】:

【解决方案5】:

& Operator 获取内存地址,而 * Opeartor 保存特定变量的内存地址。

【讨论】:

    【解决方案6】:

    简单的解释..就像,你想改变原始值

    func zero(num *int){  // add * to datatype
      *num = 0 // can mutate the original number
    }
    
    i := 5
    zero(&i) // passing variable with & will allows other function to mutate the current value of variable```
    

    【讨论】:

      猜你喜欢
      • 2023-03-08
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 2011-08-12
      • 2017-06-11
      • 2018-03-05
      • 2023-03-27
      • 1970-01-01
      相关资源
      最近更新 更多