How do you use Thrift's TMemoryBuffer in Golang? - go

In Go, I have a byte array data []byte which I am trying to read into an object generated by Thrift. In C# the working code is as follows:
var request = new Request();
using (var transport = new TMemoryBuffer(data))
using (var protocol = new TBinaryProtocol(transport))
{
request.Read(protocol);
}
However in Go, it does not work:
request := app.NewRequest()
transport := thrift.TMemoryBuffer{
Buffer: bytes.NewBuffer(data),
}
protocol := thrift.NewTBinaryProtocolTransport(transport) // error here
request.Read(protocol)
The error it gives is:
cannot use memoryBuffer (type thrift.TMemoryBuffer) as type thrift.TTransport in argument to thrift.NewTBinaryProtocolTransport:
thrift.TMemoryBuffer does not implement thrift.TTransport (Close method has pointer receiver)
I am unsure of how to fix this, as TMemoryBuffer does not seem to implement TTransport and I can't find documentation of how TMemoryBuffer should be used instead.

The important part of that error is Close method has pointer receiver.
A function can be defined on a type, or a pointer to that type (i.e a pointer receiver), the TTransport interface defines a function Close with a pointer receiver.
Read the tour of go for a refresher on pointer receivers.
Changing your code to the following, should work:
transport := &thrift.TMemoryBuffer{
Buffer: bytes.NewBuffer(data),
}
One way to think about the problem would be that thrift.TMemoryBuffer does not have Close function defined on it, but that *thrift.TMemoryBuffer does. And the function NewTBinaryProtocolTransport requires a type with a Close function defined as specified by the interface.

Related

Obtaining an addressable copy of a reflect.Value

I want to add marshalling/unmarshalling to types that I accept, in a way similar JSON custom encoding/decoding. I have it all working great when the type implements a Marshal method (value receiver) and Unmarshal method (pointer receiver).
The Unmarshal method must obviously use a pointer receiver so that the new value is saved. I have been told that a Marshal method using a pointer (not value) receiver should also be allowed. The trouble with this is I am using a reflect.Value which is not always addressable.
Here's an edited extract of the code which panics:
var v reflect.Value // passed in parameter
t := v.Type()
pt := reflect.TypeOf(reflect.New(t).Interface())
if t.Implements(reflect.TypeOf((*Marshaler)(nil)).Elem()) {
str, err = v.Interface().(Marshaler).MarshalXXX()
// ... value receiver WORKS FINE
} else if pt.Implements(reflect.TypeOf((*Marshaler)(nil)).Elem()) {
str, err = v.Addr().Interface().(Marshaler).MarshalXXX()
// ptr receiver gives PANIC value is not addressable
I tried creating a copy of v, but the copy is also not addressable which makes no sense to me:
tmp := reflect.New(v.Type())
tmp.Addr().Set(v)
str, err = tmp.Interface().(Marshaler).MarshalXXX()
In case I have not explained this well here is an example on the Go Playground for you to try:
Also while I am here: Is there a better way to get the type of a pointer to a the type than in the assignment to pt above?
I found the answer. The problem was I was using Addr instead of Elem. Though that begs the question why Set worked, since the panic did not occur till the following line.
In summary, to create an addressable copy of a reflect.Value v do this:
tmp := reflect.New(v.Type()) // create zero value of same type as v
tmp.Elem().Set(v)
Please forgive me asking prematurely, but I had already spent 4 hours trying to solve the problem. For completeness here is the fix to my Go playground code in the question.

Declare a variable without datatype

I have a piece of code that needs a variable declaration w/o its type. The variable is assigned a value later and that is an interface. pseudo code will look very similar to this:
var client
if some_condn {
client = ssh.Dial(params)
} else {
client = my_own_ssh_dial(my_params)
}
session,_ := client.NewSession()
The problem is GO does not allow a variable declaration w/o type. Is there any way I can use something like an generic Object (from Java) to default client to start with?
TIA
A variable must have a type in order to use it. The closest thing to an untyped variable would be the type interface{}, which is an interface type, but has no methods to call.
Since the goal here is to call the NewSession method, declare the variable with an interface containing that method.
var client interface {
NewSession() (*ssh.Session, error)
}
if some_condn {
client = ssh.Dial(params)
} else {
client = my_own_ssh_dial(my_params)
}
session, _ := client.NewSession()
I'm pretty new to Go, but I'll take a stab. If it's wrong, cool. Unfortunately, I don't have enough code from you to actually try and do this - but essentially, you'll need to make your own type my_own_ssh, and then add a Dial function to it. Then, you'll define an
interface Client {
Dial()
}
And then you can define your client variable with var client Client before the conditional check. You'll also need to create a function Dial that has a my_own_ssh receiver in order for the interface to work/make sense.
I'm very happy to receive feedback on this answer, because like I said - I'm pretty new to it :)

