Go Flag Usage Description Contains the Word value - go

I've defined a custom flag for accepting a slice of strings as such:
type strSliceFlag []string
func (i *strSliceFlag) String() string {
return fmt.Sprint(*i)
}
func (i *strSliceFlag) Set(value string) error {
*i = append(*i, value)
return nil
}
I then parse it with
...
var tags strSliceFlag
flag.Var(&tags, "t", tFlagExpl)
flag.Parse()
...
When I build this program, and run it with the help flag: main -h, it prints out:
Usage of main:
-t value
Test explanation
My question is, where is the word value coming from? I can't find out how to remove it. I think it maybe has something to do with the default value for the flag.

value is the default argument name chosen by flag.UnquoteUsage for custom types (rendered via flag.(*FlagSet).PrintDefaults).
You can override the default with backquotes in your usage text. The backquotes are stripped from usage text. Eg:
package main
import (
"flag"
"fmt"
)
type stringSlice []string
func (s *stringSlice) String() string {
return fmt.Sprint(*s)
}
func (s *stringSlice) Set(v string) error {
*s = append(*s, v)
return nil
}
func main() {
var s stringSlice
flag.Var(&s, "foo", "append a foo to the list")
flag.Var(&s, "foo2", "append a `foo` to the list")
flag.Parse()
}
Running with -h shows how the argument name changes:
Usage of ./flagusage:
-foo value
append a foo to the list
-foo2 foo
append a foo to the list

Related

How to make nil interface to struct in golang

I'm new in Golang.
I executed the code below. I get empty humans array in the end.
What should I do in func F?
For testing(monkeypatch) sake. I have to follow the way how the origin func is called.
package main
import (
"fmt"
)
type Human struct {
Name string
}
type Cat struct {
Name string
}
func F(arr interface{}) {
switch arr.(type) {
case *[]*Human:
arr = &[]*Human{{Name: "abc"}}
arr = arr.(*[]*Human)
case *[]*Cat:
arr = &[]*Cat{{Name: "meow"}}
arr = arr.(*[]*Cat)
}
}
func main() {
var humans []*Human
F(&humans)
fmt.Println(humans)
var cats []*Cat
F(&cats)
fmt.Println(cats)
}
The answer, and the main issue cause as well, is that Go always uses pass by value (or copy of the value) when arguments are passed around to function or assigned to variables.
Your function F takes an arr argument:
func F(arr interface{}) {
//...
}
When called from your main function, you are passing an []*Human pointer as an argument, which values will be copied and fed to your function F for execution.
Going back to your function F body, the arr will be having the same value passed by main, which happens to be the address to the original []*Human struct. Upon assigning a new value to arr:
func F(arr interface{}) {
switch arr.(type) {
case *[]*Human:
arr = &[]*Human{{Name: "abc"}}
// ...
}
}
You are assigning a new value to the local arr variable and not to the original pointer, which remains, indeed, unchanged.
To update the value toward which the argument pointer is referring to, you should used the dereferrence symbol:
func F(arr interface{}) {
switch arr := arr.(type) {
case *[]*Human:
*arr = []*Human{&Human{Name: "abc"}}
fmt.Println(arr)
// ...
}
}
Note the switch arr := arr.(type) statement which creates a new arr variable (shadowing the argument arr) with the interface dynamic type to be able to assign the proper value to it.

"Cannot use .this" error when using _ for multiple type parameters in method declaration

