Not sure what the correct name is, but I'm looking for more information about "chained function calls" in Go. For example:
foo.DoSomething().WithThisOptionalThing()
So I can use foo.DoSomething() but with the possibility to add .WithThisOptionalThing() which does something extra's. Is this possible? Please point me in the right direction / provide some examples.
Basically, you make all your configuration functions keep returning the main "object" while you chain things together and have a final "Go" function or whatever you want to call it to make it perform the action.
Here's an example on play
package main
import (
"fmt"
)
func main() {
DoSomething().Go()
DoSomething().WithThisOptionalThing().Go()
}
type Chainable struct {
thing bool
}
func DoSomething() *Chainable {
return &Chainable{}
}
func (c *Chainable) WithThisOptionalThing() *Chainable {
c.thing = true
return c
}
func (c *Chainable) Go() error {
// Actually do something now that it's been configured
fmt.Println("Thing is", c.thing)
return nil
}
You just need to know: When it comes to chaining things your methods should either always
receive pointers and return pointers
or
receive values and return values
or
receive values and return pointers
at least they're the working combinations known to me. I couldn't find any documentation on this. If you know what's going on please let me know.
Related
I'm implementing a simple router in Go. I used to have a lot of redundant code for each endpoint returning an error when the method called wasn't implemented for that endpoint. I refactored and made a "base" type which provides default functions for each request type that simply return the unimplemented error. Now all I have to do is override the specific method functions for a given endpoint I wish to implement. This was all fun and games until I wanted to figure out, given an endpoint variable, which of the methods have been overridden?
Omitting extraneous details, here's as simple of an example as I can think of right now:
package main
import (
"fmt"
)
// Route defines the HTTP method handlers.
type Route interface {
Get() string
Post() string
}
// BaseRoute is the "fallback" handlers,
// if those handlers aren't defined later.
type BaseRoute struct{}
func (BaseRoute) Get() string {
return "base get"
}
func (BaseRoute) Post() string {
return "base post"
}
// Endpoint holds a route for handling the HTTP request,
// and some other metadata related to that request.
type Endpoint struct {
BaseRoute
URI string
}
// myEndpoint is an example endpoint implementation
// which only implements a GET request.
type myEndpoint Endpoint
func (myEndpoint) Get() string {
return "myEndpoint get"
}
func main() {
myEndpointInstance := myEndpoint{URI: "/myEndpoint"}
fmt.Println(myEndpointInstance.URI)
fmt.Println(myEndpointInstance.Get())
fmt.Println(myEndpointInstance.Post())
}
This snippet will print out the following:
/myEndpoint
myEndpoint get
base post
So my overriding of the functions works as intended. Now I'm wondering that in my main function, after I declare the myEndpointInstance, can I tell somehow that the Post function has not been overridden and is still implemented by the underlying BaseRoute without actually calling the function? Ideally, I want something like this:
func main() {
myEndpointInstance := myEndpoint{URI: "/myEndpoint"}
if myEndpointInstace.Post != BaseRoute.Post {
// do something
}
}
I've played around with the reflect package a bit, but haven't found anything helpful.
As noted by others, which method to call is a compile-time decision. So you can check this at compile time, most IDE's will navigate you to the method that is bound to the actual call.
If you want to check this at runtime, you may compare the function pointers. You can't compare function values, they are not comparable (only to the nil value). Spec: Comparison operators:
Slice, map, and function values are not comparable. However, as a special case, a slice, map, or function value may be compared to the predeclared identifier nil.
This is how you can do that:
myEndpointInstance := myEndpoint{URI: "/myEndpoint"}
v1 := reflect.ValueOf(myEndpointInstance.Post).Pointer()
v2 := reflect.ValueOf(myEndpointInstance.BaseRoute.Post).Pointer()
fmt.Println(v1, v2, v1 == v2)
v1 = reflect.ValueOf(myEndpointInstance.Get).Pointer()
v2 = reflect.ValueOf(myEndpointInstance.BaseRoute.Get).Pointer()
fmt.Println(v1, v2, v1 == v2)
This will output (try it on the Go Playground):
882848 882848 true
882880 882912 false
Output tells Post() is not "overridden" (myEndpointInstance.Post is the same as myEndpointInstance.BaseRoute.Post), while Get() is (myEndpointInstance.Get is not the same as myEndpointInstance.BaseRoute.Get).
See related questions:
How to compare 2 functions in Go?
Collection of Unique Functions in Go
I have a function which currently doesn't receive a bool parameter, but then calls another function with a hardcoded bool. We need to remove the hardcoded call and allow a bool to be passed.
I first thought I could try some default parameter - my google searches resulted in that Go apparently doesn't support optional (resp. default) parameter.
So I thought I'd try function overloading.
I found this thread on reddit, which says that it works with a special directive since version 1.7.3:
https://www.reddit.com/r/golang/comments/5c57kg/when_did_function_overloading_get_slipped_in/
I am using 1.8, and still I couldn't get it to work.
I am not even sure I may be allowed to use that directive, but I was speculating that changing the function signature right away may be dangerous as I don't know who uses the function...
Anyway - even with //+overloaded it didn't work
Is there any "idiosyncratic" way or pattern to solve this problem in Go?
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
//some comment
//+overloaded
func (self *RemoteSystem) Apply(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
//result, err := anotherFunc(rpath, true)
return self.Apply(rpath, lpath, true)
}
When I run my test, I get (forgive me for omitting part of the real path to file):
too many arguments in call to self.Apply
have (string, string, bool)
want (string, string)
../remotesystem.go:178: (*RemoteSystem).Apply redeclared in this block
previous declaration at ../remotesystem.go:185
Overloading isn't available in Go. Instead of writing functions with the same name that do different things, it is preferable to be more expressive with what the function does in the function name. In this instance, what would commonly be done is something like this:
func (self *RemoteSystem) Apply(rpath, lpath string, dynamic bool) error {
result, err := anotherFunc(rpath, dynamic)
}
func (self *RemoteSystem) ApplyDynamic(rpath, lpath string ) error {
//in this function anotherFunc was being called, and dynamic is hardcoded to true
return self.Apply(rpath, lpath, true)
}
Just by the name of the function, you can easily tell what is different and why.
Another example to provide some context (pun intended).
I write a lot of Google App Engine code in Go using go-endpoints. The way to log things is different depending on if you have a context or not. My logging functions ended up like this.
func LogViaContext(c context.Context, m string, v ...interface{}) {
if c != nil {
appenginelog.Debugf(c, m, v...)
}
}
func LogViaRequest(r *http.Request, m string, v ...interface{}) {
if r != nil {
c := appengine.NewContext(r)
LogViaContext(c, m, v...)
}
}
From the Reddit post:
Unicode. I can tell by the pixels.
Go doesn't support function overloading. But it does support using Unicode characters in function names, which allows you to write function names that look like other function names.
The first one is setValue, the second one is setV\u0430lue aka setV\xd0\xb0lue (with CYRILLIC SMALL LETTER A) and the third is setVal\U0001d69ee aka setVal\xf0\x9d\x9a\x9ee (with MATHEMATICAL MONOSPACE SMALL U).
See also:
Does the Go language have function/method overloading? (stackoverflow.com)
Why does Go not support overloading of methods and operators? (golang.org)
Alternative for function overloading in Go? (stackoverflow.com)
For example, take this code:
func jediTrainer () -> ((String, Int) -> String) {
func train(name: String, times: Int) -> (String) {
return "\(name) has been trained in the Force \(times) times"
}
return train
}
let train = jediTrainer()
train("Obi Wan", 3)
I am completely confused as to what is going on in this function. jediTrainer takes no parameters, and returns a function called train. When we say "train = jediTrainer()" are we now storing the FUNCTION "train" into the variable called "train", as it returned that function that's now stored in the variable? Can you please break down what exactly is going on here into steps? Thank you so much!
In Swift functions are first class objects that means functions can be referenced by variables, passed as parameters and returned from other functions.
In your case jediTrainer() returns a function which is a nested function in itself. So let train is referring to train() function in jediTrainer. Now you could call that train function using train variable.
For more information on this please refer to Function Types and related topics here.
You also have an opinion of definining functions inside a bodies of other functions.These are called nested function .
By default Nested functions is hidden from outside world .It can still be called and used by its enclosing function .An enclosing function can also return one of nested functions ,thus allowing the nested function to be used in another scope .
func aFunc (flag:Book)->(Int)->Int
{
func plus ( input:Int )->Int
{
return input + 1
}
func minus ( input:Int )->Int
{
return input - 1
}
if (flag)
{
return plus
}
else
{
return minus
}
}
I've recently learnt that in the net/http package, there's a pattern of usage that keeps confusing me most. It is function type conversion. It is like this:
(function a) ->convert to-> (type t)
(type t) ->implentments-> (interface i)
So, if there's a function that takes interface i as its parameter, it will invoke the function a, this is the way net/http implements it.
But when I write my own code, I've had many misunderstandings on this pattern. My code goes like this:
package main
import (
"fmt"
)
type eat interface {
eat()
}
type aaa func()
func (op *aaa) eat() {//pointer receiver not right
fmt.Println("dog eat feels good")
}
///////////////////////////////////////////////
func dog() {
fmt.Println("I'm a dog")
}
///////////////////////////////////////////////
func feelsGood(a eat) {
a.eat()
}
func main() {
b := aaa(dog)
feelsGood(b)
}
//error:aaa does not implement eat (eat method has pointer receiver)
Type aaa has method eat, the same function name and parameter signature, which conforms to the rule of interface eat, but why does it give that error? Does the receiver matter?
Another question is with only a function and type, excluding an interface, the code goes like this:
package main
import (
"fmt"
)
type aaa func()
func (op *aaa) eat() {
op()
}
///////////////////////////////////////////////
func dog() {
fmt.Println("I'm a dog")
}
///////////////////////////////////////////////
func main() {
obj:=aaa(dog)
obj.eat()
}
//error:cannot call non-function op (type *aaa)
First, is op an anonymous function, regardless of the error?
Second, it works well after I remove the asterisk, but why? op is instance of type aaa, receiver is op, does op stand for function dog()? The http package uses f(w,r) the same way, but it is a little bit of hard to understand. Is op a type, or an instance, or an anonymous function?
It seems like my comprehension of function converting is not right, but I've also checked many posts on Google, and none of them can teach me how to think of it and use it correctly.Thank you!
Question 1:
In Go, for a type T (like aaa in your case), T and *T have different method sets.
So, a value of type T can only access method:
func(t T)Foo() { ... }
While a value of type *T can access both methods:
func(t T)Foo() { ... }
func(t *T)Bar() { ... }
In your case, you have two options. Either you declare the eat method for aaa instead od *aaa:
func (op aaa) eat() {
op()
}
Or you pass the pointer to b to feelsGood:
feelsGood(&b)
Question 2:
Yes, this question is related to the first. But in this case you can access the method because obj.eat() will be short for (&obj).eat().
Your problem here is that you cannot call a function on the function pointer (op *aaa). Your options are to either create the method for aaa instead of *aaa:
func (op aaa) eat() {
op()
}
Or to call the op function on the value and not the pointer:
func (op *aaa) eat() {
(*op)()
}
For the first part of your question: See http://golang.org/doc/faq#different_method_sets which exmplains everything better than I could. You may even search stackoverflow and the golang-nuts mailing list for this question as this comes up very often.
The second is just the same IMHO: aaa doesn't have an eat-method (only *aaa has).
I am trying to understand how you return non-primitives (i.e. types that do not implement Copy). If you return something like a i32, then the function creates a new value in memory with a copy of the return value, so it can be used outside the scope of the function. But if you return a type that doesn't implement Copy, it does not do this, and you get ownership errors.
I have tried using Box to create values on the heap so that the caller can take ownership of the return value, but this doesn't seem to work either.
Perhaps I am approaching this in the wrong manner by using the same coding style that I use in C# or other languages, where functions return values, rather than passing in an object reference as a parameter and mutating it, so that you can easily indicate ownership in Rust.
The following code examples fails compilation. I believe the issue is only within the iterator closure, but I have included the entire function just in case I am not seeing something.
pub fn get_files(path: &Path) -> Vec<&Path> {
let contents = fs::walk_dir(path);
match contents {
Ok(c) => c.filter_map(|i| { match i {
Ok(d) => {
let val = d.path();
let p = val.as_path();
Some(p)
},
Err(_) => None } })
.collect(),
Err(e) => panic!("An error occurred getting files from {:?}: {}", pa
th, e)
}
}
The compiler gives the following error (I have removed all the line numbers and extraneous text):
error: `val` does not live long enough
let p = val.as_path();
^~~
in expansion of closure expansion
expansion site
reference must be valid for the anonymous lifetime #1 defined on the block...
...but borrowed value is only valid for the block suffix following statement
let val = d.path();
let p = val.as_path();
Some(p)
},
You return a value by... well returning it. However, your signature shows that you are trying to return a reference to a value. You can't do that when the object will be dropped at the end of the block because the reference would become invalid.
In your case, I'd probably write something like
#![feature(fs_walk)]
use std::fs;
use std::path::{Path, PathBuf};
fn get_files(path: &Path) -> Vec<PathBuf> {
let contents = fs::walk_dir(path).unwrap();
contents.filter_map(|i| {
i.ok().map(|p| p.path())
}).collect()
}
fn main() {
for f in get_files(Path::new("/etc")) {
println!("{:?}", f);
}
}
The main thing is that the function returns a Vec<PathBuf> — a collection of a type that owns the path, and are more than just references into someone else's memory.
In your code, you do let p = val.as_path(). Here, val is a PathBuf. Then you call as_path, which is defined as: fn as_path(&self) -> &Path. This means that given a reference to a PathBuf, you can get a reference to a Path that will live as long as the PathBuf will. However, you are trying to keep that reference around longer than vec will exist, as it will be dropped at the end of the iteration.
How do you return non-copyable types?
By value.
fn make() -> String { "Hello, World!".into() }
There is a disconnect between:
the language semantics
the implementation details
Semantically, returning by value is moving the object, not copying it. In Rust, any object is movable and, optionally, may also be Clonable (implement Clone) and Copyable (implement Clone and Copy).
That the implementation of copying or moving uses a memcpy under the hood is a detail that does not affect the semantics, only performance. Furthermore, this being an implementation detail means that it can be optimized away without affecting the semantics, which the optimizer will try very hard to do.
As for your particular code, you have a lifetime issue. You cannot return a reference to a value if said reference may outlive the value (for then, what would it reference?).
The simple fix is to return the value itself: Vec<PathBuf>. As mentioned, it will move the paths, not copy them.