英文:
Converting command line argument to use as struct field
问题
我正在尝试打印一个从终端输入的特定JSON字段(转换为结构体)。
这是我创建的结构体示例,我想将"field1"作为命令行参数,并通过访问解码后的JSON输出将其打印到HTML正文或控制台。
通常我可以这样打印,但我找不到一种将**os.Args1**的值转换为已定义的结构体字段的方法。
type foo struct{
field1 string
field2 int
}
var res *foo
_=json.NewDecoder(resp.Body).Decode(&res)
fmt.Println(res.field1)
总之,有没有一种将任何字符串变量转换为函数/方法的方法。非常感谢。
修订说明:例如,
我将在终端中写入:
go run main.go "field1"
程序将执行类似于以下操作:
fmt.Fprintf(writer, "option.field is %v", someFuncThatConcatenatesThisTwo("option."+ os.Args[1]))
顺便说一下,有多个字段需要调用。预定义可以解决某些特定情况,但我想了解是否还有其他方法。
英文:
I am trying to print a JSON(converted to struct) field particularly which is taken as input from terminal.
type foo struct{
field1 string
field2 int
}
This is struct sample that i created and i want to take "field1" as command-line argument and print it to html body or console by reaching decoded JSON output.
Normally i can print it this way but i couldn't find a way to convert os.Args1 value to field of struct which was already defined.
var res *foo
_=json.NewDecoder(resp.Body).Decode(&res)
fmt.Println(res.field1)
In summary, is there a way to convert any string variable to function/method. Thanks a lot in advance
Rev. note: eg.
i will write to terminal:
go run main.go "field1"
the program will do something like this
fmt.Fprintf(writer, "option.field is %v", someFuncThatConcatenatesThisTwo("option."+ os.Args[1]))
Btw, There is multiple fields to be called. Predefining could solve for a certain case of course but i want to learn is something else.
答案1
得分: 2
总结一下,有没有一种方法可以将任何字符串转换为函数/方法?
我不确定你在这里想要实现什么。这没有任何意义。
通常情况下,要使用命令行参数填充结构字段,你可以按照以下方式进行操作。
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)
}
为了让你的生活更加轻松,你可以使用 flag
(或 pflag
)包将输入参数声明为命令行标志。
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)
}
或者,像 @Jomaar 回答的那样,你可以使用一个辅助库,比如 go-arg
,以避免手动声明命令行标志。另一种选择是 go-flags
。
编辑
经过进一步澄清,似乎你想要使用写入器选择性地写入结构的字段,并且你想要使用位置命令行参数来指定要写入的字段。
在这种情况下,我认为 map
将是一个更合适的数据结构,因为它允许你使用字段的 string
键来简单地引用字段。
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)
}
}
}
如果你想继续使用结构体,你可以使用 reflect
包。
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 示例:https://play.golang.org/p/sch53l2bq4O
英文:
> 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论