Is it possible to use only one of the return values when initializing members in Go? - go

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.

Related

Modifying struct

I have a struct such as
type Info struct {
Foo string
FooBar string
Services string
Clown string
}
and lets say I have already populated the first 2 fields
input := &Info{
Foo: "true",
Services: "Massage",
}
Is there a way to "reopen" the struct to add missing elements. Something like this :
input = {
input,
Foobar: "Spaghetti",
Clown: "Carroussel"
}
Instead of
input.Foobar = "Spaghetti"
input.Clown = "Carroussel"
I have multiple fields and just don't really like having many lines input.Fields. I didn't find anything like it. So I was wondering.
No, this is not supported by the language's syntax.
Btw, the solution you want to avoid consists of less lines that the theoretical alternative :) (2 lines vs 4 lines in your example).
One could create a helper function which copies non-zero fields from one instance of a struct to another, so you could create a struct with the additional fields using a composite literal and use that as the source, but this requires using reflection, which is slow, and this solution wouldn't be more readable.
See related: "Merge" fields two structs of same type

Can I add items to a slice in the creation statement depending on a condition?

I have function that creates a slice like this :
func buildOptions(cfg *ServerConfig) []SomeType {
return []SomeType{
Option1,
Option2,
Option3,
}
}
I need Option3 to be added to the slice only if a certain condition is met. Can it be done with some kind of immediate if in the same statement?
of do I have to do something like this:
func buildOptions(cfg *ServerConfig) []SomeType {
options:= []SomeType{
Option1,
Option2,
}
if addOption3==true{
options = append(options, Option3)
}
return options
}
No, you can't have conditional inclusion of listed elements in a composite literal.
And it may be more verbose using an additional if and append(), but it's much more obvious what happens (what your code does).
You could achieve something like this using a helper function passing the condition and all the elements, but that just obfuscates the code more and would have worse performance.

Use map[string]SpecificType with method of map[string]SomeInterface into

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.

how to pass different types to a function

I have two golang functions, doing exactly same thing, one takes input a slice and the other takes a map as input. I want to combine this into one function, to avoid duplication.
func DoSomething([]data) {
//do something.
}
func DoSomething(map[string]data) {
//do something.
}
Combined function may look like:
func DoSomethingNew (param type) {
//param could be map or slice
}
I want to know if it is possible to pass different types to same function in golang and how. I googled but couldn't find anything relevant.
You can use interfaces Go Playground
func F(data interface{}) {
switch data.(type){
case []int:
fmt.Println("Slice")
fmt.Println(data)
case map[string]int:
fmt.Println("Map")
fmt.Println(data)
}
fmt.Println()
}
where you actually check for the type and do something based on the type.
There are several ways you could do this, but the simple way would be to make it so DoSomethingNew accepts the interface{} type. Inside of the method you would then do a type switch or in this case with only two options, perhaps just one type assertion, followed by the other, returning error if both fail. Another option would be to have both as arguments and check for nil inside the function with a similar if, else-if, else pattern to handle the error if the input is of neither types you're looking for. To make your code more safe you could move to a more strict interface than the empty one which all types implement. You could also do some method chaining or even implement the method with using the types themselves as the receiving type. Here's an example that shows a few of the ideas; https://play.golang.org/p/_v2AyFjGzv

Golang, Go : mapping with returning interface?

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...

Resources