How to use "range" for map correctly?

I needed to use range for map, but workflowcheck returns error:

non-deterministic, reason: iterate over map

I found in documentation that for time.Now, sleep, etc. exists functions in workflow package.
But not for range. Only a recommendation for sorting keys.

  1. How do i create a loop for a map correctly? Do I need to get a list of keys using reflect?
  2. Can i use the maps package to get the keys? Inside package also uses range
  3. Maybe you can add a range function to workflow that will be get map and callback parameters?

You can use range over map to collect keys. Then, sort them before using them. Do not call any Temporal APIs like ExecuteActivity or Sleep inside the loop. Nondeterministic code that doesn’t affect the execution order of Temporal API calls is allowed.

Please file a feature request to get this added.

We just added a helper for this (see this PR). It will be coming next release and, assuming you have comparable map keys, workflow.DeterministicKeys will give you a deterministic key set. You can range over that and access the map safely. Until released, here’s the simple implementation:

func DeterministicKeys[K constraints.Ordered, V any](m map[K]V) []K {
	r := make([]K, 0, len(m))
	for k := range m {
		r = append(r, k)
	return r