Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
321 views
in Technique[技术] by (71.8m points)

reflection - Generic Programming in Go. Avoiding hard coded type assertion

I'm programming a generic cache mechanism and i need to set some attributes in a struct knowing only their reflect.Type, attribute name and reflect.Value to be setted in the attribute, but i can't avoid the type assertion, that makes my code not generic...

func main() {
    addressNew := Address{"New Address description!"}

    // In the real problem, i know the reflect.Type of value, but
    // the struct came to me as a interface{}, just like this method
    // Return many kinds of values from redis as interface{}, 
    // (Customer, Order, Address, Product, SKU etc), in a generic way,
    // but returns the reflect.Type of value also.
    interfaceSomeValue := getMyValue()

    fmt.Printf("%v", interfaceSomeValue)
    fmt.Println("")

    // This portion of code comes from my cache mechanism, that is a library 
    // used by other projects. My cache lib really can't know all others
    // type structs to perform the type assertion, but the cache mechanism know 
    // the reflect.Type of the interface. 
    // If you try at this way, will cause a panic by try to access a FieldByName
    // in a interface, because the Customer comes from getMyValue and 
    // becomes a interface{}, and now a type assertion is 
    // required -> http://play.golang.org/p/YA8U9_KzC9
    newCustomerNewAttribute := SetAttribute(&interfaceSomeValue, "Local", interface{}(addressNew), reflect.TypeOf(Customer{}))

    fmt.Printf("%v", newCustomerNewAttribute)
    fmt.Println("")
}

func SetAttribute(object interface{}, attributeName string, attValue interface{}, objectType reflect.Type) interface{} {
    if reflect.ValueOf(object).Kind() != reflect.Ptr {
        panic("need a pointer")
    }

    value := reflect.ValueOf(object).Elem()
    field := value.FieldByName(attributeName)
    valueForAtt := reflect.ValueOf(attValue)
    field.Set(valueForAtt)
    return value.Interface()
}

Go Playground for the problem (works by hard coded type assertion)...

Go Playground for the problem (doesn't work with an unknown interface)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...