duanba8070 2018-10-04 04:18
浏览 50
已采纳

混淆在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? If I do so to a.Color, it says

invalid indirect of a.Color (type string)

or if I remove a star(*) from num, it says

invalid operation: num + 2 (mismatched types *int and int)

that makes me confused, can someone explain why?

  • 写回答

2条回答 默认 最新

  • drhgzx4727 2018-10-04 04:21
    关注

    These are two different cases:

    Case1

    num is a pointer to int, So you need to add the integer value to the value stored at address pointed by num. Hence you are dereferencing the num pointer to get the value stored inside it as:

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

    Case2

    you are assigning a string value to Color field of Apple struct which is not a pointer. 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:

    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.

    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.

    func Eat(a *Apple) {
        str := "green"
        r := reflect.ValueOf(a).Elem()
        elm := r.FieldByName("Color")
        elm.Set(reflect.ValueOf(&str))
        fmt.Printf("%+v
    ", (*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)))
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 #MATLAB仿真#车辆换道路径规划
  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