【问题标题】:reflect, assign a pointer struct value反射,分配一个指针结构值
【发布时间】:2016-10-15 14:17:55
【问题描述】:

我正在尝试将指向结构的指针分配给已初始化的相同类型的结构指针的值。

做一个简单的服务定位器

代码是这样的

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
}

尽管我尝试过,但我不断收到诸如此类的运行时错误

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

试玩here

需要帮助,非常感谢!


有了 JimB 的帮助和信息,这里是固定播放 https://play.golang.org/p/_g2AbX0yHV

【问题讨论】:

    标签: go


    【解决方案1】:

    您不能将指针的值直接分配给y,因为您将y 的值传递给Get,而不是其地址。你可以传入y的地址(类型**Concrete),这样你就可以将一个指针(*Concrete)分配给y。如果直接分配值是安全的,则将注册指针的间接分配给y,但y 必须使用有效值初始化,以便有一个地址可以写入。

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-19
      • 2021-11-26
      • 2022-01-06
      • 1970-01-01
      • 2013-03-04
      相关资源
      最近更新 更多