2016-10-15 6 views
2

構造体へのポインタを同じ型の既に初期化された構造体ポインタの値に代入しようとしています。ポインタ構造体の値を代入する

シンプルなサービスロケータを行うには

コードは私の試みにもかかわらず、この

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 
} 

のようなものです私はhere

必要プレイをしてみてください

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

なランタイムエラーを取得しておきます助けて、ありがとう! JimBで


役立ち、ここでの情報は、固定プレイhttps://play.golang.org/p/_g2AbX0yHV

答えて

3

であるあなたがGetyの値を渡しているので、あなたはその、yに直接ポインタの値をない割り当てることはできません住所。 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

+0

はいうわー、それは間違いなく理にかなって:)おかげでたくさん! –

関連する問題