Skip to content

Commit ff3f12e

Browse files
authored
doc: update the defer{} section, describe defer(fn){} (#25669)
1 parent be82b03 commit ff3f12e

File tree

1 file changed

+56
-8
lines changed

1 file changed

+56
-8
lines changed

doc/docs.md

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,25 +2301,27 @@ The above code prints:
23012301

23022302
### Defer
23032303

2304-
A defer statement defers the execution of a block of statements
2305-
until the surrounding function returns.
2304+
A `defer {}` statement, defers the execution of the block of statements
2305+
until the surrounding scope of the defer ends. It is a convenient feature
2306+
that allows you to group related actions (getting access to a resource
2307+
and cleaning/freeing it after you are done) closely together, instead
2308+
of spreading them across multiple potentially very remote lines of code.
23062309

23072310
```v
23082311
import os
23092312
2310-
fn read_log() {
2313+
fn read_log() ! {
23112314
mut ok := false
2312-
mut f := os.open('log.txt') or { panic(err) }
2313-
defer {
2314-
f.close()
2315-
}
2315+
mut f := os.open('log.txt')!
2316+
defer { f.close() }
23162317
// ...
23172318
if !ok {
2319+
// ...
23182320
// defer statement will be called here, the file will be closed
23192321
return
23202322
}
23212323
// ...
2322-
// defer statement will be called here, the file will be closed
2324+
// defer statement will be called here too, the file will be closed
23232325
}
23242326
```
23252327

@@ -2402,6 +2404,52 @@ fn (mut app App) auth_with_user_middleware() (bool, string) {
24022404
}
24032405
```
24042406

2407+
#### defer in loop scopes:
2408+
Defer can be used inside loops too, and the deferred statement will be executed once for each
2409+
iteration. You can also have multiple defer statements in the same scope, in which case, they
2410+
will be executed in reverse order of their appearance in the source code:
2411+
```v
2412+
fn main() {
2413+
defer { println('Program finish.') }
2414+
println('Loop start.')
2415+
for i in 1 .. 4 {
2416+
defer { println('Deferred execution for ${i}. Defer 1.') }
2417+
defer { println('Deferred execution for ${i}. Defer 2.') }
2418+
defer { println('Deferred execution for ${i}. Defer 3.') }
2419+
println('Loop iteration: ${i}')
2420+
}
2421+
println('Loop done.')
2422+
}
2423+
```
2424+
2425+
The example will print this:
2426+
```txt
2427+
Loop start.
2428+
Loop iteration: 1
2429+
Deferred execution for 1. Defer 3.
2430+
Deferred execution for 1. Defer 2.
2431+
Deferred execution for 1. Defer 1.
2432+
Loop iteration: 2
2433+
Deferred execution for 2. Defer 3.
2434+
Deferred execution for 2. Defer 2.
2435+
Deferred execution for 2. Defer 1.
2436+
Loop iteration: 3
2437+
Deferred execution for 3. Defer 3.
2438+
Deferred execution for 3. Defer 2.
2439+
Deferred execution for 3. Defer 1.
2440+
Loop done.
2441+
Program finish.
2442+
```
2443+
2444+
#### defer(fn) {}
2445+
2446+
Note, that in most of the examples above, the `defer{}` statement was directly inside
2447+
a function scope, so it was executed when the function itself returned. Sometimes, you
2448+
need to defer a statement to execute right at the function end (like the above), even
2449+
if you are inside an inner scope (deep inside an `if` or `for`).
2450+
2451+
For these more rare cases, you can use: `defer(fn) {}` instead of just `defer {}`.
2452+
24052453
### Goto
24062454

24072455
V allows unconditionally jumping to a label with `goto`. The label name must be contained

0 commit comments

Comments
 (0)