http://golang.org/pkg/sort/
This is from Go example.
// OrderedBy returns a Sorter that sorts using the less functions, in order.
// Call its Sort method to sort the data.
func OrderedBy(less ...lessFunc) *multiSorter {
return &multiSorter{
changes: changes,
less: less,
}
}
What does this do by colon? Is it mapping? Is it closure? Too much new syntax here. What should I read to understand this syntax in Go?
It's a factory function, creating and initialising a struct of type multisorter:
https://sites.google.com/site/gopatterns/object-oriented/constructors
Additionally, Go "constructors" can be written succinctly using initializers within a factory function:
function NewMatrix(rows, cols, int) *matrix {
return &matrix{rows, cols, make([]float, rows*cols)}
}
Also, it is using named parameters when initialising:
http://www.golang-book.com/9
This allocates memory for all the fields, sets each of them to their zero value and returns a pointer. (Circle) More often we want to give each of the fields a value. We can do this in two ways. Like this:
c := Circle{x: 0, y: 0, r: 5}
The `less ...lessFunc` in the func declaration means:
any number of parameters, each of type `lessFunc` can be passed here, and will be stored in the slice `less`
So it creates a `multiSorter` struct, which supports the sort interface, and calling the sort method from that interface (and implemented by multiSorter) will cause the object to use each lessFunc in turn while sorting
Does this make sense? I can expand more if needed...
Related
I have several implementation of the same method SetRateForMeasure:
package repartition
type Repartition interface {
Name() string
Compute(meters []models.Meter, totalsProd, totalsConso map[string]float64) []models.Meter
SetRateForMeasure(meter models.Meter, measure models.Measure, total float64) float64
}
Then, in my code (in repartition.go), I call it:
rate := repartition.SetRateForMeasure(meter, measure, total)
where repartition is the interface defined before.
Thing is, when I add a new implementation of this method, the arguments of my functions might differ.
For example, the static repartition use a static percentage that is only used in this case.
I end up adding parameters so that I have a common interface to all methods, but it results that there is a lot of unused parameters depending on the implementation.
If I add it to common interface, it will be unused for the other definitions.
I tried to remove this method from my interface definition, but now
rate := repartition.SetRateForMeasure()
is no more defined.
How should I organize my code ?
There is no function overloading in Go, so you cannot declare the same function with different arguments. There's a few ways you can implement this though:
You can add multiple functions with different names and signatures
You can change the function to accept a struct instead of arguments
SetRateForMeasure(args SetRateOptions) float64
type SetRateOptions struct {
Meter models.Meter
Measure models.Measure
Total float64
Percentage *float64 // If nil, use default percentage
... // more parameters as needed
}
Go doesn't support method overriding. You either define methods with different names that take different parameters
or you can declare the method to accept a parameter struct.
type SetRateParams struct {
Meter models.Meter
Measure models.Measure
Total float64
}
type Repartition interface {
SetRateForMeasure(params SetRateParams) float64
}
Optionally, you can declare params in your structs as pointers, so you can represent "not-provided" semantics with nil instead of using the zero-value. This might be relevant in case of numerical params where 0 could be a valid value.
Using a struct param has also the advantage that you don't have to change all the call sites in case you decide to add an additional param 6 months from now (you just add it to the struct).
There are also worse solutions with interface{} varargs, for the sake of stating what is possible, but unless you loathe type safety, I wouldn't recommend that.
I have two structs that are having same receiver function implementations:
type A struct {
name string
// other fields
}
type B struct {
name string
// other fields
}
type AA struct {
resource A
}
func (a *AA) Get() string {
// process something with a.resource.name
return a.resource.name
}
type BB struct {
resource B
}
func (b *BB) Get() string {
// process something with b.resource.name
return b.resource.name
}
type I interface {
Get() string
}
both structs AA and BB have Get function, in order to satisfy the interface I, this might be a dumb question, but I dont know how I can simplify them to remove the duplications of two Get functions, tried:
having a generic struct and embedded in A & B - cant do this due
to json serializations in the system I use.
embedded AA in BB and calling AA.Get - wont work since name is inside B instead of A
Combine AA and BB with both fields like resourceA and resourceB - this complicates the Get function, since then it needs to handle
create a non-receiver function and use it for both AA and BB - this can work but since there are quite some fields I need, not just name, so the function will end up with quite many parameters.
I cant stop feeling there should be an easier way, and also trying/googling a way to simplify it, but non of them seems to work, could someone point me some directions or hints?
much appreciated!
[UPDATE]
I'm trying to create a Kubernetes operator, which has some CRDs (Custom Resource Definitions), and since I create a generic controller that just take the CRDs and calling their functions (that's why I have interface), but I found I need to implement functions that are exactly the same, like GetName, GetObject, or some functions that manipulate the data and get back the results, and they're all the same across those CRD structs.
I've decided to just create a function that takes required parameters, and reuse the function across the structs, thanks for all the comments.
If you have other suggestions, please feel free to comment or suggest, thanks!
I understand how to use multiple return values in go. I further understand that in most cases one of the returns is an error, so ignoring returned values can be dangerous.
Is there a way to ignore a value in struct initializer like this? The below example does not work as Split returns two values, but I am interested only in the first one. I can of course create a variable but...
someFile := "test/filename.ext"
contrivedStruct := []struct{
parentDir string
}{
{ parentDir: filepath.Split(someFile) },
}
It's not possible to use only one of the return values when initializing members in Go.
Using variables clearly expresses your intent.
Go sometimes feels like it could be more succinct, but the Go authors favoured readability over brevity.
Alternatively, use a wrapper function. There are several 'Must' wrapper functions in the standard library, like: template.Must.
func first(args ...string) string {
return args[0]
}
For your particular example, splitting paths, see filepath.Base or filepath.Dir.
No, there is no way to skip one of the returned values in structure initializer.
I get cannot use map[string]MyType literal (type map[string]MyType) as type map[string]IterableWithID in argument to MapToList with the code below, how do I pass in a concrete map type to method that expects a interface type?
https://play.golang.org/p/G7VzMwrRRw
Go's interface convention doesn't quite work the same way as in, say, Java (and the designers apparently didn't like the idea of getters and setters very much :-/ ). So you've got two core problems:
A map[string]Foo is not the same as a map[string]Bar, even if Bar implements Foo, so you have to break it out a bit (use make() beforehand, then assign in a single assignment).
Interface methods are called by value with no pointers, so you really need to do foo = foo.Method(bar) in your callers or get really pointer-happy to implement something like this.
What you can do to more-or-less simulate what you want:
type IterableWithID interface {
SetID(id string) IterableWithID // use as foo = foo.SetID(bar)
}
func (t MyType) SetID(id string) IterableWithID {
t.ID = id
return t
}
...and to deal with the typing problem
t := make(map[string]IterableWithID)
t["foo"] = MyType{}
MapToList(t) // This is a map[string]IterableWithID, so compiler's happy.
...and finally...
value = value.SetID(key) // We set back the copy of the value we mutated
The final value= deals with the fact that the method gets a fresh copy of the value object, so the original would be untouched by your method (the change would simply vanish).
Updated code on the Go Playground
...but it's not particularly idiomatic Go--they really want you to just reference struct members rather than use Java-style mutators in interfaces (though TBH I'm not so keen on that little detail--mutators are supes handy to do validation).
You can't do what you want to do because the two map types are different. It doesn't matter that the element type of one is a type that implements the interface which is the element type of the other. The map type that you pass into the function has to be map[string]IterableWithID. You could create a map of that type, assign values of type MyType to the map, and pass that to the function.
See https://play.golang.org/p/NfsTlunHkW
Also, you probably don't want to be returning a pointer to a slice in MapToList. Just return the slice itself. A slice contains a reference to the underlying array.
I'm coming from a Node.js background, and there a typical pattern is to have a function which takes an options object, i.e. an object where you set properties for optional parameters, such as:
foo({
bar: 23,
baz: 42
});
This is JavaScript's "equivalent" to optional and named parameters.
Now I have learnt that there are no optional parameters in Go, except variadic parameters, but they lack the readability of named parameters. So the usual pattern seems to be to hand over a struct.
OTOH a struct can not be defined with default values, so I need a function to set up the struct.
So I end up with:
Call a function that creates the struct and then fills it with default values.
Overwrite the values I would like to change.
Call the function I actually want to call and hand over the struct.
That's quite complicated and lengthy compared to JavaScript's solution.
Is this actually the idiomatic way of dealing with optional and named parameters in Go, or is there a simpler version?
Is there any way that you can take advantage of zero values? All data types get initialized to a zero value, so that is a form of default logic.
An options object is a pretty common idiom. The etcd client library has some examples (SetOptions,GetOptions,DeleteOptions) similar to the following.
type MyOptions struct {
Field1 int // zero value (default) of int is 0
Field2 string // zero value (default) of string is ""
}
func DoAction(arg1, arg2 string, options *MyOptions){
var defaultValue1 int = 30 // some reasonable default
var defaultValue2 string = "west" // some reasonable default
if options != nil {
defaultValue1 = options.Field1 // override with our values
defaultValue2 = options.Field2
}
doStuffWithValues
An relevant question (and very much in the mindset of Go) would be, do you need this kind of complexity? The flexibility is nice, but most things in the standard library try to only deal with 1 default piece of info/logic at a time to avoid this.