I am playing around with type parameters (generics) using Go 1.18beta1.
Problem
Consider the following snippet:
package main
import (
"fmt"
)
func main() {
foo := &Foo[string, int]{
valueA: "i am a string",
valueB: 123,
}
fmt.Println(foo)
}
type Foo[T1 any, T2 any] struct {
valueA T1
valueB T2
}
func (f *Foo[_,_]) String() string {
return fmt.Sprintf("%v %v", f.valueA, f.valueB)
}
This snippet fails to build with the following error:
<autogenerated>:1: cannot use .this (type *Foo[string,int]) as type *Foo[go.shape.string_0,go.shape.string_0] in argument to (*Foo[go.shape.string_0,go.shape.int_1]).String
I attempted to use _ in the method declaration because of the following statement in the Type Parameters Proposal:
The type parameters listed in a method declaration need not have the same names as the type parameters in the type declaration. In particular, if they are not used by the method, they can be _.
Question
Is the build error above a bug in 1.18beta1 or am I missing something?
Snippet variations that build successfully
Use type parameter names
I can make the code build successfully if I change the String method declaration to the following (replace the _ with actual type parameters):
func (f *Foo[T1,T2]) String() string {
return fmt.Sprintf("%v %v", f.valueA, f.valueB)
}
Single type parameter
I managed to use the _ successfully when only using a single type parameter:
package main
import (
"fmt"
)
func main() {
foo := &Foo[string]{"i am a string"}
fmt.Println(foo)
}
type Foo[T1 any] struct {
value T1
}
func (f *Foo[_]) String() string {
return fmt.Sprintf("%v", f.value)
}
Instantiate Foo with same type for T1 and T2
_ also works in method declaration if Foo is instantiated with the same type (e.g. string for both T1 and T2):
package main
import (
"fmt"
)
func main() {
foo := &Foo[string, string]{
valueA: "i am a string",
valueB: "i am also a string",
}
fmt.Println(foo)
}
type Foo[T1 any, T2 any] struct {
valueA T1
valueB T2
}
func (f *Foo[_,_]) String() string {
return fmt.Sprintf("%v %v", f.valueA, f.valueB)
}
As mentioned in the comments of the question, the described behavior is a bug in Go 1.18beta1 and is being tracked by issue 50419.
Edit
I have confirmed that the bug in question is fixed in 1.18beta2, which was released on 31 January, 2022.

How to convert a user-defined named type/struct to it's anonymous type

The original question
I have the following Go code. I would like to handle Foo a struct or Bar a type as a string. With "handle" I mean that I would like to convert/cast/whatever it's underlaying value to the (real) type string. I have a workaround, but I find it unintuitive in the case of a struct.
Going for a Type (instead of a struct) seems the better approach. I don't need to maintain any state, nor do I have any need for "inheriting" type specific functionality, so in my case it should work. However a call to type.String() causes stack recursion. I'm mostly curious if I'm not missing something (obvious).
package main
import "fmt"
type Foo struct {
string
}
func (f *Foo) String() string {
return f.string
}
type Bar string
func (b *Bar) String() string {
return fmt.Sprintf("%s", b) // Cannot use: return string(b) here.
}
func main() {
a := Foo{"a"}
var b Bar
b = "b"
fmt.Printf("A is: %s\n", a) // Doesn't call a.String() ?
//fmt.Printf("A is: %s\n", string(a)) // Doesn't work
fmt.Printf("A is: %s\n", a.string) // workaround A
fmt.Printf("A is: %s\n", a.String()) // workaround B, required if I want to use it in a different package
fmt.Printf("B is: %s\n", b) // Calls b.String()
fmt.Printf("B is: %s\n", string(b))
//fmt.Printf("B is: %s\n", b.String()) // Causes a stack overflow
}
Output:
A is: {a}
A is: a
A is: a
B is: b
B is: b
Code on Go's Playground: https://play.golang.org/p/zgrKao4cxa
The behaviour is from Go version 1.5.2
Answers
The following are short examples based on the answers of my original questions. Also, the following post helped in understanding and reasoning of the subject: Value receiver vs. Pointer receiver in Golang?
In case of a type, the following works:
type MyString string
func (b MyString) String() string {
return string(b)
}
Go's Playground link: https://play.golang.org/p/H12bteAk8D
In case of a struct, the following works:
package main
import "fmt"
type MyString struct {
string
someState int
}
func (m MyString) String() string {
return string(m.string)
}
func main() {
// The verbose version:
//var a MyString = MyString{string: "a", someState: 1}
a := MyString{"a", 1}
fmt.Printf("A is: %s\n", a)
fmt.Printf("A is: %s\n", a.String())
}
Go's Playground link: https://play.golang.org/p/GEKeY4rmB8
You've made a pointer receivers for your String methods, but you are working with values, not pointers to them, so it wouldn't apply. You need to switch to pointers or change String methods signatures:
package main
import "fmt"
type Foo struct {
string
}
func (f Foo) String() string {
return "My " + f.string
}
type Bar string
func (b Bar) String() string {
return fmt.Sprintf("My %s", string(b))
}
func main() {
a := Foo{"a"}
var b Bar = "b"
fmt.Printf("A is: %s\n", a)
fmt.Printf("B is: %s\n", b)
}
Please, be careful with receivers type:
The rule about pointers vs. values for receivers is that value methods
can be invoked on pointers and values, but pointer methods can only be
invoked on pointers
Oh, and one more thing. fmt.Sprintf("%s", b) will call String method if it's defined. So, you'll get a recursion.

How to define group of flags in go?

