go - 将命令行参数转换为结构字段
问题描述
我正在尝试打印一个 JSON(转换为 struct)字段,特别是它作为终端的输入。
type foo struct{
field1 string
field2 int
}
这是我创建的结构示例,我想将“field1”作为命令行参数,并通过达到解码的 JSON 输出将其打印到 html 正文或控制台。
通常我可以用这种方式打印它,但我找不到将os.Args[1]值转换为已经定义的结构字段的方法。
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]))
顺便说一句,要调用多个字段。预定义当然可以解决某种情况,但我想学习的是另一回事。
解决方案
总之,有没有办法将任何字符串转换为函数/方法。
我不确定你想在这里实现什么。这没有任何意义。
通常,要使用命令行参数填充结构字段,您可以执行以下操作。
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
推荐阅读
- r - 根据另一列的条件提取值
- c++ - 当您只需要修改父依赖项之一的方法时,创建派生类的最佳方法
- python - 如何测试在 tarfile.open 上下文管理器中调用的函数?
- sql-server - 从字符串 yyyy-mm-dd HH:mm:ss.fff 更新 DateTime 字段会导致错误
- python - 如果用户创建了博客文章,Django 2.2 无法弄清楚如何授权用户编辑或删除博客文章
- angular - 单个字符串数组上的角度过滤器
- kotlin - Bmi计算器科特林
- python - 我正在为我的 python 类制作一个游戏,但我无法让它运行
- javascript - 如何在我的代码中插入换行符?
- swift - 当我将 JSONEncoder 与 Date 类型一起使用时,我得到的日期为“598146673”