Can we extract the struct from interface and put it in another interface

I am working on creating some testbeds that depends on some other package, now the package owner has changed the signature of one method which was initially a struct and now he has started passing interface, now as I was creating a different interface now my code has started failing

so I am just wondering if there is any way I can copy the struct present in the interface that I receive in my method then I will not have to make many changes
below is the struct

there are 2 interfaces
consumer.TraceConsumer
testbed.MockTraceDataConsumer

Initially we were having a method start which implements Start(struct a,)
now the package owner has changed the implementation of this method and made it like Start(interface b)
now I wanted to extract the struct presnt in this interface and then pass it to my next method, is it possible .

to make it more Understandable, adding a below code

type MockTraceConsumer struct {
	numSpansReceived atomic.Uint64
	backend          *MockBackend
}

type TraceConsumer interface {
	ConsumeTraces(ctx context.Context, td pdata.Traces) error
}

type MockTraceDataConsumer interface {
	MockConsumeTraceData(spansCount int) error
}

method I have to implement
Start(TraceConsumer)

I want to convert this interface TraceConsumer to  MockTraceDataConsumer,
so one way that i can think of is extracting the struct  MockTraceConsumer from the interface TraceConsumer and and pass it to my interface MockTraceDataConsumer

please let me know if that is possible.

Sorry, I don’t quite understand the problem. Is it like this? https://play.golang.org/p/nFaeF5ertFw

If so, you could do this: https://play.golang.org/p/mj98K_o78GM

1 Like

Thanks for the reply I have made some changes in the sample you shared earlier, I hope it is better now
also in comment I have mentioned what I want to achieve
https://play.golang.org/p/R6YaJSCMEE5

So it’s more like this? https://play.golang.org/p/UGhDahuHhx_w If so, does this work https://play.golang.org/p/qrpmcq5doeA

Thanks sean, I think this will also not work as in NewFunc() you are returning the old function only

func (n newFromOld) NewFunc() int { return n.o.OldFunc() }

let me show you the real code on github

this is the old method signature

https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/700/files#diff-8035efcefc9a36760d52eaf93887cf41R41

now the lib that I was depending has changed the interface.

https://github.com/open-telemetry/opentelemetry-collector/blob/master/testbed/testbed/receivers.go#L47 

the start method is getting called from here

https://github.com/open-telemetry/opentelemetry-collector/blob/master/testbed/testbed/mock_backend.go#L87

which is just passing the struct MockTraceConsumer

so without change any code in collector package can I how can use it in my collector-contrib package.

So you want *MockAwsXrayDataReceiver from the github.com/open-telemetry/opentelemetry-collector-contrib package to implement DataReceiver from the github.com/open-telemetry/opentelemetry-collector package?

yes exactly.

And why don’t you just change line 41 of mockawsxraydatareceiver.go from:

func (ar *MockAwsXrayDataReceiver) Start(tc *testbed.MockTraceConsumer, mc *testbed.MockMetricConsumer) error

to

func (ar *MockAwsXrayDataReceiver) Start(tc consumer.TraceConsumer, mc consumer.MetricsConsumer, lc consumer.LogsConsumer) error {

And why don’t you just change line 41 of mockawsxraydatareceiver.go from:

because I need to pass the object of *testbed.MockTraceConsumer in line 51

calling the new method mockawsreceiver

https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/700/files#diff-8035efcefc9a36760d52eaf93887cf41R51

this object is received in trace_receiver which accepts only object of interface *testbed.MockTraceConsumer and after that it call method MockConsumeTraceData(count)
this method is only define in interface *testbed.MockTraceConsumer and not it consumer.TraceConsumer

MockConsumeTraceData(count) method call code snippet

https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/700/files?file-filters%5B%5D=.go#diff-e7727f150535787f058976c1a94736f3R126

trace_receiver New() method definition code snippet

https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/700/files?file-filters%5B%5D=.go#diff-e7727f150535787f058976c1a94736f3R49

Implementation of method MockConsumeTraceData(count) code snippet

https://github.com/open-telemetry/opentelemetry-collector/blob/master/testbed/testbed/mock_backend.go#L222

Call to Start method code snippet

https://github.com/open-telemetry/opentelemetry-collector/blob/master/testbed/testbed/mock_backend.go#L87

To extract a struct from an interface, you just have to do a type assertion on the interface with the struct type you are expecting to extract.

Example: https://play.golang.org/p/izvMOwq-nXM

I’m not sure what’s going on in this project, so it has been very hard for me to provide any specific advice. It seems that you added support for some functionality and then the API changed so now your code doesn’t work. I’m looking at other receiver implementations but they all use consumer.TraceConsumer or consumer.MetricConsumer from what I’ve seen. It looks like there’s a helper function, ToTraces that can convert a byte slice into *pdata.Traces that can then be passed on to a consumer.TraceConsumer, but that looks like it (maybe?) only deals with UDP segments. I’m not sure if it will work for you with the body of an *http.Request from (*MockAwsXrayReceiver).handleRequest. You might need to check out diffs from other receivers to see how they handled the change.