Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 迭代Golang中的结构并打印值(如果已设置)_Loops_Go_Struct - Fatal编程技术网

Loops 迭代Golang中的结构并打印值(如果已设置)

Loops 迭代Golang中的结构并打印值(如果已设置),loops,go,struct,Loops,Go,Struct,首先,如果这个问题被搞糊涂了,我要道歉,因为我只是尝试着去做,不知道我在做什么。我有一个由不同类型的各种属性组成的结构,例如: type foo struct { bar string baz int bez []string (...) 最初,我想迭代所有这些属性并打印值(如果存在),但我意识到不能像列表或映射那样对结构进行range。因此,我尝试了一些运气不佳的技巧(比如尝试迭代一个单独的属性列表),我认为我最好只是寻求帮助,因为我可能在这里超过了我的头脑 其想法是

首先,如果这个问题被搞糊涂了,我要道歉,因为我只是尝试着去做,不知道我在做什么。我有一个由不同类型的各种属性组成的结构,例如:

type foo struct {
    bar string
    baz int
    bez []string
(...)
最初,我想迭代所有这些属性并打印值(如果存在),但我意识到不能像列表或映射那样对结构进行
range
。因此,我尝试了一些运气不佳的技巧(比如尝试迭代一个单独的属性列表),我认为我最好只是寻求帮助,因为我可能在这里超过了我的头脑


其想法是,如果我创建此结构的新实例,我希望能够只打印设置的值:

obj := foo{"bar_string", 1}
鉴于字符串切片
bez
未在
obj
中设置,我希望能够执行类似(伪)的操作:

给予:

"bar_string"
1
理想情况下,不打印
[]
,我猜这是
bez
的零值


我对这整件事的看法是错的吗?我不使用映射的原因是,我希望属性是不同的类型,并且为了清晰起见,我希望将来使用的不同对象被组织到结构中。

Go没有内置的结构迭代。用于。。。范围语句仅适用于:

数组、切片、字符串或映射的所有条目,或在通道上接收的值

或使用这些基础类型之一定义的类型(例如,
类型Foo[]int

如果您想在编译时遍历已知的结构,最好只逐个访问字段

如果您想迭代编译时未知的结构,可以使用
reflect
包(不推荐):


您可能应该使用reflect,但在struct属性上迭代这是一个非常好的主意。如果您希望有一个不同值类型的对象,并且只打印设置的值,您是否有一个不太奇怪的建议?我的印象是,例如,映射需要有一个单一的类型@pzkpfw这看起来很像您试图让go按照其他(非编译)语言习惯的方式运行。不要那样做。学习如何按照应该使用的方式使用语言。Go是一种静态类型语言,如果不使用类型反射和转换,就不能有空值或不同数据类型的映射。“其思想是,如果我创建此结构的新实例,我希望能够只打印设置的值”,这不是Go的工作方式。根本没有“unset”结构字段。如果不“设置”它们,编译器/运行时只会将它们设置为零值,而您(真的!)无法区分是设置值还是编译器。
"bar_string"
1
type Foo struct {
  Bar string
  Baz int
  Quux []int
}

// x := Foo{"bar", 1, nil}
func printAny(x interface{}) {
    v := reflect.ValueOf(x)

    for i := 0; i < v.NumField(); i++ {
        field := v.Field(i)
        if !reflect.DeepEqual(field.Interface(), reflect.Zero(field.Type()).Interface()) {
            fmt.Println(field) 
            // bar
            // 1
        }
    }
}
type Foo struct {
  Bar string
  Baz int
  Quux []int
}

func (f Foo) String() string {
    s := []string{f.Bar, strconv.Itoa(f.Baz)}
    if f.Quux != nil {
        s = append(s, fmt.Sprintf("%v", f.Quux))
    }
    return strings.Join(s, "\n")
}

func main() {
   fmt.Println(Foo{"bar", 1, nil}) 
   // bar
   // 1
}