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.
Related
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()
}
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)
I've heard many times that you should avoid global variables.
In my example I declared a global myTypes variable only to avoid declaring that variable over and over again in a function call or something similar.
Is this how it should be done? Is there a better way? A more testable way?
var myTypes = map[string]string{
"type1": "tpl1",
"type2": "tpl2",
}
func AFunc(someType string) string {
fmt.Sprintf("this is your type %s", myTypes[someType])
}
func main() {
AFunc("type1")
}
Not all global variables are bad. In your case:
The global variable is in the main package and therefore only accessible by a single program. This is ok.
The global variable is initialized once and not modified thereafter. This is ok.
On the other hand, whenever a global variable is modified during the program’s execution, the program becomes more difficult to understand. Therefore it should be avoided.
In a package that is meant to be reusable, global variables should be avoided since then two users of that package might influence each other. Imagine if the json package had a global variable var Indent bool. Such a variable is better to be hidden inside a data structure like JsonFormatter that gets created anew each time someone wants to format some JSON.
One usual way is to use Method Value
Consider a struct type T with two methods, Mv, whose receiver is of type T, and Mp, whose receiver is of type *T.
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
The expression
T.Mv
yields a function equivalent to Mv but with an explicit receiver as its first argument; it has signature
func(tv T, a int) int
You can see an example of Method Value in this thread
// TODO: Get rid of the global variable.
var foo service
func handleFoo(w http.ResponseWriter, req *http.Request) {
// code that uses foo
}
func main() {
foo = initFoo()
http.HandleFunc("/foo", handleFoo)
}
One way to get rid of that global variable is to use method values:
type fooHandler struct {
foo service
}
func (h fooHandler) handle(w http.ResponseWriter, req *http.Request) {
// code that uses h.foo
}
func main() {
foo := initFoo()
http.HandleFunc("/foo", fooHandler{foo}.handle)
}
A new official approach for your global values is introduced in Go 1.7 with context.Context#Values.
Use context Values only for request-scoped data that transits processes and APIs, not for passing optional parameters to functions.
See "How to correctly use context.Context in Go 1.7"
Finally, in addition of being hard to test, global values can prevent vendoring.
See "To vendor or not to vendor, that is a question"
Many Go’s libaries have exported package variables. Those variables can be viewed as certain global states of a certain package.
Prior vendoring era, we can go get each imported package once and the global state of each imported package can be shared within all other imported packages.
Some devs may take it as granted and simply manipulate those global states at will.
However, with vendoring each imported package may have its own view of global states. Now a dev may found it impossible to change other package’s view of global state
You're not modifying myTypes, just reading it, so it's not a variable at all, it's a constant, and would be defined as such if Go supported it (and make sure you don't mutate it -- unfortunately Go doesn't allow you to enforce "constness" like other languages do). Global constants are mostly fine.
If you were to modify myTypes, e.g. by providing a function to add new types at runtime, then yes, it's a bad idea to retain myTypes as global state. You might just get away with it as long as you do it only in your "main program" which you're sure will never be a package to be imported by other code, but you don't know where this code might end up / get copied to (or even just used from multiple places in the same package), so why risk it. If this becomes a package that gets imported by other packages, things may work fine as long as there's not more than one such "client" package is active at runtime, but as soon as somebody links together several such packages into one binary, all those user packages will stomp over each other's data in the global myTypes. If a client package expects to only see the myTypes that it put in earlier, this will break if there's another client with different expectations. So packages that work fine when used individually may break when used together, with no way to fix this except changing the shared code. So just don't do it. It's a shame that Google themselves use global state in some of their own public stuff, e.g. in the standard "flag" package and things like "glog" which uses it and thus inherits the problem. Don't do it.
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
I'm currently in the design stage of writing a utility library that will make interaction with the x-go-binding a bit easier. (I've done this before with Python and xpyb.) For example, it will help with querying information defined in the EWMH spec and binding keys to callback functions. (And much more.) So as my initial idea for a package layout, consider:
xutil
ewmh
keybind
Where each is its own package. (Similar to how the standard library's image package is setup.)
What's unique about my situation is that almost every x-go-binding call requires some combination of an xgb connection object or a root window identifier. Therefore, it makes sense to me to store this information in a struct like so:
type XUtilConnection struct {
conn xgb.Conn
root xgb.Id
// a few other things, like a mapping of events to callbacks
}
So that I'd have a factory that could be used like so:
xconn = xutil.NewXUtilConnection(blah blah)
And it could be used like:
xconn.get_active_window()
xconn.bind_key("Shift-a", my_callback_fun)
There may also be functions like:
keybind.get_keycode("a")
ewmh.get_atom("_NET_ACTIVE_WINDOW")
My problem of course is that receivers, to my knowledge, can only be of types that have been declared in the same package. If I separate my packages, I cannot use my XUtilConnection type as a receiver in any of my sub-packages.
I suspect that my answer is going to be making this one big package separated into different logical files, but I fear that this might lead to namespace clutter. (For example, implementing the EWMH spec is probably on the order of 100+ functions.)
I am also aware that I could define a new container type in each sub-package for my XUtilConnection object. (I've heard that this should be a struct containing a single member XUtilConnection to avoid casting.) But this seems like a really messy situation to me, and would prevent the kind of semantics I'd like. (i.e., using an XUtilConnection struct to call methods in several different modules.)
I would suggest to use embedding.
In package xutil:
type XUtilConnection struct {
*ewmh.EWMH // Embed all methods of *ewmh.EWMH
*keybind.KeyBind // Embed all methods of *keybind.KeyBind
}
In package xutil/ewmh:
type EWMH struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some EWMH methods:
func (e *EWMH) GetAtom(name string) { ... }
func (e *EWMH) ...
In package xutil/keybind:
type KeyBind struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some keybind methods:
func (k *KeyBind) GetKeyCode(s string) { ... }
func (k *KeyBind) ...
This will enable you to directly call EWMH's and KeyBind's methods on values of type *XUtilConnection:
var c *XUtilConnection = ...
c.GetAtom("_NET_ACTIVE_WINDOW") // Call (*emwh.EWMH).GetAtom(string)
c.GetKeyCode("a") // Call (*keybind.KeyBind).GetKeyCode(string)
I'm not sure if I understood correctly the problem (I'm confused by seeing package names where they seem to be discussed as method receivers?), but I guess passing around an interface instead of the [*]struct would enable satisfying it from within any package. One can also always do something like (totally untested code):
package foo
type Foo interface { Bar(); Baz() }
----
package qux
import "foo"
type qux struct { foo.Foo; myStuff t }
func Foo(f foo.Foo) foo.Foo {
return qux{f, &t{}}
}
func (q qux) Bar() {
// smthg
}
To e.g. "override" f.Bar in package qux and "inherit" f.Baz() unaltered.