Sobes.tech
Senior
21

package main func oneStep(yield func() bool) { yield() } func f() { for range oneStep { print("f ") recover() } } func g() { for range 1 { print("g ") recover() } } func checkPanic(loop func(), c chan<- struct{}) { defer func() { println(recover() != nil) c <- struct{}{} }() defer loop() panic(123) } func main() { c := make(chan struct{}, 1) go checkPanic(f, c) <-c go checkPanic(g, c) <-c }

Companies where asked
sber tech

Answer from AI

sobes.tech AI

В представленном коде есть несколько ошибок и недопониманий, связанных с использованием циклов и функций в Go.

  1. Функция oneStep принимает функцию yield и просто вызывает её, возвращая bool, но не является итератором или каналом, поэтому использовать for range oneStep невозможно.

  2. В функции f и g попытка использовать for range по функции или по числу (for range 1) некорректна — в Go можно итерироваться по срезам, массивам, каналам, строкам, но не по функциям или числам.

  3. В функции checkPanic происходит паника, которая должна быть поймана в recover внутри отложенной функции. При этом defer loop() вызывается после установки defer с recover, что означает, что loop() будет вызвана после установки recover, и если в loop() произойдет паника, она будет поймана.

  4. В main запускаются горутины с checkPanic(f, c) и checkPanic(g, c), и программа ждет завершения через канал.

Если исправить код, то можно сделать так, чтобы oneStep возвращала канал, по которому можно итерироваться:

func oneStep() <-chan struct{} {
	ch := make(chan struct{})
	go func() {
		ch <- struct{}{}
		close(ch)
	}()
	return ch
}

func f() {
	for range oneStep() {
		print("f ")
		recover()
	}
}

func g() {
	for i := 0; i < 1; i++ {
		print("g ")
		recover()
	}
}

Таким образом, исходный код содержит ошибки в использовании циклов и функций, и для корректной работы нужно изменить структуру, чтобы for range итерировался по каналу или срезу.