Declare a variable without datatype - go

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 :)

Related

Go test function with pointer reference

I'm working on unit tests on a Go project, and I'm new to Go. So to start I wanted to test something easy. And I started with this function:
func (this *Service) InList(idPerson string, personsId []string) bool {
for _, personsId := range personsId {
if id == idPerson {
return true
}
}
return false
}
Service is a struct defined on top of the class.
This is the test I wrote:
func TestValidatePersonID(t *testing.T) {
personID := "12345"
personIDs := []string{"12345", "123456t", "1234567a"}
ok := *Service.InList(personID, personIDs)
if !ok {
t.Errorf("Id %v not found", personID)
}
}
If i try to Call Service without * I get the error:
invalid method expresion (needs pointer reciever)
If i try to call the function (*Service).inList, it says I'm missing an argument. I'm new to Go if anyone could point to me what I'm doing wrong and how Could I get a pointer receiver of that Service in my test?. I would appreciatte it.
The correct syntax for the method expression is:
ok := (*Service).InList(nil, personID, personIDs)
This snippet adds nil as the receiver argument and uses parentheses to specify the type correctly.
The approached used in the question is not idiomatic. Either call a method on a value
s := Service{}
ok := s.InList(personID, personIDs)
or convert the method to a function.
You have to call a method on an instance of its receiver type. So, for a method defined on *Service, you must call it on an instance of *Service:
var foo *Service
foo = &Service{}
foo.InList(personID, personIDs)
However, in your case, there's no reason for this to be a method; it doesn't seem to have anything at all to do with its receiver (it never references it), so it could just be a regular function. Also note that it's unidiomatic to name the receiver this in Go.
I also highly recommend at least taking the Go tour, which covers writing methods in detail, with interactive examples.
If you do not reference the receiver object, then you should not have one, keep your code as simple as possible.
There are three ways of writing a method or function, with each its own purpose.
without receiver, when no receiver is referenced in the function ( we call this a function )
a value receiver, the receiver is referenced, but not changed in the method ( we call this a method )
a pointer receiver, something in the receiver will be changed in the method

How do you use Thrift's TMemoryBuffer in Golang?

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.

Best way to get array-like behavior of different but similar types in Go?

Scenario:
I have a few different clients, each interacting with a different API.
The data fields of these clients are the same:
type clientX struct {
key string
secret string
client *http.Client
}
However these clients each have many methods (all different from each other):
func (c *ClientX) someMethod() (*ResponseType, error) {
//code
}
The amount of clients may change over time, as support for new APIs is added, or some number of APIs go offline. Therefore, all functions in the main package need to be modular and adaptable to accept a variable number of clients as arguments.
What is the best way to go about this problem?
I can't put the clients in an array because they are different types.
Ideas I'm toying around with:
The first solution that comes to mind is an array of type interface{}. However I'm concerned of the performance of an []interface{} as well as the code-bloat I'll have from identifying client types when iterating through the array (type-assertions).
I'm not as educated on inheritance as I'd like to be, so I'm not sure if this works. I'm envisioning creating a parent class Client containing the key, secret, and client data fields. The specific clients will be subclasses inheriting from the parent class Client, and then defining all the methods specific to that client. From my basic understanding, I could then put all of these clients into an array by defining the array type as Client. This leaves me a bit confused on how the elements in the array would behave as the would not be of type ClientX but of the more general type Client. Would this lead to having to type assert all over again aka the same problem as in solution 1? If Im going to have to ID and assert the type anyway are there any performance benefits to having an array of type Client over an array of type interface?
Have the clients (clientA, clientB, clientC) be global variables. Any function can access them so I won't have to pass them as arguments. In order to handle variable clients (the number is decided at runtime) I would have a clientsEnabled map[string]bool for functions to identify which clients to use and which to ignore. This seems like it would have minimal code-bloat. However, I'm wary of using globals, and was always taught to avoid unless absolutely necessary.
Another solution that the SO community has
Would love to have some feedback, thank you.
First of, there is no inheritance in golang. Also, I'd highly recommend reading about interfaces in golang.
As for this problem specifically, instead of storing interface{} instances, I'd introduce a command interface and implement it for each API with which the application would have to work. Something like this: https://play.golang.org/p/t5Kldpbu-P.
Since you mentioned that there is no common behaviour amongst the client commands, I wouldn't introduce interfaces for their methods unless there are inter-dependencies amongst them. Interfaces in that case would make them easy to unit test (create a mock that implements the interface).
This is simple and easy to extend.
From the information given, it sounds like you should define an interface type that encapsulates what the various client types have in common. That would be the way to actually achieve what you talk about in #2. Remember that Go does not have the concept of classes and subclasses, so if you have a type ClientX and then embed that in other types (the closest thing Go has to subclassing), those other types cannot be used where a type ClientX is expected. The only way to have one type that can represent several different underlying types is by defining an interface.
In addition to the common fields in the ClientX struct, I assume you will have to have some sort of client-specific handler function. That function would then do whatever client-specific operations are necessary. (It's hard to be more specific without knowing more details about what you're doing.)
Here's a simple example:
package main
import (
"fmt"
"net/http"
)
type client interface {
getKey() string
getSecret() string
getHttpClient() *http.Client
handler()
}
type clientX struct {
key string
secret string
client *http.Client
}
func (c *clientX) getKey() string {
return c.key
}
func (c *clientX) getSecret() string {
return c.secret
}
func (c *clientX) getHttpClient() *http.Client {
return c.client
}
type clientOne struct {
clientX
data1 string
data2 int
// ...
}
func (c *clientOne) handler() {
fmt.Printf("clientOne handler: data1: %q\n", c.data1)
}
func main() {
c1 := &clientOne{
clientX: clientX{
key: "abc",
secret: "def",
},
data1: "some data",
}
var clients []client
clients = append(clients, c1)
for _, c := range clients {
fmt.Printf("key %q secret %q\n", c.getKey(), c.getSecret())
c.handler()
}
}

