_linters/src/honnef.co/go/tools/ssa/builder.go
func (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) {
	//
	// loop:                                   (target of continue)
	//      ko = <-x                           (key, ok)
	//      ok = extract ko #1
	//      if ok goto body else done
	// body:
	//      k = extract ko #0
	//      ...
	//      goto loop
	// done:                                   (target of break)

	loop = fn.newBasicBlock("rangechan.loop")
	emitJump(fn, loop)
	fn.currentBlock = loop
	recv := &UnOp{
		Op:      token.ARROW,
		X:       x,
		CommaOk: true,
	}
	recv.setPos(pos)
	recv.setType(types.NewTuple(
		newVar("k", x.Type().Underlying().(*types.Chan).Elem()),
		varOk,
	))
	ko := fn.emit(recv)
	body := fn.newBasicBlock("rangechan.body")
	done = fn.newBasicBlock("rangechan.done")
	emitIf(fn, emitExtract(fn, ko, 1), body, done)
	fn.currentBlock = body
	if tk != nil {
		k = emitExtract(fn, ko, 0)
	}
	return
}
func (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) {
	//
	// loop:                                   (target of continue)
	//      ko = <-x                           (key, ok)
	//      ok = extract ko #1
	//      if ok goto body else done
	// body:
	//      k = extract ko #0
	//      ...
	//      goto loop
	// done:                                   (target of break)

	loop = fn.newBasicBlock("rangechan.loop")
	emitJump(fn, loop)
	fn.currentBlock = loop
	recv := &UnOp{
		Op:      token.ARROW,
		X:       x,
		CommaOk: true,
	}
	recv.setPos(pos)
	recv.setType(types.NewTuple(
		newVar("k", x.Type().Underlying().(*types.Chan).Elem()),
		varOk,
	))
	ko := fn.emit(recv)
	body := fn.newBasicBlock("rangechan.body")
	done = fn.newBasicBlock("rangechan.done")
	emitIf(fn, emitExtract(fn, ko, 1), body, done)
	fn.currentBlock = body
	if tk != nil {
		k = emitExtract(fn, ko, 0)
	}
	return
}
func ( b * builder ) rangeChan ( fn * Function , x Value , tk types . Type , pos token . Pos ) ( k Value , loop , done * BasicBlock ) { // // loop:                                   (target of continue) //      ko = <-x                           (key, ok) //      ok = extract ko #1 //      if ok goto body else done // body: //      k = extract ko #0 //      ... //      goto loop // done:                                   (target of break) loop = fn . newBasicBlock ( " " ) emitJump ( fn , loop ) fn . currentBlock = loop recv := & UnOp { Op : token . ARROW , X : x , CommaOk : true , } recv . setPos ( pos ) recv . setType ( types . NewTuple ( newVar ( " " , x . Type ( ) . Underlying ( ) . ( * types . Chan ) . Elem ( ) ) , varOk , ) ) ko := fn . emit ( recv ) body := fn . newBasicBlock ( " " ) done = fn . newBasicBlock ( " " ) emitIf ( fn , emitExtract ( fn , ko , 1 ) , body , done ) fn . currentBlock = body if tk != nil { k = emitExtract ( fn , ko , 0 ) } return }
// rangeChan emits to fn the header for a loop that receives from
// channel x until it fails.
// tk is the channel's element type, or nil if the k result is
// not wanted
// pos is the position of the '=' or ':=' token.
//
rangeChan emits to fn the header for a loop that receives from channel x until it fails . tk is the channel s element type or nil if the k result is not wanted pos is the position of the = or : = token .