Go package selector based on condition - go

We have 2 packages that implement the same function signatures. In my main I need to switch out the package being used based on a condition:
import (
packageA "deployment/sdk/packageA"
packageB "deployment/sdk/packageB"
)
someCondition := true
var packageToUse ?
if someCondition {
packageToUse = packageA
} else {
packageToUse = packageB
}
packageToUse.DoSomething()
Of course, this doesn't compile. I don't know what type to use for packageToUse. This approach is probably an anti-pattern. I'm just not sure the approach I should be taking.
any suggestions?
The error I get is use of package without selector

It is very much a pattern - aside from the dynamic import. It is called „Interfaces“.
Given an interface definition like
type Stringer interface{
String() string
}
and the type Foo implementing said interface
type foo int
func(f foo)String() string{
return fmt.Sprintf(”%d”,f)
}
as well as Bar implementing said interface
type bar string
func (b bar) String()string {
return string(b)
}
one can actually use both as a parameter for a function baz
func baz(s Stringer){
fmt.Println(s.String())
}
Note that unlike other languages, you do not have to declare the interfaces a type implements - as long as a type happens to factually implement an interface, the go compiler is ok with it. Run on Playground
So, with regards to your question of package imports: Unless you have ginormous dependency trees to import, it really is not worth the hassle.
Say we talk of an application using either BBolt or etcd and for good measure some MongoDB. The resulting size to include all of them, while relatively speaking is quite astonishing, is negligible. I compiled a go program with imports of bbolt, bbolt & etcd and bbolt, etcd & mongodb. These are the results in bytes.
11734884 size_all
2455544 size_bolt
10307700 size_boltetcd
We are talking of a few megabytes in file size. So say you use either Bolt or etcd or MongoDB, do you really want to jump through all the hoops and loops required to get dynamic imports done properly? I for my part would neither want to do it nor would I want Go to provide such a feature.
"Premature optimization is the root of all evil (or at least most of it) in programming."
– Donald Knuth

This isn't quite what you asked, but this is how I would accomplish the goal if I were you:
// I assumed both package functions have the same signature, so you can use a type
// TODO: Actual function signature you want to use here
type myFn func() error
var fnToUse myFn
if someCondition {
fnToUse = packageA.Func1
} else {
fnToUse = packageB.Func2
}
fnToUse()

Following up a bit on comment about using an interface
I would step back a bit and see if this can be better solved using an
interface that you provide the concrete class for in the condition
statement.
package packageA
type Thing struct {
}
func (t Thing) DoSomething() {
}
--
package packageB
type Thing struct {
}
func (t Thing) DoSomething() {
}
--
package main
import (
"packageA"
"packageB"
)
type PackageUser interface {
DoSomething()
}
func main() {
var pu PackageUser
if (condition) {
pu := packageA.Thing{}
} else {
pu := packageB.Thing{}
}
pu.DoSomething()
}

Related

Factory method in golang suffers from cyclic dependency

