简体   繁体   English

混淆在Go中使用指针

[英]Confusing of using pointer in Go

I have my sample code like below. 我有下面的示例代码。

type Apple struct {
    Color string
}
//In this way, the code runs just fine.
func main(){
        var test = 6
        TestTest(&test)
        fmt.Println(test)
        a := Apple{"red"}
        Eat(&a)
        fmt.Println(a.Color)
}


    func TestTest(num *int) {
        *num = *num + 2
    }
    func Eat(a *Apple) {
        a.Color = "green"
    }

the question is, why do I have to put a star(*) before a num variable but not for a.Color ? 问题是,为什么我必须在num变量之前放一个star(*)而不是a.Color If I do so to a.Color , it says 如果我对a.Color这样做,它说

invalid indirect of a.Color (type string) 无效的a.Color(类型字符串)间接

or if I remove a star(*) from num , it says 或者如果我从num删除了star(*),它说

invalid operation: num + 2 (mismatched types *int and int) 无效的运算:num + 2(类型不匹配的* int和int)

that makes me confused, can someone explain why? 这让我感到困惑,有人可以解释为什么吗?

These are two different cases: 这是两种不同的情况:

Case1 情况1

num is a pointer to int, So you need to add the integer value to the value stored at address pointed by num . num是一个指向int的指针,因此您需要将整数值添加到num指向的地址存储的值上。 Hence you are dereferencing the num pointer to get the value stored inside it as: 因此,您要取消引用num指针以获取存储在其中的值,如下所示:

func TestTest(num *int) {
    *num = *num + 2 // dereference the pointer to get the value.
}

Case2 案例2

you are assigning a string value to Color field of Apple struct which is not a pointer. 您正在将字符串值分配给Apple结构的Color字段,而不是指针。 But you are using the pointer to the struct not to the field. 但是您使用的是指向结构的指针,而不是指向字段的指针。 That's why you are able to assign a value like this: 这就是为什么您可以分配这样的值的原因:

func Eat(a *Apple) { // a is the pointer to struct.
    a.Color = "green"
}

Now if you want to generate the same error which is you are getting in first case, create a pointer type Color field inside the struct as: 现在,如果要生成与第一种情况相同的错误,请在结构内部创建一个指针类型Color域,如下所示:

type Apple struct {
    Color *string // this is the pointer value which will throw the same error in your current implementation.
}

Error code on Go playground when trying to assign a pointer type value to a non-pointer variable when using struct. 尝试在使用struct时将指针类型值分配给非指针变量时, Go操场上的错误代码。

Solution

To set the value in case you are using pointer field in a struct use reflection as: 要在使用结构体中的指针字段的情况下设置值,请使用反射:

package main

import (
    "fmt"
    "reflect"
)

//I have my sample code like this.

type Apple struct {
    Color *string
}

//In this way, the code runs just fine.
func main() {
    var test = 6
    TestTest(&test)
    fmt.Println(test)
    point := "red"
    a := Apple{&point}
    Eat(&a)
    fmt.Println(a.Color)
}

func TestTest(num *int) {
    *num = *num + 2
}
func Eat(a *Apple) {
    str := "green"
    r := reflect.ValueOf(a)
    elm := r.Elem().FieldByName("Color")
    elm.Set(reflect.ValueOf(&str))
    fmt.Printf("%+v", (*a).Color)
}

Playground Example 操场上的例子

One more thing to notice is the value of reflection is actually reflect.Ptr so what we can do is we can loop over the struct fields to get the value and then use reflect.Indirect to get the value of the pointer type color field. 需要注意的另一件事是反射的值实际上是reflect.Ptr因此我们可以做的是我们可以遍历结构字段以获取值,然后使用reflect.Indirect来获取指针类型颜色字段的值。

func Eat(a *Apple) {
    str := "green"
    r := reflect.ValueOf(a).Elem()
    elm := r.FieldByName("Color")
    elm.Set(reflect.ValueOf(&str))
    fmt.Printf("%+v\n", (*a).Color)
    for i := 0; i < r.NumField(); i++ {
        valueField := r.Field(i)
        fmt.Println(reflect.Indirect(valueField))
    }
    // or use FieldByName to get the value of a field.
    st := "Color"
    fmt.Println(reflect.Indirect(reflect.ValueOf(a).Elem().FieldByName(st)))
}

Because Go automatically dereferences a pointer before dot property. 因为Go自动在点属性之前取消引用指针。

You can also do it manually by: 您还可以通过以下方式手动进行操作:

(*a).Color = "green"

Your code failed probably because you didn't use the parenthese and it tries to dereference Color property instead of a itself. 您的代码失败,可​​能是因为您未使用括号,而是试图取消引用Color属性而不是其自身。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM