Dart basics
last modified May 30, 2026
In this article we cover the basic programming concepts of Dart language.
Dart is a client-optimized language for fast applications on any platform. It is used to build mobile, desktop, server, and web applications.
Dart simple example
The following is a simple example in Dart.
void main() {
print('First program in Dart');
}
The program prints a message to the console. Dart programs have the
main.dart extension. The main function is the entry point
to the program. The body of the function is enclosed in a pair of curly brackets.
The print function displays a message in console. The statements
are terminated with a semicolon.
$ dart main.dart First program in Dart
We run the program.
Dart comments
Comments are used by humans to clarify source code. There are three types of comments in Dart: single line comments (//), multi-line comments (/* */), and documentation comments (///).
Documentation comments are used to produce documentation by
dartdoc. They are used also by IDEs.
/*
This is main.dart
Author: Jan Bodnar
ZetCode 2023
*/
// Program starts here
void main() {
print("This is a Dart program");
}
In the example, we have a multi-line and a single line comment. Comments are ignored by the compiler.
Dart variables
Variables store references to values. Every value is an object -- an instance of a class.
void main() {
String name = 'John Doe';
int age = 34;
double height = 172.5;
print('$name is $age years old; his height is $height cm');
}
In the example, we have three variables: a string, an integer, and a double
variable. The data type of the variables are explicitly specified with
String, int, and double.
String name = 'John Doe';
We can create string literals both with single and double quotes.
print('$name is $age years old; his height is $height cm');
Dart supports variable interpolation in strings. The variables preceded with
the $ character are evaluated to their values inside strings.
$ dart main.dart John Doe is 34 years old; his height is 172.5
Dart var keyword
When we use the var keyword, the compiler infers the data type of
a variable from the right side of the assignment.
void main() {
var name = 'John Doe';
var age = 34;
var height = 172.5;
print('$name is $age years old; his height is $height cm');
print(name.runtimeType);
print(age.runtimeType);
print(height.runtimeType);
}
The data types of the three variables are inferred by the compiler.
print(name.runtimeType); print(age.runtimeType); print(height.runtimeType);
We can use the runtimeType attribute to get the data type of a
variable.
$ dart main.dart John Doe is 34 years old; his height is 172.5 cm String int double
Dart dynamic keyword
With the dynamic keyword, we can declare a dynamically typed
variable. We can assign values of different data types to the same variable.
void main() {
dynamic n = 3;
print(n);
n = 'three';
print(n);
}
In the example, we first assign value 3 to the n variable; later,
we assign the string value 'three'.
$ dart main.dart 3 three
Dart final and const
The final keyword declares a variable that can be set only once.
The const keyword creates a compile-time constant. Both produce
immutable values, but const is evaluated at compile time while
final is evaluated at runtime.
void main() {
final name = 'John Doe';
const pi = 3.14159;
print(name);
print(pi);
final now = DateTime.now();
print(now);
}
The name is a final variable and pi is a
const variable. Because DateTime.now() is computed at
runtime, it must be final, not const.
$ dart main.dart John Doe 3.14159 2025-05-30 10:15:23.456789
Dart null safety
Dart has sound null safety: variables cannot hold null by default. Append
? to a type to allow null. The ?? operator returns
the right side when the left side is null. The null-aware operator
?. calls a method only if the object is non-null.
void main() {
String? city;
print(city);
city = 'London';
print(city);
String? country;
var label = country ?? 'unknown';
print(label);
String? msg = 'Hello world';
print(msg?.toUpperCase());
print(msg?.length);
}
We demonstrate the core null safety features of Dart.
String? city; print(city);
A nullable String? variable is null by default.
Printing it outputs the literal null.
var label = country ?? 'unknown';
The ?? null-coalescing operator returns the right operand when the
left operand is null.
print(msg?.toUpperCase());
The ?. null-aware access operator calls the method only if the
object is non-null; if null, the whole expression evaluates to null.
$ dart main.dart null London unknown HELLO WORLD 11
Dart user input
The dart:io library provides file, socket, HTTP, and other I/O
support for non-web applications.
import 'dart:io';
void main() {
stdout.write("Enter your name: ");
var name = stdin.readLineSync() ?? '';
print('Hello $name\n');
}
The example prompts the user for his name and prints a message.
stdout.write("Enter your name: ");
We can use the stdout.write function to write to the console
without a newline character.
var name = stdin.readLineSync() ?? '';
We read the user input with stdin.readLineSync. The ??
operator provides an empty string as a fallback if the method returns null.
$ dart main.dart Enter your name: Peter Hello Peter
Dart conditionals
Conditionals are created with the if, else if, and
else keywords.
import 'dart:io';
void main() {
stdout.write("Enter a number: ");
var input = stdin.readLineSync() ?? '';
var n = int.parse(input);
if (n > 0) {
print('$n is a positive value');
} else if (n == 0) {
print('$n is zero');
} else {
print('$n is a negative value');
}
}
In the example, we ask for a number from the user. Depending on the received value, we print a message to the console.
var n = int.parse(input);
Since the readLineSync returns a string, we transform the string
to a number with int.parse.
if (n > 0) {
print('$n is a positive value');
} else if (n == 0) {
print('$n is zero');
} else {
print('$n is a negative value');
}
After the if keyword, we place the condition between two round
brackets. If the condition is true, the body of the if statement is executed.
Other branches are skipped. If the condition is false, the compiler tests the
condition after the else if statement. If it is true, the following
body is executed. If both conditions fail, the body after the else
statement is executed.
$ dart main.dart Enter a number: 4 4 is a positive value $ dart main.dart Enter a number: -4 -4 is a negative value $ dart main.dart Enter a number: 0 0 is zero
Dart switch
The switch statement evaluates an expression and executes the
matching case block. Dart 3 also introduced switch expressions
that evaluate to a value using the arrow => syntax.
void main() {
var dayNum = 3;
switch (dayNum) {
case 1:
print('Monday');
break;
case 2:
print('Tuesday');
break;
case 3:
print('Wednesday');
break;
case 4:
print('Thursday');
break;
case 5:
print('Friday');
break;
default:
print('Weekend');
}
var dayName = switch (dayNum) {
1 => 'Monday',
2 => 'Tuesday',
3 => 'Wednesday',
4 => 'Thursday',
5 => 'Friday',
_ => 'Weekend',
};
print(dayName);
}
We use both the classic switch statement and the Dart 3 switch expression.
switch (dayNum) {
case 3:
print('Wednesday');
break;
...
default:
print('Weekend');
}
Each case value is compared against the switch expression. The
break statement prevents fall-through to the next case. The
default clause executes when no case matches.
var dayName = switch (dayNum) {
1 => 'Monday',
...
_ => 'Weekend',
};
The switch expression introduced in Dart 3 evaluates to a value. Each arm uses
the => arrow. The _ wildcard matches any remaining
value.
$ dart main.dart Wednesday Wednesday
Dart Exception
Exceptions are errors indicating that something unexpected happened.
Exceptions are processed with try, on, and
catch keywords.
import 'dart:io';
void main() {
stdout.write("Enter a number: ");
var input = stdin.readLineSync() ?? '';
late int n;
try {
n = int.parse(input);
} on FormatException {
print('wrong value');
return;
}
if (n > 0) {
print('$n is a positive value');
} else if (n == 0) {
print('$n is zero');
} else {
print('$n is a negative value');
}
}
In the example, we handle the case when the user does not enter a valid number value.
late int n;
The late modifier tells the compiler that the variable will be
initialized later, before it is used. This allows us to declare the variable
before the try block and assign it inside the block.
try {
n = int.parse(input);
} on FormatException {
print('wrong value');
return;
}
The error prone code is placed in the body of the try statement.
The FormatException is thrown when a string or some other data does
not have an expected format and cannot be parsed or processed.
$ dart main.dart Enter a number: 4 4 is a positive value $ dart main.dart Enter a number: f wrong value
Dart while loop
The while statement is a control flow statement that allows code to
be executed repeatedly based on a given boolean condition.
The while keyword executes the statements inside the block enclosed
by the curly brackets. The statements are executed each time the expression is
evaluated to true.
void main() {
int i = 0;
int sum = 0;
while (i <= 10) {
sum += i;
i++;
}
print(sum);
}
In the code example, we calculate the sum of values from a range of numbers.
The while loop has three parts. Initialization, testing and
updating. Each execution of the statement is called a cycle.
int i = 0;
We initiate the i variable. It is used as a counter.
while (i <= 10) {
...
}
The expression inside the round brackets following the while
keyword is the second phase, the testing. The statements in the body are
executed until the expression is evaluated to false.
sum += i;
We add the current value of i to the sum variable.
i++;
This is the last, third phase of the while loop, the updating. We
increment the counter. Note that improper handling of the while
loops may lead to endless cycles.
$ dart main.dart 55
Dart for loop
We can do loops with the for statement. There are two for loops
in Dart: the classic for loop and the for range loop.
void main() {
var sum = 0;
for (var i = 0; i < 10; i++) {
sum += i;
}
print(sum);
var vals = [1, 2, 3, 4, 5];
for (var e in vals) {
print(e * e);
}
}
In the example, we use both for loops.
var sum = 0;
for (var i = 0; i < 10; i++) {
sum += i;
}
We calculate the sum of values 0..9 with the classic for loop. There are three phases. In the first phase, we initiate the counter i to zero. This phase is done only once. Next comes the condition. If the condition is met, the statement inside the for block is executed. In the third phase the counter is increased. Now we repeat the 2, 3 phases until the condition is not met and the for loop is left. In our case, when the counter i is equal to 10, the for loop stops executing.
var vals = [1, 2, 3, 4, 5];
for (var e in vals) {
print(e * e);
}
In the second form, we go through the elements of a list one by one. We square all the values of the list.
$ dart main.dart 45 1 4 9 16 25
Dart functions
Functions are named blocks of code that perform a specific task. Dart supports regular functions, arrow functions, and functions with named or optional parameters.
int add(int a, int b) {
return a + b;
}
double circleArea(double r) => 3.14159 * r * r;
String greet({required String name, String greeting = 'Hello'}) {
return '$greeting, $name!';
}
void main() {
print(add(3, 4));
print(circleArea(5.0));
print(greet(name: 'Alice'));
print(greet(name: 'Bob', greeting: 'Hi'));
}
We define three functions and call them from main.
int add(int a, int b) {
return a + b;
}
The add function takes two integer parameters and returns their sum.
The return type is declared before the function name.
double circleArea(double r) => 3.14159 * r * r;
The arrow syntax => is a shorthand for a single-expression
function body.
String greet({required String name, String greeting = 'Hello'}) {
Named parameters are enclosed in curly braces. The required keyword
marks a parameter as mandatory. Parameters with default values are optional.
$ dart main.dart 7 78.53975 Hello, Alice! Hi, Bob!
Dart lists
A list is an ordered collection of objects. Dart lists are instances of the
List class and are created with list literals using square brackets.
void main() {
var nums = [1, 2, 3, 4, 5];
print(nums);
print(nums.length);
print(nums.first);
print(nums.last);
print(nums[2]);
nums.add(6);
nums.remove(3);
print(nums);
var doubled = nums.map((e) => e * 2).toList();
print(doubled);
var evens = nums.where((e) => e % 2 == 0).toList();
print(evens);
}
We create a list of integers and perform various operations on it.
print(nums.length); print(nums.first); print(nums.last); print(nums[2]);
We access the list length, the first and last elements, and an element by index. List indices start at zero.
var doubled = nums.map((e) => e * 2).toList();
The map method transforms each element using a function and returns
an iterable. We convert it to a list with toList.
var evens = nums.where((e) => e % 2 == 0).toList();
The where method filters elements based on a predicate.
$ dart main.dart [1, 2, 3, 4, 5] 5 1 5 3 [1, 2, 4, 5, 6] [2, 4, 8, 10, 12] [2, 4, 6]
Dart maps
A map is an unordered collection of key-value pairs. Keys must be unique. Maps
are instances of the Map class and are created with map literals
using curly braces.
void main() {
var person = {
'name': 'John Doe',
'age': 34,
'city': 'New York',
};
print(person);
print(person['name']);
print(person.length);
person['email'] = 'john@example.com';
person.remove('city');
print(person.keys.toList());
print(person.values.toList());
person.forEach((key, value) {
print('$key: $value');
});
}
We create a map representing a person and perform common operations on it.
print(person['name']);
A map value is accessed by its key inside square brackets. If the key does not
exist, null is returned.
person['email'] = 'john@example.com';
person.remove('city');
We add a new key-value pair by assignment and remove an entry with
remove.
person.forEach((key, value) {
print('$key: $value');
});
The forEach method iterates over all key-value pairs.
$ dart main.dart
{name: John Doe, age: 34, city: New York}
John Doe
3
[name, age, email]
[John Doe, 34, john@example.com]
name: John Doe
age: 34
email: john@example.com
Dart command line arguments
Dart programs can receive command line arguments. They follow the name of the program when we run it.
void main(List<String> args) {
for (var val in args) {
print(val);
}
print('---------');
for (int i = 0; i < args.length; i++) {
print(args[i]);
}
}
We receive the arguments in the args list. We go through the
arguments with the classic and the range for loops.
$ dart main.dart 1 2 3 4 1 2 3 4 --------- 1 2 3 4
Source
This was an introduction to the Dart programming language.
Author
List all Dart tutorials.