Defer in Dart

In Dart, we can use try-finally blocks to ensure that certain code is executed at the end of a function, similar to the defer keyword in other languages. This is often used for cleanup purposes.

Suppose we wanted to create a file, write to it, and then close when we’re done. Here’s how we could do that in Dart:

import 'dart:io';

void main() {
  final file = createFile('/tmp/defer.txt');
  try {
    writeFile(file);
  } finally {
    closeFile(file);
  }
}

File createFile(String path) {
  print('creating');
  final file = File(path);
  file.createSync();
  return file;
}

void writeFile(File file) {
  print('writing');
  file.writeAsStringSync('data\n');
}

void closeFile(File file) {
  print('closing');
  try {
    file.closeSync();
  } catch (e) {
    stderr.writeln('error: $e');
    exit(1);
  }
}

In this Dart example, we use a try-finally block in the main function. The finally block ensures that closeFile is called after writeFile, regardless of whether an exception occurs or not.

The createFile function creates a new file and returns a File object. The writeFile function writes some data to the file, and closeFile closes the file.

It’s important to check for errors when closing a file, even in a finally block. In our closeFile function, we catch any potential errors and print them to stderr before exiting the program.

Running the program confirms that the file is closed after being written:

$ dart run defer.dart
creating
writing
closing

This approach in Dart achieves a similar result to using defer in other languages, ensuring that cleanup code is executed even if an error occurs in the main body of the function.