简体   繁体   中英

Golang: convert struct to embedded at offset 0 struct

I have some different structs like Big with Small embedded at offset 0. How can I access Small 's structure fields from code, that doesn't know anything about Big type, but it is known that Small is at offset 0?

type Small struct {
    val int
}

type Big struct {
    Small
    bigval int
}

var v interface{} = Big{}
// here i only know about 'Small' struct and i know that it is at the begining of variable
v.(Small).val // compile error

It seems that compiler is theoretically able to operate such expression, because it knows that Big type has Small type embedded at offset 0. Is there any way to do such things (maybe with unsafe.Pointer )?

Avoid using unsafe whenever possible. The above task can be done using reflection ( reflect package):

var v interface{} = Big{Small{1}, 2}

rf := reflect.ValueOf(v)
s := rf.FieldByName("Small").Interface()

fmt.Printf("%#v\n", s)
fmt.Printf("%#v\n", s.(Small).val)

Output (try it on the Go Playground ):

main.Small{val:1}
1

Notes:

This works for any field, not just the first one (at "offset 0"). This also works for named fields too, not just for embedded fields. This doesn't work for unexported fields though.

type Small struct {
    val int
}

type Big struct {
    Small
    bigval int
}

func main() {
    var v = Big{Small{10},200}
    print(v.val)
}

While answer with reflection is working but it has performance penalties and is not idiomatic to Go.

I believe you should use interface. Like this

https://play.golang.org/p/OG1MPHjDlQ

package main

import (
    "fmt"
)

type MySmall interface {
    SmallVal() int
}

type Small struct {
    val int
}

func (v Small) SmallVal() int {
    return v.val
}

type Big struct {
    Small
    bigval int
}

func main() {
    var v interface{} = Big{Small{val: 3}, 4}
    fmt.Printf("Small val: %v", v.(MySmall).SmallVal())
}

Output:

Small val: 3

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM