I'm messing with the flag library, and found that this code does not work:
package main
import (
"fmt"
"flag"
)
var recursive bool
func init() {
recursive = *flag.Bool("r", false, "Search recursively")
}
func main() {
flag.Parse()
fmt.Printf("Recursive: %t \n\n", recursive)
flag.PrintDefaults()
}
But this does (I commented the three lines I changed):
package main
import (
"fmt"
"flag"
)
var recursive *bool //Changed to pointer type
func init() {
recursive = flag.Bool("r", false, "Search recursively") //Changed to not dereference function
}
func main() {
flag.Parse()
fmt.Printf("Recursive: %t \n\n", *recursive) //Changed to dereference variable
flag.PrintDefaults()
}
Why does this behave like this? Are functions not allowed to be dereferenced in Golang, or am I doing something else wrong?
The reason for this is because when you call flag.Bool(), it does not yet parse the command line arguments, it just defines a named flag and initializes it with the default value (which is false as you specified it).
Command line arguments are only parsed when you call flag.Parse(). If you use recursive bool, in the init() function the default false will be assigned to it. The flag package does not know about your recursive variable, so later when you call flag.Parse(), its value will not/ cannot be changed.
flag.Bool() returns a pointer to a bool variable which the flag package knows about, and later when you call flag.Parse() the pointed bool variable will be properly updated, so when you print the pointed valued after flag.Bool(), it will be the updated value which will be set based on your command line arguments.
Alternative: Register your variable
So you must store and use the pointer returned by flag.Bool() else you will only see the default value. Or you can let the flag package know about your recursive variable: you can tell the flag package that you what it to store the result into your recursive variable by telling this with the flag.BoolVar() function:
flag.BoolVar(&recursive, "r", false, "Search recursively")
Note that in this case there is no return value, becase you explicitly provided a pointer to a bool which you want the flag package to store the result to.
Related
If I have function like this
func TestMethod ( d interface{} ) {
}
If I am calling this as
TestMethod("syz")
Is this pass by value or pass by pointer ?
To summarise some of the discussion in the comments and answer the question:
In go everything in Go is passed by value. In this case the value is an interface type, which is represented as a pointer to the data and a pointer to the type of the interface.
This can be verified by running the following snippet (https://play.golang.org/p/9xTsetTDfZq):
func main() {
var s string = "syz"
read(s)
}
//go:noinline
func read(i interface{}) {
println(i)
}
which will return (0x999c0,0x41a788), one pointer to the data and one pointer to the type of interface.
Updated: Answer and comments above are correct. Just a lite bit of extra information.
Some theory
Passing by reference enables function members, methods, properties,
indexers, operators, and constructors to change the value of the
parameters and have that change persist in the calling environment.
Little code sniped to check how function calls work in GO for pointers
package main_test
import (
"testing"
)
func MyMethod(d interface{}) {
// assume that we received a pointer to string
// here we reassign pointer
newStr := "bar"
d = &newStr
}
func TestValueVsReference(t *testing.T) {
data := "foo"
dataRef := &data
// sending poiner to sting into function that reassigns that pointer in its body
MyMethod(dataRef)
// check is pointer we sent changed
if *dataRef != "foo" {
t.Errorf("want %q, got %q", "bar", *dataRef)
}
// no error, our outer pointer was not changed inside function
// confirms that pointer was sent as value
}
I am passing a pointer to a string, to a method which takes an interface (I have multiple versions of the method, with different receivers, so I am trying to work with empty interfaces, so that I don't end up with a ton of boilerplate madness. Essentially, I want to populate the string with the first value in the slice. I am able to see the value get populated inside the function, but then for some reason, in my application which calls it, tha value doesn't change. I suspect this is some kind of pointer arithmetic problem, but could really use some help!
I have the following interface :
type HeadInterface interface{
Head(interface{})
}
And then I have the following functions :
func Head(slice HeadInterface, result interface{}){
slice.Head(result)
}
func (slice StringSlice) Head(result interface{}){
result = reflect.ValueOf(slice[0])
fmt.Println(result)
}
and... here is my call to the function from an application which calls the mehtod...
func main(){
test := x.StringSlice{"Phil", "Jessica", "Andrea"}
// empty result string for population within the function
var result string = ""
// Calling the function (it is a call to 'x.Head' because I lazily just called th import 'x')
x.Head(test, &result)
// I would have thought I would have gotten "Phil" here, but instead, it is still empty, despite the Println in the function, calling it "phil.
fmt.Println(result)
}
*NOTE : I am aware that getting the first element doesn't need to be this complicated, and could be slice[0] as a straight assertion, but this is more of an exercise in reusable code, and also in trying to get a grasp of pointers, so please don't point out that solution - I would get much more use out of a solution to my actual problem here * :)
As you said in your NOTE, I'm pretty sure this doesn't have to be this complicated, but to make it work in your context:
package main
import (
"fmt"
"reflect"
)
type HeadInterface interface {
Head(interface{})
}
func Head(slice HeadInterface, result interface{}) {
slice.Head(result)
}
type StringSlice []string
func (slice StringSlice) Head(result interface{}) {
switch result := result.(type) {
case *string:
*result = reflect.ValueOf(slice[0]).String()
fmt.Println("inside Head:", *result)
default:
panic("can't handle this type!")
}
}
func main() {
test := StringSlice{"Phil", "Jessica", "Andrea"}
// empty result string for population within the function
var result string = ""
// Calling the function (it is a call to 'x.Head' because I lazily just called th import 'x')
Head(test, &result)
// I would have thought I would have gotten "Phil" here, but instead, it is still empty, despite the Println in the function, calling it "phil.
fmt.Println("outside:", result)
}
The hard part about working with interface{} is that it's hard to be specific about a type's behavior given that interface{} is the most un-specific type. To modify a variable that you pass as a pointer to a function, you have to use the asterisk (dereference) (for example *result) on the variable in order to change the value it points to, not the pointer itself. But to use the asterisk, you have to know it's actually a pointer (something interface{} doesn't tell you) so that's why I used the type switch to be sure it's a pointer to a string.
Consider this package:
package A
var X="change me"
var Y=func(i int) int { return i*i) }
func Z(i int) int { return -i) }
The two explicit variables (X,Y) can be changed in another package, say main...
package main
import "A"
func main () {
A.X="done"
A.Y=func (i int) int { return i*i*i }
print(A.X,A.Y(7))
//... but A.Z apparently can't be changed.
//A.Z=func (int i) int { return i*i*i } //main.go:8: cannot assign to A.Z
}
Obviously there's a difference between defining a func variable (like Y) and an explicit func (like Z). I have googled this but not found much in the way of enlightenment. It almost seems as if var SomeFunc=func (...) defines indeed a variable, but func SomeFunc(...) defines a constant.
PS: A small goodie I found while researching this which I have not seen mentioned in the Go books I've read so far. A dot before a package import imports names without them having to be qualified:
package main
import . "A"
func main () {
X="done"
Y=func (i int) int { return i*i*i }
print(X,Y(7))
}
func SomeFunc(), in essence creates a strong/constant/immutable binding of the identifier SomeFunc to the function you define. When you create a variable like so:
var (
SomeFunc = func(i int) int {
return i * 2
}
)
You create a global variable of the type func(int) int. You can reassign this variable later on. This is something you can't really do with a func SomeFunc identifier. Simply put, this is because func SomeFunc() binds the function Directly to the identifier. The var SomeFunc approach creates a variable (type func(int) int in this case), and that variable is initialised using the function you're assigning. As is the case with variables: reassignment is possible.
Example
What you can do with functions, is shadow them using a scoped variable. This will probably get flagged by most linters, but it's a technique/trick that sometimes can be useful in testing
Example
As for the dot-imports: Please don't do that unless there's a very, very, very good reason for it. A good reason would be you writing a package that adds to an existing one, so you no longer import an existing one, but import your own. Think of it as extending a package. 99% of the time. Don't, whatever you do, use it to quench errors when you import encoding/json to add json serialization annotations to a struct. In those cases, use an underscore:
package foo
import (
"encoding/json"
)
type Bar struct {
Foobar string `json:"foobar"`
}
func New() *Bar {
&Bar{"Default foobar"}
}
Don't know about golang 1.8, but packages like that could result in compiler errors (package encoding/json imported but not used). To silence that error, you simply changed the import to:
import(
_ "encoding/json"
)
The dot-packages, underscores, and package aliases all follow the same rule: use them as little as possible.
Code used in examples:
package main
import (
"fmt"
)
var (
SomeFunc = func(i int) int {
return i * 2
}
)
func main() {
fmt.Println(SomeFunc(2)) // output 4
reassign()
fmt.Println(SomeFunc(2)) // output 8
shadowReassign()
fmt.Println(SomeFunc(2)) // output 2
}
// global function
func reassign() {
// assign new function to the global var. Function types MUST match
SomeFunc = func(i int) int {
return i * 4
}
}
// assign function to local reassign variable
func shadowReassign() {
reassign := func() {
// same as global reassign
SomeFunc = func(i int) int {
return i
}
}
reassign()
}
There's a difference between declaring a variable initialized with a function value:
var Y=func(i int) int { return i*i) }
and declaring a function:
func Z(i int) int { return -i) }
The specification says this about declarations:
A declaration binds a non-blank identifier to a constant, type, variable, function, label, or package.
The specification also says:
A function declaration binds an identifier, the function name, to a function.
The declaration of Y binds a variable to the name. This variable is initialized with a function value. The declaration of Z binds a function to the name.
If an explicit period (.) appears instead of a name, all the package's exported identifiers declared in that package's package block will be declared in the importing source file's file block and must be accessed without a qualifier.
I'm writing a Lisp variant in Go and want to define constants for Nil and EmptyList. These will be referenced throughout the codebase, but I want to prevent them from being accidentally re-defined.
// Representation of the empty list
var EmptyList = (*List)(nil)
I can't use a const here for two reasons:
const definitions cannot be nil
const definitions cannot be pointers
What options do I have to ensure EmptyList is always the nil pointer?
In Go, use a function. For example,
package main
import "fmt"
type List struct{}
func IsEmptyList(list *List) bool {
// Representation of the empty list
return list == (*List)(nil)
}
func main() {
fmt.Println(IsEmptyList((*List)(nil)))
}
Output:
true
The function will be inlined.
$ go tool compile -m emptylist.go
emptylist.go:7: can inline IsEmptyList
emptylist.go:13: inlining call to IsEmptyList
emptylist.go:7: IsEmptyList list does not escape
emptylist.go:13: IsEmptyList((*List)(nil)) escapes to heap
emptylist.go:13: main ... argument does not escape
$
Can anyone explain flags in Go?
flag.Parse()
var omitNewline = flag.Bool("n", false, "don't print final newline")
flags are a common way to specify options for command-line programs.
package main
import (
"flag"
"fmt"
)
var (
env *string
port *int
)
// Basic flag declarations are available for string, integer, and boolean options.
func init() {
env = flag.String("env", "development", "a string")
port = flag.Int("port", 3000, "an int")
}
func main() {
// Once all flags are declared, call flag.Parse() to execute the command-line parsing.
flag.Parse()
// Here we’ll just dump out the parsed options and any trailing positional
// arguments. Note that we need to dereference the points with e.g. *evn to
// get the actual option values.
fmt.Println("env:", *env)
fmt.Println("port:", *port)
}
Run Programs:
go run main.go
Try out the run program by first giving it without flags. Note that if you omit flags they automatically take their default values.
go run command-line-flags.go --env production --port 2000
If you provide a flag with specified value then default will overwrite by passed one.
See http://golang.org/pkg/flag/ for a full description.
The arguments for flag.Bool are (name string, value bool, usage string)
name is the argument to look for, value is the default value and
usage describes the flag's purpose for a -help argument or similar, and is displayed with flag.Usage().
For more detailed example check here
flag is used to parse command line arguments. If you pass "-n" as a command line argument, omitNewLine will be set to true. It's explained a bit farther in the tutorial :
Having imported the flag package, line 12 creates a global variable to hold the value of echo's -n flag. The variable omitNewline has type *bool, pointer to bool.
Personally, I prefer the Var type functions, as they take a reference, rather
than returning a reference. That way you can use the variable without
dereferencing:
package main
import "flag"
func main() {
var omitNewline bool
flag.BoolVar(&omitNewline, "n", false, "don't print final newline")
flag.Parse()
println(omitNewline)
}
https://golang.org/pkg/flag#BoolVar