Idiomatic way of running 2 goroutines, the 2nd one conditionally

I want to execute 2 operations concurrently each one setting a variable (or returning a result)

The second goroutine will be executed conditionally.

In case the second one is not executed, the result set (or returned) by the second one is equal to the first one.

I am asking which is the optimal and most idiomatic way of going about this.

1. Litteral function invocation

var (
   v1, v2 int
   wg sync.WaitGroup
)

wg.Add(2)
go func(){
 v1 = anotherfunc(param1)
  wg.Done()
}
if something{
  go func(){
    v2 = anotherfunc(param2)
    wg.Done()
  }
} else {
  v2 = v1
  wg.Done()
}
wg.Wait()

2. Normal function invocation with channels

go anotherfunc(param1, channel1)
if something {
  go anotherfunc(param2, channel2)
  var2 <- channel2
}
var1 <- channel1
if !something {
 var2 = var1
}

edit: I now realise the first approach has a flaw. We cannot guarantee that the first goroutine will have returned before the v2 = v1 assignment. Not sure if there is a way of keeping the first approach with some addition(s).

If you want to keep the first approach you can just wait for the first job then conditionally add the second job:

func main() {
	var (
		v1, v2 int
		wg     sync.WaitGroup
	)
	wg.Add(1)
	go func() {
		v1 = longRunning()
		wg.Done()
	}()
	wg.Wait()
	fmt.Println("First:", v1)
	if v1 < 50 {
		// Nothing to do
		v2 = v1
	} else {
		wg.Add(1)
		go func() {
			v2 = longRunning()
			wg.Done()
		}()
		wg.Wait()
	}
	fmt.Println("Second:", v2)
}

Note that for the purposes of simulating latency I just have a function that sleeps then returns pseudo-random numbers:

// Simulate a long-running job
func longRunning() int {
	fmt.Println("Starting long-running job...")
	time.Sleep(500 * time.Millisecond)
	randSource := rand.NewSource(time.Now().UnixNano())
	randGen := rand.New(randSource)
	return randGen.Intn(100)
}

Anyway, I think this general approach is pretty readable / nice. However, I wonder if you could use channels and always just send two values so the main function doesn’t care how it gets the values as long as it gets them. Since you’re running your jobs sequentially, you only need one goroutine:

func main() {
	var v1, v2 int
	results := make(chan int)
	go func() {
		result := longRunning()
		results <- result
		// We need to do some additional processing to determine second value
		if result > 50 {
			result = longRunning()
		}
		// Send second value
		results <- result
	}()
	v1 = <-results
	fmt.Println("First:", v1)
	v2 = <-results
	fmt.Println("Second:", v2)
}

That seems pretty clean to me. Of course you need to be really careful about error handling and make sure that channel always sends two values.