Function defines unnamed parameters but caller still passes values - go

I'm trying to understand the Wire library in Golang and find that in the wire.go there's a function looks like this:
func NewSet(...interface{}) ProviderSet {
return ProviderSet{}
}
It looks foreign to me as to why the ...interface{}) parameter is unnamed (meaning not being used inside the function) but then the caller still passes meaningful values to it?
var Set = wire.NewSet(
wire.Value(Foo(41)),
provideFooBar)

Parameters being named or unnamed has nothing to do with whether the caller having to pass values for them. Being unnamed just means they cannot be used (cannot be referred to) inside the function.
NewSet has a variadic parameter, which means any number of arguments may be passed to it that can be assigned to the type, and any value can be assigned to interface{} (all value implements the empty interface).
The "empty" implementation of NewSet() you see is just a placeholder for documentation and compilers. The generated code will use the passed arguments.
If you have a function:
func dummy(int) {}
You can't call it like dummy(), that's a compile-time error. You can only call it by passing an int value to it, e.g. dummy(1).
See related: Is unnamed arguments a thing in Go?

Related

Is a type that extends a Map still passed by reference in Go?

If you have a type in Go, that extends a Map, is this new type still "passed by reference" (or respectively passed as a pointer value)? Or is it copied when used as a function parameter?
Example:
type myMapType map[string][]int
func doSomething(m myMapType) myMapType{
// do something
return m
}
I want to prevent unnecessary copying of data. So do I need a pointer for the above example, or not?
Thanks in advance!
When you declare
type myMapType map[string][]int
You now have a type called myMapType, whose behaviour is the same as map[string][]int.
It's the same as if every instance of myMapType was an instance of map[string][]int, with the only difference being that their types are not considered "the same" in cases where that matters (assignment, type switch, type assertion, etc.).
In other words, myMapType and map[string][]int are equi-valent but not identic-al.

mixed named and unnamed parameters in golang

I am facing an issue with my code and is giving errors:
unnamed and mixed parameters
func(uc fyne.URIWriteCloser, error) {
...
}
It looks like you declared a function that has a named, and an unnamed parameter, which you cannot do.
There are two ways you can handle parameters in a func. You can either name all of the parameters, or provide no names to any of the parameters.
This is a valid func signature with both parameters named.
func(uc fyne.URIWriteCloser, err error) {
// do something
}
And so is this, without naming the parameters.
func(fyne.URIWriteCloser, error) {
// do something
}
If you were to name the first param, but leave the second param unnamed
func(uc fyne.URIWriteCloser, error) {
// do something
}
Then you would see this error
Function has both named and unnamed parameters
So, the problem is that the second param simply declares the param type and not the name, while the first param is defining the type and naming the param.
As specified in the specs for Function Types:
Within a list of parameters or results, the names (IdentifierList) must either all be present or all be absent.
If present, each name stands for one item (parameter or result) of the specified type and all non-blank names in the signature must be unique.
If absent, each type stands for one item of that type.
Parameter and result lists are always parenthesized except that if there is exactly one unnamed result it may be written as an unparenthesized type.
So either remove uc, or add err error.

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.

Why can methods in Go only be declared on types defined in the same package?

The Go Tour says the following:
You can only declare a method with a receiver whose type is defined in the same package as the method. You cannot declare a method with a receiver whose type is defined in another package (which includes the built-in types such as int).
Is there a reason for this other than avoiding everyone building their own methods off int and string? I've Googled around, but can't find anything referencing it.
The reason is that if you could define methods on other packages' types, you could modify the behavior of other packages. This is because the method set of a given type can have an effect on how values of that type are used.
Consider, for example, the fmt.Println function. When you pass an argument to fmt.Println, it will print a string representation of that value based on a set of rules. One of those rules is that if the type of the value has a String() string method (that is, it implements the fmt.Stringer interface), then that method will be called in order to obtain the string representation of the value.
Thus, imagine that we have a package, foo, and that package has a type, FooInt, defined as follows:
type FooInt int
Now imagine that this package also has a function, PrintFooInt:
func PrintFooInt(f FooInt) { fmt.Println(f) }
This will print the integer value of f. But let's say that you (in a different package, say main) were able to add methods to FooInt. Then you could do this:
func (f FooInt) String() string { return "foobar!" }
This would actually change the behavior of foo.PrintFooInt, which shouldn't be possible from outside the package.

Function parameter error - Missing Argument Label Anomaly - SWIFT

I have a strange issue (which I can overcome however I would like to get a proper understanding of my error).
I have a small random number generator function which I use often:
func ranNum(low: Int, high:Int) -> UInt32 {
var result = arc4random_uniform(UInt32((high+1)-low)) + low
return result
}
When I use this in XCode playgrounds it works just fine if I pass in something like:
ranNum(1, 10)
However, in a regular Swift file it generates the error message : Missing argument label 'hi:' in call. Now I can overcome this by calling the function this way:
ranNum(1, hi:10)
Apart from it just being a little harder to read, it just isn't making sense why it works in Playgrounds but also why it requires only the 2nd argument label and not both. Any help as to what I am not understandinh would be greatly appreciated.
That's called external parameter name, and by default:
global functions: don't have implicit external names
class/struct methods: external names are automatically defined for all parameters after the first
initializers: external names are automatically defined for all parameters
If not explicitly specified, external names take the same name as the local parameter.
You can override that by prefixing a local parameter name with _. In your case:
func ranNum(low: Int, _ high:Int) -> UInt32 {
...
}
You mentioned that in playground calling the function works without any external parameter name - I may argue that:
in playground you have that function as a global function
in other tests, that function is a class/struct method
Am I right?

Resources