Go: How to use named arguments when calling a function? - go

How can I invoke a function while using named arguments?
(If it's unclear what named arguments are, here's an example of using them in Python)
Example of what I'd like to do:
func Add(a int, b int) int {
return a + b
}
func main() {
c := Add(a: 1, b:3)
return c
}
However, the above gives me the error:
unexpected :, expecting comma or )
(it's referring to the ':' right after the 'a')

In brief: the Go language does not support named args but IDEs do (see below).
I agree that named arguments could be useful in Go. It could help avoid bugs. For example, just yesterday my tests picked up a bug where the source and dest. parameters to copy() (Go built-in function) were back to front.
However, there are probably hundreds of useful language features that Go could have. We try to avoid adding non-essential features to the language to keep things simple. Once you've used Go for a large project you will greatly appreciate how much simpler things are compared to other languages. (I have used more than a dozen languages professionally and Go is by far the least annoying.)
But actually you can have named arguments if your IDE supports it. For example, I use GoLand and when you enter the arguments to a function it shows the parameter name (in light gray) in-line with a colon before the value. This is even better than what you are used to as you don't even have to type the name!

Go does not have named arguments. The closest thing I know of in Go to named arguments is using a struct as input. So for your example you could do -
type Input struct {
A int
B int
}
func Add(in Input) int {
return in.A + in.B
}
func main() {
c := Add(Input{A: 1, B: 3})
return c
}

Related

Is it possible to get a single value from a function (which has multiple return values) during a statement?

Lets say for example add(int, int) returns and int and an error, and I want to append the int return value into a string. The way I know how to do it in go is:
foo := ""
bar, _ := add(1, 2)
foo += strconv.Itoa(bar)
However, if add() didn't return an error variable, I can just do foo += strconv.Itoa(add(1, 2)).
Is it possible to ignore the error variable during the statement to do something like that?
Is it possible to ignore the error variable during the statement to do something like that?
No, Go offers no language construct for something like this.
(But you can have your own Must... functions like you'll find in package regexp or text/template.)
Disclaimer (my opinion): This answer is just for fun. I don't recommend ever using this. Ignoring errors is bad, and trying to compactify every line of code is a fool's errand. This just illustrates some interesting concepts about how Go handles multiple return values, and I learned something new while writing this, so I thought I'd share.
Related: The more practical cousin of this problem is the "Must pattern", used by some of the standard library including templates. It involves taking a value and an error, panicing if the error is not nil, and then returning the value. See this (currently frozen) proposal
You need a wrapper function to do this. The multiple return values will automatically expand to fill the arguments.
See this example which matches the types of add()
func ignoreError(i int, err error) int {
return i
}
Calling:
foo := ""
foo += strconv.Itoa(ignoreError(add(1, 2)))
Here's a more general alternative, which will take any number of values from another function and return the first.
func takeFirstValue(v ...interface{}) interface{} {
if len(v) == 0 {
return nil
}
return v[0]
}
Calling:
foo := ""
foo += strconv.Itoa(takeFirstValue(add(1, 2)).(int))
This option requires casting at the call site .(int) to restore the data type, as takeFirstValue returns interface{}.

Map to store generic type functions in Go

I am trying to create a Map with String and functions as key and Value. It works if all functions are of same signature but my requirement is to store functions of different signature in the same map. Is this possible in Go?
package main
import "fmt"
func main() {
functions := buildFunctions()
f := functions["isInValid"]
// f("hello")
}
func buildFunctions() map[string]func() bool {
functions := map[string]func() bool{
"isInValid": isInValid,
"isAvailable": isAvailable,
}
return functions
}
func isInValid(s string) bool {
fmt.Println("Invalid ", s)
return true
}
func isAvailable(s string, s1 string) bool {
return true
}
https://play.golang.org/p/ocwCgEpa_0G
Go is a strongly typed language. So, it's not possible the way, it is possible with, say python. But just like python, once you do this, you loose the benefit of compile time error checks, and your runtime error checking has to be full-proof.
Here's what you can do:
Use map[string]interface{} type for your function map, which enables you to store anything. But then you are responsible to correctly type assertion at the time of calling. Problem is that, in most cases, if while calling a function, you could know the type of function, may be you might not need a map in the first place.
Use a map[string]string or map[string]interface{} as the argument, and return type in all the functions that are supposed to go into this map. Or at least put all the variable arguments into this map.
eg.
map[string](func (name string, age int, other_attributes
map[string]interface{}) (map[string]interface{}, error))
But again, each function call should provide the correct arguments, and there should also be checks inside the functions, to see (with non-panic version of map lookup), if the parameters are correctly provided, if not, you can return a custom error like ErrInvalidParametersPassed. (playing the role of an interpreter). But you will still have lesser chances of messing up, compared to first option. As the burden of type assertion will be on the function implementation, and not the caller. Caller just needs to fetch it's required values, which it anyways needs to know about.
But yet, best option would be to redesign your actual solution in a way, so that it can be done without going this road. As #bereal suggested in comments, it's good to have separate maps if possible, or maybe use a superset of arguments if they aren't too different, or too many. If there are just a few arguments, even switch case could be clean enough. Look for ways that cheat/bypass compile time checks, when you are truly convinced that there is no other elegant way.

Idiomatic way to initialise an empty string in Go

In Go you can initialise an empty string (in a function) in the following ways:
var a string
var b = ""
c := ""
As far as I know, each statement is semantically identical. Is one of them more idiomatic than the others?
You should choose whichever makes the code clearer. If the zero value will actually be used (e.g. when you start with an empty string and concatenate others to it), it's probably clearest to use the := form. If you are just declaring the variable, and will be assigning it a different value later, use var.
var a string
It's not immediately visible that it's the empty string for someone not really fluent in go. Some might expect it's some null/nil value.
var b = ""
Would be the most explicit, means everyone sees that it's a variable containing the empty string.
b := ""
The := assigment is so common in go that it would be the most readable in my opinion. Unless it's outside of a function body of course.
There isn't a right way to declare empty variables, but there are some things to keep in mind, like you can't use the := shortcut outside of a function body, as they can with var:
var (
name string
age int64
)
I find var name = "" to be the clearest indication that you're declaring an empty variable, but I like the type explicitness of var name string. In any case, do consider where you are declaring variables. Sometimes all at once outside the function body is appropriate, but often nearest to where you actually use it is best.
rob (Pike?) wrote on a mailthread about top-level declaration
At the top level, var (or const or type or func) is necessary: each item must be introduced by a keyword for ur-syntactic reasons related to recognizing statement boundaries. With the later changes involving semicolons, it became possible, I believe, to eliminate the need for var in some cases, but since const, type, and func must remain, it's not a compelling argument.
There is a certain ambiguity in "short-variable" declarations (using :=), as to whether the variable is declared or redeclared as outlined in the specs:
Unlike regular variable declarations, a short variable declaration may redeclare variables provided they were originally declared earlier in the same block (or the parameter lists if the block is the function body) with the same type, and at least one of the non-blank variables is new. As a consequence, redeclaration can only appear in a multi-variable short declaration. Redeclaration does not introduce a new variable; it just assigns a new value to the original.
There is absolutely no difference in the generated code (with the current compiler – Go 1.7.4), and also gometalinter does not complain for any of those. Use whichever you like.
Some differences:
You can only use the short variable declaration in functions.
With short variable declaration, you can create variables of multiple types in one line, e.g.
a, b := "", 0
The following 3 apps generate identical code:
a.go
package main
import "fmt"
func main() { var a string; fmt.Println(a) }
b.go
package main
import "fmt"
func main() { var a = ""; fmt.Println(a) }
c.go
package main
import "fmt"
func main() { a := ""; fmt.Println(a) }
To verify, build each (e.g. with go build -o a), and use diff on Linux to compare the executable binaries:
diff a b && diff a c
I try to stick to the short declaration for a couple of reasons.
It's shorter
Consistency
Allocates memory for maps, slices and pointers to structs and types.
Although var a string and a := "" are the same, b := []T{} and var b []T are not the same. When dealing with slices and maps the shorter declaration will not be nil. More often then not (especially with maps) I want allocated memory.
There are few situations where var will be needed, for instance, you are calling a function that will populate a property of a type.
var err error
foo.Name, err = getFooName()
Using := syntax in the above situation will error out since foo.Name is already declared.
just
*new(string)
It's only stuff in stackoverf related to empty strings in go. So it should be here

Best practice for unions in Go

Go has no unions. But unions are necessary in many places. XML makes excessive use of unions or choice types. I tried to find out, which is the preferred way to work around the missing unions. As an example I tried to write Go code for the non terminal Misc in the XML standard which can be either a comment, a processing instruction or white space.
Writing code for the three base types is quite simple. They map to character arrays and a struct.
type Comment Chars
type ProcessingInstruction struct {
Target *Chars
Data *Chars
}
type WhiteSpace Chars
But when I finished the code for the union, it got quite bloated with many redundant functions. Obviously there must be a container struct.
type Misc struct {
value interface {}
}
In order to make sure that the container holds only the three allowed types I made the value private and I had to write for each type a constructor.
func MiscComment(c *Comment) *Misc {
return &Misc{c}
}
func MiscProcessingInstruction (pi *ProcessingInstruction) *Misc {
return &Misc{pi}
}
func MiscWhiteSpace (ws *WhiteSpace) *Misc {
return &Misc{ws}
}
In order to be able to test the contents of the union it was necessary to write three predicates:
func (m Misc) IsComment () bool {
_, itis := m.value.(*Comment)
return itis
}
func (m Misc) IsProcessingInstruction () bool {
_, itis := m.value.(*ProcessingInstruction)
return itis
}
func (m Misc) IsWhiteSpace () bool {
_, itis := m.value.(*WhiteSpace)
return itis
}
And in order to get the correctly typed elements it was necessary to write three getters.
func (m Misc) Comment () *Comment {
return m.value.(*Comment)
}
func (m Misc) ProcessingInstruction () *ProcessingInstruction {
return m.value.(*ProcessingInstruction)
}
func (m Misc) WhiteSpace () *WhiteSpace {
return m.value.(*WhiteSpace)
}
After this I was able to create an array of Misc types and use it:
func main () {
miscs := []*Misc{
MiscComment((*Comment)(NewChars("comment"))),
MiscProcessingInstruction(&ProcessingInstruction{
NewChars("target"),
NewChars("data")}),
MiscWhiteSpace((*WhiteSpace)(NewChars(" \n")))}
for _, misc := range miscs {
if (misc.IsComment()) {
fmt.Println ((*Chars)(misc.Comment()))
} else if (misc.IsProcessingInstruction()) {
fmt.Println (*misc.ProcessingInstruction())
} else if (misc.IsWhiteSpace()) {
fmt.Println ((*Chars)(misc.WhiteSpace()))
} else {
panic ("invalid misc");
}
}
}
You see there is much code looking almost the same. And it will be the same for any other union. So my question is: Is there any way to simplify the way to deal with unions in Go?
Go claims to simplify programing work by removing redundancy. But I think the above example shows the exact opposite. Did I miss anything?
Here is the complete example: http://play.golang.org/p/Zv8rYX-aFr
As it seems that you're asking because you want type safety, I would firstly argue that your initial
solution is already unsafe as you have
func (m Misc) Comment () *Comment {
return m.value.(*Comment)
}
which will panic if you haven't checked IsComment before. Therefore this solution has no benefits over
a type switch as proposed by Volker.
Since you want to group your code you could write a function that determines what a Misc element is:
func IsMisc(v {}interface) bool {
switch v.(type) {
case Comment: return true
// ...
}
}
That, however, would bring you no compiler type checking either.
If you want to be able to identify something as Misc by the compiler then you should
consider creating an interface that marks something as Misc:
type Misc interface {
ImplementsMisc()
}
type Comment Chars
func (c Comment) ImplementsMisc() {}
type ProcessingInstruction
func (p ProcessingInstruction) ImplementsMisc() {}
This way you could write functions that are only handling misc. objects and get decide later
what you really want to handle (Comments, instructions, ...) in these functions.
If you want to mimic unions then the way you wrote it is the way to go as far as I know.
I think this amount of code might be reduced, e.g. I personally do not think that safeguarding type Misc against containing "illegal" stuff is really helpful: A simple type Misc interface{} would do, or?
With that you spare the constructors and all the Is{Comment,ProcessingInstruction,WhiteSpace} methods boil down to a type switch
switch m := misc.(type) {
Comment: fmt.Println(m)
...
default: panic()
}
Thats what package encoding/xml does with Token.
I am not sure to understand your issue. The 'easy' way to do it would be like the encoding/xml package with interface{}. If you do not want to use interfaces, then you can do something like you did.
However, as you stated, Go is a typed language and therefore should be use for typed needs.
If you have a structured XML, Go can be a good fit, but you need to write your schema. If you want a variadic schema (one given field can have multiple types), then you might be better off with an non-typed language.
Very useful tool for json that could easily rewritten for xml:
http://mholt.github.io/json-to-go/
You give a json input and it gives you the exact Go struct. You can have multiple types, but you need to know what field has what type. If you don't, you need to use the reflection and indeed you loose a lot of the interest of Go.
TL;DR You don't need a union, interface{} solves this better.
Unions in C are used to access special memory/hardware. They also subvert the type system. Go does not have the language primitives access special memory/hardware, it also shunned volatile and bit-fields for the same reason.
In C/C++ unions can also be used for really low level optimization / bit packing. The trade off: sacrifice the type system and increase complexity in favor of saving some bits. This of course comes with all the warnings about optimizations.
Imagine Go had a native union type. How would the code be better? Rewrite the code with this:
// pretend this struct was a union
type MiscUnion struct {
c *Comment
pi *ProcessingInstruction
ws *WhiteSpace
}
Even with a builtin union accessing the members of MiscUnion requires a runtime check of some kind. So using an interface is no worse off. Arguably the interface is superior as the runtime type checking is builtin (impossible to get wrong) and has really nice syntax for dealing with it.
One advantage of a union type is static type check to make sure only proper concrete types where put in a Misc. The Go way of solving this is "New..." functions, e.g. MiscComment, MiscProcessingInstruction, MiscWhiteSpace.
Here is a cleaned up example using interface{} and New* functions: http://play.golang.org/p/d5bC8mZAB_

How to statically limit function arguments to a subset of values

How does one statically constrain a function argument to a subset of values for the required type?
The set of values would be a small set defined in a package. It would be nice to have it be a compile-time check instead of runtime.
The only way that I've been able to figure out is like this:
package foo
// subset of values
const A = foo_val(0)
const B = foo_val(1)
const C = foo_val(2)
// local interface used for constraint
type foo_iface interface {
get_foo() foo_val
}
// type that implements the foo_iface interface
type foo_val int
func (self foo_val) get_foo() foo_val {
return self
}
// function that requires A, B or C
func Bar(val foo_iface) {
// do something with `val` knowing it must be A, B or C
}
So now the user of a package is unable to substitute any other value in place of A, B or C.
package main
import "foo"
func main() {
foo.Bar(foo.A) // OK
foo.Bar(4) // compile-time error
}
But this seems like quite a lot of code to accomplish this seemingly simple task. I have a feeling that I've overcomplicated things and missed some feature in the language.
Does the language have some feature that would accomplish the same thing in a terse syntax?
Go can't do this (I don't think, I don't think a few months makes me experienced)
ADA can, and C++ can sometimes-but-not-cleanly (constexpr and static_assert).
BUT the real question/point is here, why does it matter? I play with Go with GCC as the compiler and GCC is REALLY smart, especially with LTO, constant propigation is one of the easiest optimisations to apply and it wont bother with the check (you are (what we'd call in C anyway) statically initialising A B and C, GCC optimises this (if it has a definition of the functions, with LTO it does))
Now that's a bit off topic so I'll stop with that mashed up blob but tests for sane-ness of a value are good unless your program is CPU bound don't worry about it.
ALWAYS write what it easier to read, you'll be thankful you did later
So do your runtime checks, if the compiler has enough info to hand it wont bother doing them if it can deduce (prove) they wont throw, with constant values like that it'll spot it eaisly.
Addendum
It's difficult to do compile time checks, constexpr in c++ for example is very limiting (everything it touches must also be constexpr and such) - it doesn't play nicely with normal code.
Suppose a value comes from user input? That check has to be at runtime, it'd be silly (and violate DRY) if you wrote two sets of constraints (however that'd work), one for compile one for run.
The best we can do is make the compiler REALLY really smart, and GCC is. I'm sure others are good too ('cept MSs one, I've never heard a compliment about it, but the authors are smart because they wrote a c++ parser for a start!)
A slightly different approach that may suit your needs is to make the function a method of the type and export the set of valid values but not a way to construct new values.
For example:
package foo
import (
"fmt"
)
// subset of values
const A = fooVal(0)
const B = fooVal(1)
const C = fooVal(2)
// type that implements the foo_iface interface
type fooVal int
// function that requires A, B or C
func (val fooVal) Bar() {
fmt.Println(val)
}
Used by:
package main
import "test/foo"
func main() {
foo.A.Bar() // OK, prints 0
foo.B.Bar() // OK, prints 1
foo.C.Bar() // OK, prints 2
foo.4.Bar() // syntax error: unexpected literal .4
E := foo.fooVal(5) // cannot refer to unexported name foo.fooVal
}

Resources