I realize questions about cyclic dependencies have been answered before, however, the answers usually simply say to merge packages. So long story short, I have an interface which many types will implement. I want to have a way of choosing which one of these types is to be used during runtime using its name. This would also be used for serialization. I read in the name of the class and then instantiate the correct one.
I have used the strategy pattern. There is a Base interface in package A.
package A
import (
"../C"
)
type Base interface {
doStuff(p C.Profile) int
}
type Operation struct {
Base Base
Data int
}
func (o *Operation) execute(p C.Profile) int {
return o.Base.doStuff(p)
}
Then, there are types that implement that interface in package B.
//file Impl1.go
package B
import (
"../C"
)
type Impl1 struct {}
func (b *Impl1 ) doStuff(p C.Profile) int {
...
}
//file Impl2.go
package B
import (
"../C"
)
type Impl2 struct {}
func (b *Impl2 ) doStuff(p C.Profile) int {
...
}
Then in package C i have struct Foo with a field of type Base. This field can point to any of the implementations from package B. We can choose the implementation during runtime. This is the struct that I eventually want to serialize.
package C
import (
"../A"
"../B"
)
type Foo struct {
bar A.Base
baz []Profile
...
}
func (f *Foo) changeBar(name string, data int) {
switch name {
case "Impl1":
f.bar = Operation{Base: B.Impl1{}, Data: data}
case "Impl2":
f.bar = Operation{Base: B.Impl2{}, Data: data}
...
}
EDIT: Also in the C package, we have the Profile, which is the reason A and B packages need to import it.
This code has a cyclic dependency C -> B -> C. An obvious solution would be to move Profile to a different package. But this is not possible because Profile (and many other similar types in the C package) and Foo are very tightly coupled and belong in the same package (maybe not so apparent in this minimal working sample). This is what other answers to these type of questions suggest, but I want to learn how to make it work, using good practices i learned from using other languages.
Another solution would be to somehow move the factory method changeBar to another package and only use it on the outside of the C package (thus avoiding the cycle), passing it results to C as parameters, but there are cases (serialization in particular) where I actually need it on the inside of the C package.
I have put a lot of time into figuring out this issue but all I end up with is either have everything in one huge package or have every single file in a separate package and have everything be exported. In other programming languages, there is the possibility to either have these cyclic dependencies or import one "class" at a time from a package. What is the way to go in go?
You can break the dependency from C to B using a type registry:
package C
import "A"
var TypeRegistry = map[string]func() A.Base {}
func (f *Foo) changeBar(name string, data int) {
if factory, ok:=TypeRegistry[name]; ok {
f.bar=Operation{Base:factory(),Data:data}
}
}
Then register your implementations in any package:
package B
import "../C"
func init() {
C.TypeRegistry["myType"]=func() A.Base { return MyType{}}
}

Create equivalent interface of another package with an interface as argument

I am practicing writing idiomatic Go code and discovered that interfaces should be declared in packages which are consuming them since they're implicit. However I came to this situation where by in the second package (package b) I want a function to call the receiver function of a struct in package a without coupling it tightly.
So naturally, I declare an interface in package b with the signature of the function I want to call from package a. The problem is that this function accepts an argument of a certain type which is an interface declared in package a. As I don't want package b to import package a, I defined an interface in package b with the exact same signature as the one which exists in package a. The playground link below shows the example code.
Playground
package main
import (
"fmt"
"log"
)
func main() {
manager := &Manager{}
coach := NewRunnerCoach(manager)
fmt.Println("Done")
}
// package a
type Runner interface {
Run()
}
type Manager struct {
}
func (o *Manager) RegisterRunner(runner Runner) {
log.Print("RegisterRunner")
}
func (o *Manager) Start() {
log.Print("Start")
}
// package b
type RunnerCoach struct {
runner *FastRunner
}
func NewRunnerCoach(registerer runnerRegisterer) *RunnerCoach {
runnerCoach := &RunnerCoach{&FastRunner{}}
registerer.RegisterRunner(runnerCoach.runner)
return runnerCoach
}
type FastRunner struct {
}
func (r *FastRunner) Run() {
log.Print("FastRunner Run")
}
// define ther registerer interface coach is accepting
type runnerRegisterer interface {
RegisterRunner(runner RunnerB)
}
// declaring a new interface with the same signature because we dont want to import package a
// and import Runner interface
type RunnerB interface {
Run()
}
This code does not compile. So the question here is that, am I using interface wrongly or should concrete types be defined in a separate package or lastly, is there a better code pattern for the problem I'm trying to solve?
EDIT: To clarify, package a and b does not import each other. The main() code exists in a separate package which connects these two.
IIUC, your question is not about packages but boils down to whether a function (or method)
can be typecast to another function which takes arguments with equivalent, but
not the same interface types.
Something like this: (Go Playground)
package main
type I1 interface{}
func f1(x I1) {}
func main() {
f := (func(interface{}))(f1)
f(nil)
}
Compilation error: ./g.go:8:26: cannot convert f1 (type func(I1)) to type func(interface {})
The answer appears to be no, because Go doesn't consider func (I1) to be
equivalent to func (interface{}). The Go spec says this
A function type denotes the set of all functions with the same parameter and result types.
The types func (I1) and func (interface{}) do not take the same parameters, even though
I1 is defined as interface{}. Your code fails to compile for a similar
reason because func (runner RunnerB) is not the same as func (runner Runner) and hence the method set of *Manager is not a superset of the
interface runnerRegisterer.
Coming to your original question:
I am practicing writing idiomatic Go code and discovered that interfaces
should be declared in packages which are consuming them since they're
implicit.
Yes, the idea is good but it doesn't apply to your implementation the way you
think it does. Since you're expecting to have different implementations of
runnerRegisterer and they must all have a method with the same signature
using the Runner interface, it makes sense to define Runner in a common
place. Also, as seen above Go wouldn't allow you to use a different interface
in the method signatures anyway.
Based on my understanding of what you're trying to achieve, here's how I think
you should re-arrange your code:
Define RunnerRegisterer (note: this is public) and Runner in one
package.
Implement your RunnerCoach in the same package and use the above
interfaces. Your RunnerCoach consumes types that implement the interfaces,
so it defines them.
Implement your runners in another package. You don't define the Runner
interface here.
Implement your Manager in another package, which uses the interface
Runner defined in RunnerCoach's package because it must take that type
as an argument if it wants to be used as a RunnerRegisterer.
The Solution
You've got a type that is used in two packages, A and B. Package A imports package B.
You have to avoid circular dependencies, so you have three choices:
Define the type in package B, so it will be available in both
packages.
Define the type in package C and have both A and B import package C.
Change your design such that the type is not used in both A and B.
These are your choices whether that type is an interface or any other type.
Choose the option that best fits your design goals.
The Rule / Idiom
I am practicing writing idiomatic Go code and discovered that
interfaces should be declared in packages which are consuming them
since they're implicit.
I get the impulse/idea - the problem is it's not very practical. Interfaces would be less useful if they could only be consumed in the package in which they are defined. The standard library is full of code that violates this axiom. Therefore I do not think the rule as presented -- applying to all interfaces in all situations, designs and contexts -- is idiomatic.
For example, look at the bytes package. func (b *Buffer) ReadFrom(r io.Reader) (n int64, err error) consumes io.Reader, an interface defined in another package. func (r *Reader) WriteTo(w io.Writer) (n int64, err error) consumes io.Writer, an interface defined in another package.

How to cast interface{} back into its original struct?

I need a way to dynamically cast a struct/interface back to its original object.
I can add methods / functions inside. basically I need something like this:
MyStruct => Interface{} => MyStruct
When on the final conversion I don't know anything about the original struct besides what come inside the struct, so I can't just so:
a.(MyStruct)
You need to know at least the possible types it could be. There's a couple cases, 1. You think you might know what it is. 2. You have a list of possible types it could be, 3. Your code knows nothing about the underlying types.
If you think you know it, you can use type assertion to convert back to the original struct type.
...
package main
import (
"fmt"
)
type MyStruct struct {
Thing string
}
func (s *MyStruct) Display() {
fmt.Println(s.Thing)
}
type Thingable interface {
Display()
}
func main() {
s := &MyStruct{
Thing: "Hello",
}
// print as MyThing
s.Display()
var thinger Thingable
thinger = s
// print as thingable interface
thinger.Display()
// convert thinger back to MyStruct
s2 := thinger.(*MyStruct) // this is "type assertion", you're asserting that thinger is a pointer to MyStruct. This will panic if thinger is not a *MyStruct
s2.Display()
}
You can see this in action here: https://play.golang.org/p/rL12Lrpqsyu
Note if you want to test the type without panicking if you're wrong, do s2, ok := thinger.(*MyStruct). ok will be true if it was successful and false otherwise.
if you want to test your interface variable against a bunch of types, use a switch: (scroll to bottom)
...
package main
import (
"fmt"
"reflect"
)
type MyStruct struct {
Thing string
}
type MyStruct2 struct {
Different string
}
func (s *MyStruct) Display() {
fmt.Println(s.Thing)
}
func (s *MyStruct2) Display() {
fmt.Println(s.Different)
}
type Thingable interface {
Display()
}
func main() {
s := &MyStruct{
Thing: "Hello",
}
// print as MyThing
s.Display()
var thinger Thingable
thinger = s
// print as thingable interface
thinger.Display()
// try to identify thinger
switch t := thinger.(type) {
case *MyStruct:
fmt.Println("thinger is a *MyStruct. Thing =", t.Thing)
case *MyStruct2:
fmt.Println("thinger is a *MyStruct2. Different =", t.Different)
default:
fmt.Println("thinger is an unknown type:", reflect.TypeOf(thinger))
}
}
You can try that out here https://play.golang.org/p/7NEbwB5j6Is
If you really don't know anything about the underlying types, you'll have to expose the things you need through interface functions and call those. Chances are you can do this without knowing anything about the underlying type. If all else fails, you can use the reflect package to introspect your interface object and gather information about it. this is how the json package reads json text and returns populated structs—though this is an advanced topic and expect to sink a lot of time into it if you go this route. it’s best to hide reflection code inside a package with a clean interface(ie the package api).
No: as mentioned in this thread
Go is neither covariant nor contravariant. Types are either equal or they aren't.
You have to either take the structs apart and deal with the pieces, or use reflection.
Type assertions are only "assertions", not "coercions" of any kind.
See also this thread, which reminds us that:
A pointer is one kind of type.
A struct is another kind of type.
An integer is another kind of type.
A floating point number is another kind of type.
A boolean is another kind of type.
The principle of an interface concerns the methods attached to a type T, not what type T is.
An interface type is defined by a set of methods.
Any value that implements the methods can be assigned to an interface value of that type.
That would make the conversion from interface to concrete type quite difficult to do.

go how to check if a function exists

Is there any way to check if a func exists in Go?
In PHP I might do something like
if(function_exists('someFunction')) {
//...
}
but I have not been able to figure out how to do this in Go
Any help on this will be greatly received.
A little more context on what you're trying to do would help.
As you note in your own comment, if you try to call a function Go checks at compile-time if the function exists, most of the times.
One exception that comes to my mind is when you use interface{} and you want to check that a method exists before calling it. For this you can use type checks.
Example:
package main
import "fmt"
// a simple Greeter struct
// with a Hello() method defined
type Greeter struct {
Name string
}
func (m *Greeter) Hello() string {
return "hello " + m.Name
}
var x interface{}
func main() {
x = Greeter {Name:"Paolo"} // x is a interface{}
g,ok := x.(Greeter) // we have to check that x is a Greeter...
if ok {
fmt.Println(g.Hello()) // ...before being able to call Hello()
}
}
Another scenario I can think of is that you're creating your own tool for Go that requires parsing go files before compiling them. If so, Go provides help in the for of the parser package
There's no way to do that (and for good!). The reason is that Go is a compiled language and does not support loadable modules (yet, at least) so functions can't come and go at runtime, and hence whether or not a top-level function exists, you know by defintion: if a given source file imports a package containing the function of interest1, that function is visible in this source file. Or this function is declared in the same package this source file belongs to and hence it's also available. In all the other cases the function is not available. Note that a function might be compiled in the program but still not visible in a given source file while compiling, so the whole definition of visibility as you put it does not exist in Go.
On the other hand you might want some generality. Generality in Go is achieved via interfaces. You might define an interface and then require a type to implement it. Checking that a type implements an interface is done via a neat trick.
An update from 2021-12-29.
The support for loadable modules was added in Go 1.8 in the form of the plugin package and has since then matured to support most mainline platforms except Windows.
Still, this solution is not without problems—for instance, see #20481.
1Without renaming that module to nothing, but let's not touch this for now.
Provided your thing is an interface value, type assert, something like this:
if Aer, ok := thing.(interface{MethodA()}); ok {
Aer.MethodA()
}
If thing is a struct, assign it to an interface variable first,
because type assertions only work on interface values.
It wouldn't hurt to define a named interface instead of using the
nonce one, but for simple cases like this it's not worth it.
Recently I had a need for figuring out if a struct has a particular function or not.
Here is another way using reflection :
package main
import (
"fmt"
"reflect"
)
type FuncRegistry struct {}
func (fr FuncRegistry) Hi() {
fmt.Println("function Hi")
}
func (fr FuncRegistry) Hello() {
fmt.Println("function Hello")
}
func functionExists(obj interface{},funcName string) bool {
mthd := reflect.ValueOf(obj).MethodByName(funcName)
if mthd.IsValid() {
fmt.Printf("Function '%s' exists \n",funcName)
return true
}
fmt.Printf("Function '%s' does not exist\n",funcName)
return false
}
// Main function
func main() {
var fr FuncRegistry
functionExists(fr,"Hi")
functionExists(fr,"Hello")
functionExists(fr,"Fail")
}
This sounds a lot like a XY problem. Please tell what you are trying to do. As far as I know, this is something you can't really do the same way as in PHP.
However, you could create a map with function names as keys. Add the functions there manually or generate the contents by parsing the source files before the compilation or at run time. Parsing the source seems like a dirty hack though.

Constants in Go established during init

In my Go program, there are configuration values that I want to be constant for the duration of program execution, but that I want to be able to change at the deployment site. As far as I can tell, there's no way to achieve this with the const keyword, since (again, as far as I can tell) its value must be a constant specified at compile time. This means that the only way to achieve what I want would be to declare normal variables and initialize them during the package's init function. It's not that that won't work, but rather that there will now be nothing to prevent these pseudo-constant's values from changing.
My two questions are:
Am I missing something about how const works?
Assuming I'm not, what's the preferred way to handle this? A public function that returns a private variable that I never expose, never changing it? Just hoping people don't alter the variables, since they're really configuration settings?
Create a file "config.go" and create the vars you want to expose.
Don't export them (make them all lower case). Instead create public (upper case) funcs that give access to each item.
package config
var x = 10
func X() int {
return x
}
When you want those variables you simply import ./config and use them in code as follows:
if config.X()
Obviously, you can set the variables in the package init.
The following code is almost the same as the second method of #Christopher, except that it is not a module, it located in the main package.
package main
import (
"os"
)
type Config struct {
debug bool
key string
proxyNumber int
}
func (c *Config) Debug() bool {
return c.debug
}
func (c *Config) Key() string {
return c.key
}
func (c *Config) ProxyNumber() int {
return c.proxyNumber
}
const (
CONFIG_NAME = "config.ini"
)
var config *Config
func init() {
DefaultConfig()
if Exists(CONFIG_NAME) {
//try to save the config file
}else {
//try to load from the config file
}
}
func DefaultConfig() {
config = &Config{debug:true, key:"abcde",
proxyNumber:5,
}
}
//Exist: check the file exist
func Exists(path string) bool {
_, err := os.Stat(path)
if err == nil { return true }
if os.IsNotExist(err) { return false }
return false
}
you can use config to load and save the config file.
This is a very good question because it delves into what I suspect may be an omission from Go - immutable state.
From the language reference, "constant expressions may contain only constant operands and are evaluated at compile-time."
You cannot make vars constant, which is a shame. Joe's answer proposes encapsulation as a solution, which will work well - but it's verbose, tedious and might introduce errors.
By comparison, many impure functional languages combine mutable variables with single-assignment immutable values. For example, Scala has the keywords 'val' and 'var'; the meaning of Scala's 'var' is quite similar to Go's 'var'. Immutability is a useful tool in the toolbox because referentially-transparent side-effect-free functions can be written, alongside stateful mutable procedural code. Both have their place. Immutability is also an valuable tool for concurrency because there is no worry about possible race conditions if immutable values are shared between goroutines.
So in my opinion, amongst its many strengths, this is one of Go's shortcomings. It would presumably not be hard to support vals as well as vars, the difference being that the compiler checks that each val is assigned exactly once.
Until that feature is added, you have encapsulation as your only option.
You can do something like this:
package main
import (
"fmt"
"strconv"
)
var a string
func main() {
myvar, err := strconv.Atoi(a)
if err != nil {
fmt.Println(err)
}
fmt.Println(myvar)
}
and compile the program with
go build -ldflags '-X main.a 10' test.go
That way you can define a constant during compile time.
Just use standard go flags with iniflags. Standard go flags allow setting arbitrary config variables at program start via passing command-line flags, while iniflags "magically" add support for reading config variables from ini files.
You can wrap the variable in a function that returns its value:
func genConst(x int) func() int {
return func() int {
return x
}
}
var Constx = genConst(5)
var x1 = Constx()
This way the value cannot be changed by accident, even in the file where it's defined

Resources