[go-nuts] Accessing interface fields

2,630 views
Skip to first unread message

Phil Bayfield

unread,
May 9, 2010, 7:44:10 PM5/9/10
to golang-nuts
If I have an interface such as...

type SomeInterface {
    SomeFunc()
    SomeOtherFunc()
}

Then a number of objects which implement it and also have some other fields such as...

type ObA struct {
    SomeField    int
    SomeOtherField    string
}

func (a *ObA) SomeFunc() { ... }
func (a *ObA) SomeOtherFunc() { ... }

Finally a function which returns SomeInterface...

func DoSomething() SomeInterface { ... }

If DoSomething actually returns an instance of ObA, I can call the methods defined by the interface SomeInterface, but I cannot access SomeField or SomeOtherField - get error like something is undefined (type SomeInterface has no field SomeField)

Is there some way round this? In the real program there are 20+ types that implement the same interface but all have some different additional fields which I need to access, the alternative would be very messy.

Daniel Smith

unread,
May 9, 2010, 7:54:39 PM5/9/10
to ph...@bayfmail.com, golang-nuts
If I understand you correctly, it sounds like you might be looking for a type assertion.

if oba, ok := someinterface.(*ObA); ok {
    x = oba.SomeField
--
Daniel Smith
http://www.schaumburggoclub.org/

Steven

unread,
May 9, 2010, 11:37:02 PM5/9/10
to Daniel Smith, ph...@bayfmail.com, golang-nuts
If you're picking between many options, a type switch might be cleaner.

switch val := someInterface.(type) {
case SomeType:
....
case SomeOtherType:
doSomethingWith(val.SomeField)
}

I suggest you read the documentation on golang.org. You can pretty
much learn everything you need to know about Go by reading the
language specification, effective go, and the various FAQ. It also
might be a good idea, once you've mastered the syntax, to read the
package documentation (not all of it, but anything you're interested
in).

Russ Cox

unread,
May 9, 2010, 11:46:48 PM5/9/10
to ph...@bayfmail.com, golang-nuts
Interfaces are only about methods.
If you have common fields then you could put get/set accessors
in the interface or maybe a getter that returns a pointer to the field.

You don't have to write the accessor methods for every type.
Given

type common struct {
x int
y float
}
func (c *common) X() *int { return &c.x }
func (c *common) Y() *float { return &c.y }

you can embed common in your structs and get the fields
and methods automatically:

type ObA struct {
common
z bool
}

You'd have to define the method for getting at Z if you
wanted one, but X and Y would be taken care of.

You can embed as many different structs as you like,
so you might have a different one for each commonly grouped
set of fields (perhaps with more descriptive names than
"common") and then mix and match as needed when
constructing the real types.

Russ

Archos

unread,
May 10, 2010, 4:14:39 AM5/10/10
to golang-nuts

Russ Cox:
> Interfaces are only about methods.
> If you have common fields then you could put get/set accessors
> in the interface or maybe a getter that returns a pointer to the field.
>
> You don't have to write the accessor methods for every type.
> Given
I think it could be used public fields instead of add get accesors.

type common struct {
X int
Y float

Phil Bayfield

unread,
May 10, 2010, 5:22:25 AM5/10/10
to r...@golang.org, golang-nuts
I have something a bit like this already, which works for certain fields that are shared between each of the structs.

Unfortunately most of the fields are different for each (they represent different fields of data packets) and some have 20+ fields in them.

I've managed to come up with a little work around using reflection, it's not that pretty but it works:

func (s *SomeStruct) GetInterface() interface{} {
v := reflect.NewValue(s)
p := v.(*reflect.PtrValue)
return p.Elem().Interface()
}

theStruct := something.GetInterface().(SomeStruct)

I can now access all the fields and it still satisfies the interface.

roger peppe

unread,
May 10, 2010, 6:22:15 AM5/10/10
to ph...@bayfmail.com, r...@golang.org, golang-nuts
On 10 May 2010 10:22, Phil Bayfield <ph...@bayfmail.com> wrote:
> I've managed to come up with a little work around using reflection, it's not
> that pretty but it works:
>
> func (s *SomeStruct) GetInterface() interface{} {
> v := reflect.NewValue(s)
> p := v.(*reflect.PtrValue)
> return p.Elem().Interface()
> }
>
> theStruct := something.GetInterface().(SomeStruct)
>
> I can now access all the fields and it still satisfies the interface.

i'm not quite sure what problem you're trying to solve here, but
is there any difference between your code and this?

func (s *SomeStruct) GetInterface() interface{} {
return *s
}

Phil Bayfield

unread,
May 10, 2010, 6:51:18 AM5/10/10
to roger peppe, r...@golang.org, golang-nuts
Yes, you're right it's practically the same thing!
I was trying to do something else with the reflection and looks like I got things a bit jumbled, thanks for pointing that out :)

Russ Cox

unread,
May 10, 2010, 1:24:08 PM5/10/10
to roger peppe, ph...@bayfmail.com, golang-nuts
> i'm not quite sure what problem you're trying to solve here, but
> is there any difference between your code and this?
>
>  func (s *SomeStruct) GetInterface() interface{} {
>    return *s
> }
>
> theStruct := something.GetInterface().(SomeStruct)

Even better:

func (s *SomeStruct) SomeStruct() *SomeStruct {
return s
}

theStruct := something.SomeStruct()

Phil Bayfield

unread,
May 10, 2010, 1:47:49 PM5/10/10
to r...@golang.org, roger peppe, golang-nuts
I don't think that would work as the function would no longer satisfy the interface?

Taru Karttunen

unread,
May 11, 2010, 2:14:31 AM5/11/10
to Archos, golang-nuts


> Russ Cox:
> > type common struct {
> > x int
> > y float
> > }
> > func (c *common) X() *int { return &c.x }
> > func (c *common) Y() *float { return &c.y }
> >
> > you can embed common in your structs and get the fields
> > and methods automatically:
> >
> > type ObA struct {
> > common
> > z bool
> > }

I have found the following pattern quite useful:

type common struct { ... }
type foo struct { common ; ... }
type bar struct { common ; ... }
type interface MyIFace {
getCommon() *common
...
}
func (c*common)getCommon() { return c }



- Taru Karttunen
Reply all
Reply to author
Forward
0 new messages