In summary, is there a way to convert any string to function/method.
I'm not sure what you're trying to achieve here. It doesn't make any sense.
In general, to populate struct fields using command line args, you could do something like the following.
package main
import (
"fmt"
"log"
"strconv"
"os"
)
type Options struct {
Field1 string
Field2 int64
}
func main() {
if len(os.Args) < 2 {
log.Fatal("missing two required positional arguments: Field1 and Field2")
}
opts := &Options{}
opts.Field1 = os.Args[1]
var err error
opts.Field2, err = strconv.ParseInt(os.Args[2], 10, 64)
if err != nil {
log.Fatalf("failed to parse integer value: %v", os.Args[2])
}
fmt.Println(opts)
}
To make your life a whole lot easier, you could use flag
(or pflag
) package to declare input arguments as command-line flags.
import (
"flag"
"fmt"
)
type Options struct {
Field1 string
Field2 int
}
var opts Options
func init() {
flag.StringVar(&opts.Field1, "field1", "", "help message for field1")
flag.IntVar(&opts.Field2, "field2", 0, "help message for field2")
flag.Parse()
}
func main() {
fmt.Println(opts)
}
Or, like @Jomaar answered, you could use a helper library like go-arg
to avoid manually declaring command-line flags. Another alternative is go-flags
.
Edit
After further clarification, it appears that you want to selectively write the fields of a struct using a writer and you want to use positional command-line arguments to specify which fields to write.
I think map
will be a more suitable data structure for storing options in this case since it will allow you to simply refer to fields using their string
keys.
import (
"fmt"
"os"
)
func main() {
options := map[string]interface{} {
"field1": "some-value",
"field2": 1,
}
for _, arg := range os.Args[1:] {
if val, ok := options[arg]; ok {
fmt.Println(val)
}
}
}
If you want to continue using structs, you can use the reflect
package.
import (
"fmt"
"os"
"reflect"
)
type Options struct {
Field1 string
Field2 int
}
func main() {
opts := &Options{Field1: "some-value", Field2: 1}
for _, arg := range os.Args[1:] {
fmt.Println(getAttr(opts, arg))
}
}
// copied from https://stackoverflow.com/a/66470232/2410641
func getAttr(obj interface{}, fieldName string) (reflect.Value, error) {
pointToStruct := reflect.ValueOf(obj) // addressable
curStruct := pointToStruct.Elem()
if curStruct.Kind() != reflect.Struct {
return reflect.Value{}, fmt.Errorf("obj is not a struct")
}
curField := curStruct.FieldByName(fieldName) // type: reflect.Value
if !curField.IsValid() {
return reflect.Value{}, fmt.Errorf("field not found: %s", fieldName)
}
return curField, nil
}
Go Playground demo: https://play.golang.org/p/sch53l2bq4O