There are several ways to traverse values
from looking up based on path to iteration and walking the value tree.
Some of these are configurable, which is tied to the different labels
like regular, hidden, optional, and definitions.
We will use the following Value for the examples in this section.
We saw how to use LookupPath with ParsePath in a previous section.
We can programmatically construct paths with Selectors and MakePath.
We’ll also use this to reconstruct the label for the current value.
selectors.go
packagemainimport("fmt""os""cuelang.org/go/cue""cuelang.org/go/cue/cuecontext")funcmain(){c:=cuecontext.New()d,_:=os.ReadFile("value.cue")val:=c.CompileBytes(d)// printing the label vs pathsub:=val.LookupPath(cue.ParsePath("obj.sub"))fmt.Println(sub.Path(),getLabel(sub))}// helper function for getting the label for a valuefuncgetLabel(valcue.Value)cue.Selector{ss:=val.Path().Selectors()s:=ss[len(ss)-1]returns}
packagemainimport("fmt""os""cuelang.org/go/cue""cuelang.org/go/cue/cuecontext")funcmain(){c:=cuecontext.New()d,_:=os.ReadFile("value.cue")val:=c.CompileBytes(d)// lookup a list valueval=val.LookupPath(cue.ParsePath("obj.list"))// we use iterators to traverse a list// List() returns an iteratoriter,_:=val.List()// This pattern is standard iteration// We get the current element and nil at the endforiter.Next(){fmt.Println(iter.Value())}}
packagemainimport("fmt""os""cuelang.org/go/cue""cuelang.org/go/cue/cuecontext")funcmain(){c:=cuecontext.New()d,_:=os.ReadFile("value.cue")val:=c.CompileBytes(d)val=val.LookupPath(cue.ParsePath("obj"))// without optionsfmt.Println("Without\n---------")printFields(val.Fields())// default optionsfmt.Println("Default\n---------")printFields(val.Fields(defaultOptions...))// custom optionsfmt.Println("Custom\n---------")printFields(val.Fields(customOptions...))}funcprintFields(iter*cue.Iterator,errerror){foriter.Next(){fmt.Printf("%v: %v\n",iter.Selector(),iter.Value())}fmt.Println()}// Cue's defaultvardefaultOptions=[]cue.Option{cue.Attributes(true),cue.Concrete(false),cue.Definitions(false),cue.DisallowCycles(false),cue.Docs(false),cue.Hidden(false),cue.Optional(false),cue.ResolveReferences(false),// The following are not set// nor do they have a bool arg// cue.Final(),// cue.Raw(),// cue.Schema(),}// Our custom optionsvarcustomOptions=[]cue.Option{cue.Definitions(true),cue.Hidden(true),cue.Optional(true),}
packagemainimport("fmt""os""cuelang.org/go/cue""cuelang.org/go/cue/cuecontext")funcmain(){c:=cuecontext.New()d,_:=os.ReadFile("value.cue")val:=c.CompileBytes(d)// before (pre-order) traversalpreprinter:=func(vcue.Value)bool{fmt.Printf("%v\n",v)returntrue}// after (post-order) traversalcnt:=0postcounter:=func(vcue.Value){cnt++}// walk the valueval.Walk(preprinter,postcounter)// print countfmt.Println("\n\nCount:",cnt)}
In the previous example for default walk, some of the fields were not traversed.
This is because CUE’s default Walk() uses the same default Field() options on a value.
In order to walk all fields, we need to write a custom walk function
where we can pass in the options for Field().
custom.go
packagemainimport("fmt""os""cuelang.org/go/cue""cuelang.org/go/cue/cuecontext")constinput=`
a: {
i: int
j: int | *i
}
`funcmain(){c:=cuecontext.New()d,_:=os.ReadFile("value.cue")val:=c.CompileBytes(d)// before (pre-order) traversalpreprinter:=func(vcue.Value)bool{fmt.Printf("%v\n",v)returntrue}// after (post-order) traversalcnt:=0postcounter:=func(vcue.Value){cnt++}Walk(val,preprinter,postcounter,customOptions...)}// Walk is an alternative to cue.Value.Walk which handles more field types// You can customize this with your own optionsfuncWalk(vcue.Value,beforefunc(cue.Value)bool,afterfunc(cue.Value),options...cue.Option){// call before and possibly stop recursionifbefore!=nil&&!before(v){return}// possibly recurseswitchv.IncompleteKind(){casecue.StructKind:ifoptions==nil{options=defaultOptions}s,_:=v.Fields(options...)fors.Next(){Walk(s.Value(),before,after,options...)}casecue.ListKind:l,_:=v.List()forl.Next(){Walk(l.Value(),before,after,options...)}// no default (basic lit types)}ifafter!=nil{after(v)}}// Cue's defaultvardefaultOptions=[]cue.Option{cue.Attributes(true),cue.Concrete(false),cue.Definitions(false),cue.DisallowCycles(false),cue.Docs(false),cue.Hidden(false),cue.Optional(false),cue.ResolveReferences(false),// The following are not set// nor do they have a bool arg// cue.Final(),// cue.Raw(),// cue.Schema(),}// Our custom optionsvarcustomOptions=[]cue.Option{cue.Definitions(true),cue.Hidden(true),cue.Optional(true),}