// Copyright 2021 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package reflect// VisibleFields returns all the visible fields in t, which must be a// struct type. A field is defined as visible if it's accessible// directly with a FieldByName call. The returned fields include fields// inside anonymous struct members and unexported fields. They follow// the same order found in the struct, with anonymous fields followed// immediately by their promoted fields.//// For each element e of the returned slice, the corresponding field// can be retrieved from a value v of type t by calling v.FieldByIndex(e.Index).func ( Type) []StructField {if == nil {panic("reflect: VisibleFields(nil)") }if .Kind() != Struct {panic("reflect.VisibleFields of non-struct type") } := &visibleFieldsWalker{byName: make(map[string]int),visiting: make(map[Type]bool),fields: make([]StructField, 0, .NumField()),index: make([]int, 0, 2), } .walk()// Remove all the fields that have been hidden. // Use an in-place removal that avoids copying in // the common case that there are no hidden fields. := 0for := range .fields { := &.fields[]if .Name == "" {continue }if != {// A field has been removed. We need to shuffle // all the subsequent elements up. .fields[] = * } ++ }return .fields[:]}typevisibleFieldsWalkerstruct {byNamemap[string]intvisitingmap[Type]boolfields []StructFieldindex []int}// walk walks all the fields in the struct type t, visiting// fields in index preorder and appending them to w.fields// (this maintains the required ordering).// Fields that have been overridden have their// Name field cleared.func ( *visibleFieldsWalker) ( Type) {if .visiting[] {return } .visiting[] = truefor := 0; < .NumField(); ++ { := .Field() .index = append(.index, ) := trueif , := .byName[.Name]; { := &.fields[]iflen(.index) == len(.Index) {// Fields with the same name at the same depth // cancel one another out. Set the field name // to empty to signify that has happened, and // there's no need to add this field. .Name = "" = false } elseiflen(.index) < len(.Index) {// The old field loses because it's deeper than the new one. .Name = "" } else {// The old field wins because it's shallower than the new one. = false } }if {// Copy the index so that it's not overwritten // by the other appends. .Index = append([]int(nil), .index...) .byName[.Name] = len(.fields) .fields = append(.fields, ) }if .Anonymous {if .Type.Kind() == Pointer { .Type = .Type.Elem() }if .Type.Kind() == Struct { .(.Type) } } .index = .index[:len(.index)-1] }delete(.visiting, )}
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.