Store a collection of constructors for types that all conform to the same interface

I'm making an app that'll need sets of rules to run a job. The app offers the possibility to express the rules in one of several different languages. I therefore have defined an interface to a live rules engine, that offers the methods that the app will need to query the current set of rules. Behind this interface, there will be one different type of engine, according to the source language.
Now I'd like to instantiate a rules engine according to the rule file's extension. But I get some errors which I have a hard time to overcome.
Let me first offer this simplified skeleton :
package main
//
//
// The interface
type RulesEngine interface {
SomeRuleEvaluator(string) bool
}
//
//
// An implementation, with its constructor
type ASimpleRulesEngine struct {
// I've also tried with :
// RulesEngine
}
func NewASimpleRulesEngine(context string) *ASimpleRulesEngine {
re := ASimpleRulesEngine{}
return &re
}
func (re *ASimpleRulesEngine) SomeRuleEvaluator(dummy string) bool {
return true
}
//
//
// A client, that'll want to be able to choose a constructor
var rulesEngineConstructorsPerExtension map[string](func(string) RulesEngine)
func init() {
rulesEngineConstructorsPerExtension = make(map[string](func(string)RulesEngine))
rulesEngineConstructorsPerExtension[".ini"] = NewASimpleRulesEngine
}
func main() {
}
When I try to build this, I get 35: cannot use NewASimpleRulesEngine (type func(string) *ASimpleRulesEngine) as type func(string) RulesEngine in assignment
I've also tried :
assigning without a pointer, although I felt stupid while trying it
having an intermediate step in the initfunction, where I'd create a new(func (string) RulesEngine) and then assign to it, with and without pointer.
storing function pointers like in C, but the compiler said it could not take the adress of my function.
I'm not that familiar with Go and this felt a bit surprising. What would be the proper type signature to use ? Is this possible at all ? If it's unavoidable, I'll obviously have a simple array of extensions on one side (to check if a file is potentially a rules file), and a big switch on the other side to provide the adequate constructor, but as much possible I'd like to avoid such duplication.
Thank you for any insight !
(edited : I've accepted my own answer for lack of any other, but its most relevant part is #seh 's comment below)
Following #JorgeMarey 's comment, and not wanting to sacrifice the constructor's type signature, I came up with this. But it does feel very tacky to me. I'll be glad to hear about a cleaner way.
func init() {
rulesEngineConstructorsPerExtension = make(map[string](func(string)RulesEngine))
cast_NewASimpleRulesEngine := func(content string) RulesEngine {
return NewASimpleRulesEngine(content)
}
rulesEngineConstructorsPerExtension[".ini"] = cast_NewASimpleRulesEngine
}
(an attempt to explicitly cast with (func(string)RulesEngine)( NewASimpleRulesEngine) was deemed unfit by the compiler too)

How do I extract a string from an interface{} variable in Go?

I'm new to the Go language.
I'm making a small web application with Go, the Gorilla toolkit, and the Mustache template engine.
Everything works great so far.
I use hoisie/mustache and gorilla/sessions, but I'm struggling with passing variables from one to the other. I have a map[string]interface{} that I pass to the template engine. When a user is logged in, I want to take the user's session data and merge it with my map[string]interface{} so that the data becomes available for rendering.
The problem is that gorilla/sessions returns a map[interface{}]interface{} so the merge cannot be done (with the skills I have in this language).
I thought about extracting the string inside the interface{} variable (reflection?).
I also thought about making my session data a map[interface{}]interface{} just like what gorilla/sessions provides. But I'm new to Go and I don't know if that can be considered best practice. As a Java guy, I feel like working with variables of type Object.
I would like to know the best approach for this problem in your opinion.
Thanks in advance.
You'll need to perform type assertions: specifically this section of Effective Go.
str, ok := value.(string)
if ok {
fmt.Printf("string value is: %q\n", str)
} else {
fmt.Printf("value is not a string\n")
}
A more precise example given what you're trying to do:
if userID, ok := session.Values["userID"].(string); ok {
// User ID is set
} else {
// User ID is not set/wrong type; raise an error/HTTP 500/re-direct
}
type M map[string]interface{}
err := t.ExecuteTemplate(w, "user_form.tmpl", M{"current_user": userID})
if err != nil {
// handle it
}
What you're doing is ensuring that the userID you pull out of the interface{} container is actually a string. If it's not, you handle it (if you don't, you'll program will panic as per the docs).
If it is, you pass it to your template where you can access it as {{ .current_user }}. M is a quick shortcut that I use to avoid having to type out map[string]interface{} every time I call my template rendering function.

Resources