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
Related
I want to define an ASN.1 structure with a numeric field. I use a custom type for that number, to make it clear what kind of value one deals with and let the compiler catch some type-related errors (e.g., attempts to use other numerical values that don't semantically fit into the field).
However, the serializer doesn't know how to deal with this field, because it is not a Go primitive type.
Here is a minimal example that illustrates the problem:
package main
import (
"encoding/asn1"
"fmt"
)
type MessageType uint
const (
Signal MessageType = 1
Payload = 2
Control = 3
)
type Packet struct {
Type MessageType
// more stuff here ...
}
func main() {
fmt.Println(Signal)
var packet Packet
packet.Type = Payload
fmt.Println(asn1.Marshal(packet))
}
When I run it, the error is [] asn1: structure error: unknown Go type: main.MessageType. It works if I use a plain integer instead of the custom MessageType, but in this case I don't get the benefit of using specific types.
What is the proper way of handling this scenario in Go? The documentation of the ASN1 module doesn't provide any examples that address this question.
golang encoding/asn1 is a low level library ... it is not an ASN.1 compiler
So it's normal you can only encode basic types
You will need to write more code before it calls encoding/asn1 library
You can do it manually if the problem you want to solve is very simple.
However, the normal process when you use ASN.1 is:
Write an ASN.1 specification
Use a tool to compile it and produce stubs in your preferred language
Write some code that will use these stubs
I think you won't find free tools to do that in Go
Looking at the source code c.Organizations = (*OrganizationsService)(&c.common) from https://github.com/google/go-github/blob/master/github/github.go#L283, in describing this bit of code with proper terminology, would you describe it as follows:
The Organizations field of variable c is set to the address of c.common casted to a pointer receiver value of OrganizationsService.
Or am I missing a bit of nuance when describing this?
Below are some relevant bits of source code that show where the variables are being defined.
// A Client manages communication with the GitHub API.
type Client struct {
clientMu sync.Mutex // clientMu protects the client during calls that modify the CheckRedirect func.
client *http.Client // HTTP client used to communicate with the API.
// Base URL for API requests. Defaults to the public GitHub API, but can be
// set to a domain endpoint to use with GitHub Enterprise. BaseURL should
// always be specified with a trailing slash.
BaseURL *url.URL
// Base URL for uploading files.
UploadURL *url.URL
// User agent used when communicating with the GitHub API.
UserAgent string
rateMu sync.Mutex
rateLimits [categories]Rate // Rate limits for the client as determined by the most recent API calls.
common service // Reuse a single struct instead of allocating one for each service on the heap.
// Services used for talking to different parts of the GitHub API.
Actions *ActionsService
Activity *ActivityService
Admin *AdminService
Apps *AppsService
Authorizations *AuthorizationsService
Checks *ChecksService
CodeScanning *CodeScanningService
Enterprise *EnterpriseService
Gists *GistsService
Git *GitService
Gitignores *GitignoresService
Interactions *InteractionsService
IssueImport *IssueImportService
Issues *IssuesService
Licenses *LicensesService
Marketplace *MarketplaceService
Migrations *MigrationService
Organizations *OrganizationsService
Projects *ProjectsService
PullRequests *PullRequestsService
Reactions *ReactionsService
Repositories *RepositoriesService
Search *SearchService
Teams *TeamsService
Users *UsersService
}
type service struct {
client *Client
}
The Organizations field of variable c is set to the address of c.common casted to a pointer receiver value of OrganizationsService.
This is close, but I'd make a few changes.
First:
casted
The operation being done here, according to official Go terminology, is a "conversion" not a cast.
Second:
c is set to the address of c.common...
While & is the "addressing" operator, the value that it results in is a pointer value. The literal contents of that value is the address. It's not incorrect to refer to addresses, but while analyzing syntax and structure, we would probably rather refer to values at the high level, rather than the contents of them.
Third:
pointer receiver value of...
The word "receiver" in Go refers to the receiver value in method call or method declaration, e.g.
func (v *Value) Method() {
}
Here v is the receiver, and it's type does happen to be a pointer type, but it doesn't have to be.
func (v Value) Method() {
}
This is also valid (though may have different and unintended effects compared to the first version). Regardless, the value in your question is not a receiver in any sense.
With the adjustments:
The Organizations field of variable c is set to the pointer to c.common converted to a pointer value to the OrganizationsService type.
Even still, we could restructure the sentence a bit so it is more similar to the order of operations as they happen in the program. It may seem natural to analyze things from left to right, but this is rarely the most comprehensible expression of code.
Here's an explanation that is, in my opinion, more natural.
The pointer to c's "common" field is converted to a pointer to OrganizationsService, and then assigned to c's "Organizations" field.
I'm working on a custom controller for a custom resource using kubebuilder (version 1.0.8). I have a scenario where I need to get a list of all the instances of my custom resource so I can sync up with an external database.
All the examples I've seen for kubernetes controllers use either client-go or just call the api server directly over http. However, kubebuilder has also given me this client.Client object to get and list resources. So I'm trying to use that.
After creating a client instance by using the passed in Manager instance (i.e. do mgr.GetClient()), I then tried to write some code to get the list of all the Environment resources I created.
func syncClusterWithDatabase(c client.Client, db *dynamodb.DynamoDB) {
// Sync environments
// Step 1 - read all the environments the cluster knows about
clusterEnvironments := &cdsv1alpha1.EnvironmentList{}
c.List(context.Background(), /* what do I put here? */, clusterEnvironments)
}
The example in the documentation for the List method shows:
c.List(context.Background, &result);
which doesn't even compile.
I saw a few method in the client package to limit the search to particular labels, or for a specific field with a specific value, but nothing to limit the result to a specific resource kind.
Is there a way to do this via the Client object? Should I do something else entirely?
So figured it out - the answer is to pass nil for the second parameter. The type of the output pointer determines which sort of resource it actually retrieves.
According to the latest documentation, the List method is defined as follows,
List(ctx context.Context, list ObjectList, opts ...ListOption) error
If the List method you are calling has the same definition as above, your code should compile. As it has variadic options to set the namespace and field match, the mandatory arguments are Context and objectList.
Ref: KubeBuilder Book
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.
I am trying to manually create an instance of the type ReactionAddedEvent given here, in nlopes' Go Slack library. However, the sub-type reactionItem is unexported, which leads me to receive the error ./bot_test.go:111: cannot refer to unexported name slack.reactionItem when trying to instantiate the object.
Here is my code:
m := &slack.ReactionAddedEvent{
Item: &slack.reactionItem{
File: &slack.File{
Preview: "Test",
URLPrivate: "http://google.com",
},
},
Reaction: "white_check_mark",
}
When I remove the identifier &slack.reactionItem from line 2 in that snippet, I get instead the error: ./bot_test.go:112: missing type in composite literal, obviously.
Is there any way for me to instantiate an object of this type with the parameters I need?
First, if slack here refers to the nlopes library, the slack.ReactionAddedEvent structure's Item field is not a pointer, so you can't store an address of a slack.reactionItem struct into that field anyway. Second, the File field of slack.reactionItem is a string, not a structure.
Third, even if the above isn't/weren't the case, if the types are not exported, but the fields themselves are, you can't assemble the structure in a single literal. Instead, you'll have to manually set those fields after creating the structure variable:
m := &slack.ReactionAddedEvent{Reaction: "white_check_mark"}
m.Item.File.Preview = "Test"
m.Item.File.URLPrivate = "http://google.com"
But again, if you're using the nlopes library, that won't work because the File field isn't actually a structure:
https://github.com/nlopes/slack/blob/master/websocket_reactions.go
And fourth, if the type isn't exported, that's probably a good sign that you shouldn't be manipulating objects of that type. In this case, in the nlopes library, those structures are only intended to be used for unmarshalling and then handling events from JSON messages.