Extract string value of Id from mgo GridFile - go

Being quite new to Go, I am having a hard time using mgo.
I am using mgo to fetch files like this :
gridfs := db.GridFS("fs")
allFiles := gridfs.Find(nil).Iter()
And then I use the returned iterator like
var f *mgo.GridFile
for gridfs.OpenNext(allFiles, &f) {
//use f.Id()
}
I want to start using f.Id() as a String but I am unable to convert. One of the ways I found was by using fileId := (f.Id().(bson.ObjectId)).Hex() which just lets me compile but fails at runtime with the message interface conversion: interface {} is bson.ObjectId, not bson.ObjectId
Having spent a lot of time on this already, I am definitely open to changing the way I fetch the files if conversion is not possible using GridFile.
I would appreciate any help with this. Thanks.

Correct answer by #icza. I had 2 versions of mgo.

Related

Reading CloudWatch log query status in go SDK v2

I'm running a CloudWatch log query through the v2 SDK for Go. I've successfully submitted the query using the StartQuery method, however I can't seem to process the results.
I've got my query ID in a variable (queryID) and am using the GetQueryResults method as follows:
results, err := svc.GetQueryResults(context.TODO(), &cloudwatchlogs.GetQueryResultsInput{QueryId: queryId,})
How do I actually read the contents? Specifically, I'm looking at the Status field. If I run the query at the command line, this comes back as a string description. According to the SDK docs, this is a bespoke type "QueryStatus", which is defined as a string with enumerated constants.
I've tried comparing to the constant names, e.g.
if results.Status == cloudwatchlogs.GetQueryResultsOutput.QueryStatus.QueryStatusComplete
but the compiler doesn't accept this. How do I either reference the constants or get to the string value itself?
The QueryStatus type is defined in the separate types package. The Go SDK services are all organised this way.
import "github.com/aws/aws-sdk-go-v2/service/cloudwatchlogs/types"
if res.Status == types.QueryStatusComplete {
fmt.Println("complete!")
}

Way to convert *grpcpool.ClientConn to *grpc.ClientConn

I am working in golang for the first time and am trying to convert a variable of type *grpcpool.ClientConn to *grpc.ClientConn.
I would like to pass the variable to a function that only takes *grpc.ClientConn. I am using a grpc client stub which requires the *grpc.ClientConn type and I am using processout/grpc-go-pool for the grpc pooling library. I looked at the possibility of making use of Factory in pool.go, but am pretty stuck since that is a type that returns a *grpc.ClientConn.
Does anyone have any suggestions as to how I might be able to make that conversion?
I mean the grpcpool.ClientConn struct is just:
https://godoc.org/github.com/processout/grpc-go-pool#ClientConn
type ClientConn struct {
*grpc.ClientConn
// contains filtered or unexported fields
}
So I'm fairly certain you can just do:
pool := &grpcPool.ClientConn{} // however you get one of these
SomeFunc(pool.ClientConn)
See https://play.golang.org/p/YEzy4Wq8WF9 as an example of getting the embedded struct

How can I use dynamic errors while retaining comparability for testing?

In go I often use
func MyFunc(s someInterface) error {
err := OtherFunc(s)
return fmt.Errorf("something wrong: %s", err)
}
So I lose the original error value, because I just take the error string and forge it into a new error. That is what I mean with dynamic errors.
Now consider a test for MyFunc():
func TestMyFunc(t *testing.T) {
s := mockSomeInterface()
testErr := MyFunc(s)
if testErr != interfaceSpecificErrorValue {
t.Errorf("fail")
}
}
What would I use for interfaceSpecificErrorValue (which is specific to someInterface in this example)? Or how could I make this testable?
I understand that I can solve this by defining all my possible errors beforehand and give them a constant value. What I am interested in is if there is another way to achieve this, because I like the hierarchical error messages that you can dynamically build up using fmt.Errorf("...: %s, err). There must be a good way to keep the error hierarchy without losing the original value.
(Comparing the output of the Error() method is a possibility, but not a good one.)
My preliminary answer to this is: In Go currently there is no canonical way to achieve nested errors with comparable error values.
After reading the offical documents and blog posts on error handling again, quite some source code from standard libraries, and finally this proposal: https://github.com/golang/proposal/blob/master/design/go2draft-error-values-overview.md, I decided I will keep my error types simple and static and wait for Go 2 to offer a better way.

Golang client to perform operations on cdt list in aerospike

I wanted to use a list as a bin value in aerospike. So, http://www.aerospike.com/docs/guide/cdt-list.html seems like a good option. But the client examples in golang https://github.com/aerospike/aerospike-client-go/blob/master/examples/list_map.go only shows a get and a put.
key, _ := as.NewKey(*shared.Namespace, *shared.Set, "listkey1")
client.Delete(shared.WritePolicy, key)
list := []string{"string1", "string2", "string3"}
bin := as.NewBin("listbin1", list)
client.PutBins(shared.WritePolicy, key, bin)
record, err := client.Get(shared.Policy, key, bin.Name)
shared.PanicOnError(err)
receivedList := record.Bins[bin.Name].([]interface{})
validateSize(3, len(receivedList))
validate("string1", receivedList[0])
validate("string2", receivedList[1])
validate("string3", receivedList[2])
What about all other APIs mentioned ? Such as how do I append to the list or get count of objects in the list etc. ? Any reference to any documentation would be appreciated.
Thanks in advance.
Don't expect examples to provide full documentation. Use the documentation for that.
Thanks to Flimzy for pointing the documentation. Maybe for future users who come accross this question, the following might help.
To perform a list operation, you need to use the following method and specify the operation:
https://godoc.org/github.com/aerospike/aerospike-client-go#Client.Operate
The Operate method takes an operation and to get an operation the List*Op methods are used (such as https://godoc.org/github.com/aerospike/aerospike-client-go#ListAppendOp)

Golang: Passing channels through empty interfaces

I'm trying to do something that seems like it should be trivial until I read up and now it seems like it should be really complex. ;-)
I've knocked up a test pattern to illustrate:
http://play.golang.org/p/Re88vJZvPT
At the most basic I'm trying to have a function that can read data from a channel and spit it out on another one. Easy. The test does this as long as you use the pusher function shown.
However the problem with this is that doing it this way I would need a different pusher function for each type of data I want to push through it.
Now I've done similar things in the past with an empty interface as nothing in the pusher code cares about what's in the data structure. What I can't figure out is when I'm dealing with channels of an un-cared-about data structure.
To illustrate the concept of what I'm trying to achieve please see the function pusher_naive_generic.
However that doesn't work either so more reading up implied the way to do it was making use of reflection and finally you see my pusher_reflect_generic function(obviously this won't achieve the same intended function as the others it's showing where I got to before getting stuck).
Which still fails because I can't get from an interface that contains a chan to the structure read from that chan.
Hopefully the code makes more sense of what I'm trying to achieve than my words actually do. I can make all of this work by explicitly coding for every type, but what I can't figure out how to do is code it for any future type.
If I have understood your question correctly, then this might be the solution:
http://play.golang.org/p/xiDO7xkoW4
func forwardChannel(i interface{}, o interface{}) {
it, ot := reflect.TypeOf(i), reflect.TypeOf(o)
if it != ot {
panic("forwardChannel: both arguments must be of the same type")
}
iv, ov := reflect.ValueOf(i), reflect.ValueOf(o)
for {
v, k := iv.Recv()
if !k {
break
}
ov.Send(v)
}
ov.Close()
}
Note that Recv, Send and Close panic if i and o are not channels.

Resources