dongsi1944 2016-10-15 14:17
浏览 33
已采纳

反映,分配一个指针结构值

I m trying to assign a pointer to a struct to the value of an already initialized struct pointer of the same type.

To do a simple service locator

Code is like this

package main

import (
  "fmt"
  "reflect"
)

type Concrete struct {}
func (c *Concrete) Do(){}

type Doer interface {
    Do()
}

func main() {
    l := ServiceLocator{}
    l.Register(&Concrete{})

    var x Doer
    if l.Get(&x); x!= nil {
        fmt.Println("by interface pointer ok")
    }

    // This is not possible in my understanding
    //var z Doer
    //if l.Get(z); z!= nil {
    //  fmt.Println("by interface ok")
    //}

    var y *Concrete
    if l.Get(y); y!= nil {
        fmt.Println("by struct pointer ok")
    }
}

type ServiceLocator struct {
  services []interface{}
  types []reflect.Type
  values []reflect.Value
}

func (s *ServiceLocator) Register(some interface{}) {
  s.services = append(s.services, some)
  s.types = append(s.types, reflect.TypeOf(some))
  s.values = append(s.values, reflect.ValueOf(some))
}

func (s *ServiceLocator) Get(some interface{}) interface{} {
  k := reflect.TypeOf(some).Elem()
  kind := reflect.TypeOf(some).Elem().Kind()
  for i, t := range s.types {
    if kind==reflect.Interface && t.Implements(k) {
      reflect.Indirect(
        reflect.ValueOf(some),
      ).Set(s.values[i])
    } else if kind==reflect.Struct && k.AssignableTo(t.Elem()) {
      fmt.Println(reflect.ValueOf(some).Elem().CanAddr())
      fmt.Println(reflect.ValueOf(some).Elem().CanSet())
      fmt.Println(reflect.Indirect(reflect.ValueOf(some)))
      reflect.ValueOf(some).Set(s.values[i])
    }
  }
  return nil
}

Despite my attempts i keep getting runtime errors such

panic: reflect: reflect.Value.Set using unaddressable value

try the play here

need help, thanks a lot!


With JimB helps and information here is the fixed play https://play.golang.org/p/_g2AbX0yHV

  • 写回答

1条回答 默认 最新

  • duanmeng3126 2016-10-15 17:48
    关注

    You can't assign the value of a pointer directly to y, because you're passing the value of y into Get, not its address. You could pass in the address of y (type **Concrete), so that you could assign a pointer (*Concrete) to y. If it's safe to assign the value directly, you assign the indirection of the registered pointer to y, but y must be initialized with a valid value so that there's an address to write to.

    n := 42
    p := &n
    
    x := new(int)
    // set the value to *x, but x must be initialized
    reflect.ValueOf(x).Elem().Set(reflect.ValueOf(p).Elem())
    fmt.Println("*x:", *x)
    
    var y *int
    // to set the value of y directly, requires y be addressable
    reflect.ValueOf(&y).Elem().Set(reflect.ValueOf(p))
    fmt.Println("*y:", *y)
    

    https://play.golang.org/p/6tFitP4_jt

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 phython读取excel表格报错 ^7个 SyntaxError: invalid syntax 语句报错
  • ¥20 @microsoft/fetch-event-source 流式响应问题
  • ¥15 ogg dd trandata 报错
  • ¥15 高缺失率数据如何选择填充方式
  • ¥50 potsgresql15备份问题
  • ¥15 Mac系统vs code使用phpstudy如何配置debug来调试php
  • ¥15 目前主流的音乐软件,像网易云音乐,QQ音乐他们的前端和后台部分是用的什么技术实现的?求解!
  • ¥60 pb数据库修改与连接
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?