Cast boxed struct to boxed pointer - golang

I'm using Protobuf for Golang.
Protobuf generates message types where type pointer implements proto.Message().
e.g.
func (*SomeMessage) Message() {}
The protobuf lib have methods like Marshal(proto.Message)
Now to my actual issue.
message := SomeMessage {}
SendMessage(&message)
func SendMessage(message interface{}) {
switch msg := message.(type) {
case proto.Message:
//send across the wire or whatever
default:
//non proto message, panic or whatever
}
}
The above works fine.
However, If I don't pass the message as a pointer, then the code in SendMessage will not match, as the interface is only implemented on the SomeMessage pointer, not on the value.
What I would like to do is:
message := SomeMessage {}
SendMessage(message) //pass by value
//there are more stuff going on in my real code, but just trying to show the relevant parts
func SendMessage(message interface{}) {
//match both pointer and value as proto.Message
//and then turn the value into a pointer so that
//other funcs or protobuf can consume it
message = MagicallyTurnBoxedValueIntoBoxedStruct(message)
switch msg := message.(type) {
case proto.Message:
//send across the wire or whatever
default:
//non proto message, panic or whatever
}
}
preferably I'd like to be able to pass both as pointer and as value.
The reason why I want to pass by value, is that this can act as a poor mans isolation when passing messages across goroutines/threads etc.
(in lack of immutability)
All of this could probably be avoided if the protobuf generator generated allowed values to be treated as proto.Message() too.
Or if there was some nicer way to do immutable messages.
It's not super important,if its possible, cool, if its not, meh :-)
[EDIT]
If I have the reflect.Type of the message and the reflect.Type of the pointer type of the message.
Is it somehow possible to create an instance of the pointer type pointing to the value using "reflect" ?
Normally, you can't take the address of a value which means you can't simply convert the interface{} to a pointer to satisfy Protobuf's requirement.
That said, you can dynamically create a new pointer then copy the value in to that then pass the newly allocated pointer to protobuf.
Here's an example on Play
The value -> pointer conversion is:
func mkPointer(i interface{}) interface{} {
val := reflect.ValueOf(i)
if val.Kind() == reflect.Ptr {
return i
}
if val.CanAddr() {
return val.Addr().Interface()
}
nv := reflect.New(reflect.TypeOf(i))
nv.Elem().Set(val)
return nv.Interface()
}
We first see if it's a pointer, if so, just return the value.
Then we check to see if it's addressable and return that.
Lastly, we make a new instance of the type and copy the contents to that and return it.
Since this this copies the data, it may not be practical for your purposes. It will all depend on size of message and expected rate of calling with a value (as that will generate more garbage).

Go heap.Interface as a struct

I'm creating a priority queue using Go's heap package. There is an example of one in the documentation.
The queue I'm creating needs to be based around a struct rather than a slice because it requires other properties like a mutex.
type PQueue struct {
queue []*Item
sync.Mutex
}
I implement all the methods that heap.Interface requires.
The issue is that my PQueue.Push method seems not to be permanently adding a value to PQueue.queue.
func (p PQueue) Push(x interface{}) {
p.Lock()
defer p.Unlock()
item := x.(*Item)
item.place = len(p.queue) // the index of an item in the queue
p.queue = append(p.queue, item)
// len(p.queue) does increase
// after the functions exits, the queues length has not increased
}
If I print the length of p.queue at the end of this function, the length has increased. After the functions exits however, it seems the original struct does not get updated.
I think it might be happening because of func (p PQueue) not being a pointer. Why might that be? Is there a way to fix it? If I were to use func (p *PQeueue) Push(x interface{}) instead, I would need to implement my own heap because heap.Interface specifically requires no pointer. Is that my only option?
The problem is that you are appending to a copy of your slice. Thus the change shows within the function, but is lost once you return from the function.
In this blog article from the section Passing slices to functions:
It's important to understand that even though a slice contains a
pointer, it is itself a value. Under the covers, it is a struct value
holding a pointer and a length. It is not a pointer to a struct.
With append you are modifying the slice header. And
Thus if we want to write a function that modifies the header, we must
return it as a result parameter
Or:
Another way to have a function modify the slice header is to pass a
pointer to it.
As a result you need to pass a pointer if you want to modify it with append. Simply change the method to use a pointer receiver. And for that to work you need to call init with a pointer like heap.Init(&pq) as shown in the example that you linked to which does just that and also uses pointer receivers.
From the spec on Method Sets:
The method set of the corresponding pointer type *T is the set of all methods
declared with receiver *T or T (that is, it also contains the method
set of T).
So using a pointer type will work with value and pointer receivers and still implement the interface.
You are right about the problem being related to the receiver of your Push method: the method will receive a copy of the PQueue, so any changes made to the struct will not persist.
Changing the method to use a pointer as a receiver is the correct change, but this also means that PQueue no longer implements heap.Interface. This is due to the fact that Go does not let you take a pointer to the value stored inside an interface variable, so the automatic translation of q.Push() to (&q).Push() does not occur.
This isn't a dead end though, since *PQueue should still implement the heap.Interface. So if you were previously calling heap.Init(q), just change it to heap.Init(&q).
I think it might be happening because of func (p PQueue) not being a pointer
That's right. Quoting Effective Go:
invoking [the method] on a value would cause the method to receive a
copy of the value, so any modifications would be discarded.
You say:
heap.Interface specifically requires no pointer
I'm confused, the example you point to is, in fact, using a pointer:
func (pq *PriorityQueue) Push(x interface{}) {
n := len(*pq)
item := x.(*Item)
item.index = n
*pq = append(*pq, item)
}
Maybe something else is going on?