I'm trying to make use of the flag package. My whole issue is that I need to specify groups/multiple values for the same parameter.
For example I need to parse a command as below:
go run mycli.go -action first -point 10 -action
second -point 2 -action 3rd -point something
I need to retrieve each group of action/point param. Is it possible?
package main
import (
"flag"
"fmt"
"strconv"
)
// Define a type named "intslice" as a slice of ints
type intslice []int
// Now, for our new type, implement the two methods of
// the flag.Value interface...
// The first method is String() string
func (i *intslice) String() string {
return fmt.Sprintf("%d", *i)
}
// The second method is Set(value string) error
func (i *intslice) Set(value string) error {
fmt.Printf("%s\n", value)
tmp, err := strconv.Atoi(value)
if err != nil {
*i = append(*i, -1)
} else {
*i = append(*i, tmp)
}
return nil
}
var myints intslice
func main() {
flag.Var(&myints, "i", "List of integers")
flag.Parse()
}
Ref: http://lawlessguy.wordpress.com/2013/07/23/filling-a-slice-using-command-line-flags-in-go-golang/
The flag package won't help you. Closest you'll get is the os package:
[jadekler#Jeans-MacBook-Pro:~/go/src]$ go run temp.go asdasd lkjasd -boom bam -hello world -boom kablam
[/var/folders/15/r6j3mdp97p5247bkkj94p4v00000gn/T/go-build548488797/command-line-arguments/_obj/exe/temp asdasd lkjasd -boom bam -hello world -boom kablam]
So, the first runtime flag key would be os.Args[1], the value would be os.Args[2], the next key would be os.Args[3], and so on.

Map of methods in Go

I have several methods that I'm calling for some cases (like Add, Delete, etc..). However over time the number of cases is increasing and my switch-case is getting longer. So I thought I'd create a map of methods, like Go map of functions; here the mapping of functions is trivial. However, is it possible to create a map of methods in Go?
When we have a method:
func (f *Foo) Add(a string, b int) { }
The syntax below create compile-time error:
actions := map[string]func(a, b){
"add": f.Add(a,b),
}
Is it possible to create a map of methods in Go?
Yes. Currently:
actions := map[string]func(a string, b int){
"add": func(a string, b int) { f.Add(a, b) },
}
Later: see the go11func document guelfi mentioned.
There is currently no way to store both receiver and method in a single value (unless you store it in a struct). This is currently worked on and it may change with Go 1.1 (see http://golang.org/s/go11func).
You may, however, assign a method to a function value (without a receiver) and pass the receiver to the value later:
package main
import "fmt"
type Foo struct {
n int
}
func (f *Foo) Bar(m int) int {
return f.n + m
}
func main() {
foo := &Foo{2}
f := (*Foo).Bar
fmt.Printf("%T\n", f)
fmt.Println(f(foo, 42))
}
This value can be stored in a map like anything else.
I met with a similar question.
How can this be done today, 9 years later:
the thing is that the receiver must be passed to the method map as the first argument. Which is pretty unusual.
package main
import (
"fmt"
"log"
)
type mType struct {
str string
}
func (m *mType) getStr(s string) {
fmt.Println(s)
fmt.Println(m.str)
}
var (
testmap = make(map[string]func(m *mType, s string))
)
func main() {
test := &mType{
str: "Internal string",
}
testmap["GetSTR"] = (*mType).getStr
method, ok := testmap["GetSTR"]
if !ok {
log.Fatal("something goes wrong")
}
method(test, "External string")
}
https://go.dev/play/p/yy3aR_kMzHP
You can do this using Method Expressions:
https://golang.org/ref/spec#Method_expressions
However, this makes the function take the receiver as a first argument:
actions := map[string]func(Foo, string, int){
"add": Foo.Add
}
Similarly, you can get a function with the signature func(*Foo, string, int) using (*Foo).Add
If you want to use pointer to type Foo as receiver, like in:
func (f *Foo) Add(a string, b int) { }
then you can map string to function of (*Foo, string, int), like this:
var operations = map[string]func(*Foo, string, int){
"add": (*Foo).Add,
"delete": (*Foo).Delete,
}
Then you would use it as:
var foo Foo = ...
var op string = GetOp() // "add", "delete", ...
operations[op](&foo, a, b)
where GetOp() returns an operation as string, for example from a user input.
a and b are your string and int arguments to methods.
This assumes that all methods have the same signatures. They can also have return value(s), again of the same type(s).
It is also possible to do this with Foo as receiver instead of *Foo. In that case we don't have to de-reference it in the map, and we pass foo instead of &foo.

Resources