Pointer to an interface in Go

I'm currently reading the source code of the https://github.com/codegangsta/inject go package to understand how does this package works.
I have some questions concerning the file https://github.com/codegangsta/inject/blob/master/inject.go file thats use some element of the Go language I don't understand and don't find precise explanations in the documentation.
// InterfaceOf dereferences a pointer to an Interface type.
// It panics if value is not an pointer to an interface.
func InterfaceOf(value interface{}) reflect.Type {
t := reflect.TypeOf(value)
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
if t.Kind() != reflect.Interface {
panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)")
}
return t
}
My first question is concerning the for loop. Why does it uses a for loop with a test expression ?
The second relates to the message in the panic function. "A pointer to an interface" is mentioned with the (*MyInterface)(nil). I only encounter a similar construction in the go documentation concerning 'compile time checking structure' when you check that a type implements a structure :
var _ SomeType = (*SomeInterface)(nil)
I did not find any informations about a statement with (*Interface)(nil) and pointer to interface.
How should we interpret this statement ? What is the relation with a pointer to interface and where could I find informations about pointer to interface ?
To summarize both answers:
The for loop
for t.Kind() == reflect.Ptr {
t = t.Elem()
}
t.Elem() is the reflection equivalent to *t, so what this loop does it dereferencing t as long as it holds another pointer value. At the end of the loop, t will hold the value that the last pointer pointed to, not a pointer anymore.
The message
Called [...] with a value that is not a pointer to an interface. (*MyInterface)(nil)
The expression (*MyInterface)(nil) is just an (poorly phrased) example of what is expected as parameter.
The syntax is that of a conversion. A conversion will attempt to convert a value (in this case nil) to a given type (*MyInterface) in this case. So,
(*MyInterface)(nil)
will give you a zero value of a *MyInterface whose interface type would be MyInterface (play):
x := (*MyInterface)(nil)
InterfaceOf(x) // MyInterface
Of course, this value does not point somewhere meaningful.
Compile time checking of interface implementation
To avoid confusion, the construct you showed
var _ SomeType = (*SomeInterface)(nil)
is probably not what you wanted. I guess you wanted this:
var _ SomeInterface = (*SomeType)(nil)
This construct enables compile time checking of interface implementation for certain types.
So in case you're writing a library of some sort and you want to satisfy an interface without
using it, you can use this to make sure that your struct implements the interface.
Why this works
First of all, var _ someType is a variable that is going to be checked by the compiler but
will not be in the compiled program and is not accessible due to the Blank Identifier _:
The blank identifier may be used like any other identifier in a declaration, but it does not introduce a binding and thus is not declared.
This enables you do declare an arbitrary number of these constructs without interfering with the
rest of the program.
You can declare a zero value of a pointer of any type by writing:
(*T)(nil)
Check this example on play.
Next, assignability says that x is assignable to T if T is an interface and x implements T.
So to summarize:
T _ = (*x)(nil)
enforces that x implements T as everything else would be an error.
The for loop is used to continually dereference the type until it is no longer a pointer. This will handle case where the type acquired an extra indirection(s).
e.g. play.golang.org/p/vR2gKNJChE
As for the (*MyInterface)(nil), pointers to interfaces always1 an error Go code. I assume the author is just describing what he means by pointer to interface with a code snippet since they are so rare.
If you're still intrigued by the forbidden type Russ Cox has some info how exactly all this works under the hood: research.swtch.com/interfaces. You'll have a hard time finding info on the use of pointers to an interface because [1].
(1) OK not really always, but honestly don't do it unless you're a Go pro. In which case don't tell anyone about it.
That for loop is identical to while loop in other languages
The second thing is just a syntax for conversions:
(*Point)(p) // p is converted to *Point
Because how this library works you just have to pass the pointer to interface, for loop then dereferences it (if we pass something like (***MyInterface)(nil)) and then if statement checks if the ty[e pointed to is an interface.

Resources