Dart: Fluxo de Controle no Dart

Última atualização: 2026-08-26

O fluxo de controle é o cérebro do seu código — ele determina qual caminho seu programa segue e quantas vezes.

1. O que Você Aprenderá


2. A História Real de um Desenvolvedor

(1) Dor: if-else Aninhados Tornam o Código Inmanutenível

Alice estava processando dados de pedidos de e-commerce e escreveu uma estrutura if-else de três níveis para filtrar e classificar pedidos. A lógica era: primeiro verificar o status do pedido, depois verificar a faixa de valor, e finalmente verificar o método de pagamento. Uma "pirâmide" de código de 300 linhas exigia que ela entendesse toda a lógica a cada modificação. Uma alteração esquecida causou um erro nos cálculos de desconto de pedidos VIP, resultando em uma perda direta de $15.000 USD.

(2) A Solução: Melhores Práticas de Fluxo de Controle

Usando a switch expression do Dart 3 para substituir o if-else aninhado, e usando for-in para substituir a iteração baseada em índice, o código foi reduzido de 300 linhas para 80 linhas, tornando a lógica clara e manutenível.

DART
// Antes: pirâmide de if-else aninhado
// Depois: switch expression limpa
String classifyOrder(Order order) => switch ((order.status, order.amount)) {
  ('pending', > 1000) => 'VIP Pendente',
  ('pending', _) => 'Normal Pendente',
  ('shipped', _) => 'Em Trânsito',
  ('delivered', _) => 'Concluído',
  _ => 'Desconhecido',
};
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

(3) Benefícios


3. Declarações Condicionais if-else

(1) Sintaxe Básica

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

: Uso Básico do if-else

DART
void main() {
  double orderAmount = 1500.0;

  if (orderAmount > 1000) {
    print('Pedido VIP - aplicar desconto');
  } else if (orderAmount > 500) {
    print('Pedido padrão');
  } else {
    print('Pedido pequeno');
  }
}
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

: if-else como Expressão (Alternativa ao Operador Ternário)

DART
void main() {
  int orderCount = 1500;

  // Operador ternário
  String tier = orderCount >= 1000 ? 'Enterprise' : 'Standard';

  // if-else como expressão (Dart 3)
  String label = if (orderCount >= 1000) 'Enterprise' else 'Standard';

  print('Nível: $tier');
  print('Rótulo: $label');
}
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.
Forma Sintaxe Retorna Valor Versão do Dart
Declaração if if (cond) { ... } Não Todas as versões
Operador Ternário cond ? a : b Sim Todas as versões
Expressão if if (cond) a else b Sim Dart 3.7+

4. switch e switch Expressions

(1) Declaração switch Tradicional

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

: Declaração switch

DART
void main() {
  String status = 'shipped';

  switch (status) {
    case 'pending':
      print('Pedido aguardando processamento');
      break;
    case 'shipped':
      print('Pedido em trânsito');
      break;
    case 'delivered':
      print('Pedido foi entregue');
      break;
    default:
      print('Status desconhecido: $status');
  }
}
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

(2) switch Expressions do Dart 3

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

: switch Expression

DART
// Switch expression - retorna um valor
String getStatusLabel(String status) => switch (status) {
  'pending' => 'Aguardando Processamento',
  'shipped' => 'Em Trânsito',
  'delivered' => 'Concluído',
  'cancelled' => 'Cancelado',
  _ => 'Status Desconhecido',
};

// Pattern matching com guards
String classifyOrder(double amount) => switch (amount) {
  >= 10000 => 'Enterprise',
  >= 1000 => 'Premium',
  > 0 => 'Standard',
  _ => 'Inválido',
};

void main() {
  print(getStatusLabel('shipped'));    // Em Trânsito
  print(classifyOrder(5500));          // Premium
  print(classifyOrder(150));           // Standard
}
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.
Aspecto Declaração switch switch Expression
Retorna Valor Não Sim
break Obrigatório Não necessário
Sintaxe case x: x =>
Versão do Dart Todas Dart 3+
Verificação de Exaustividade Não Sim (sealed class)

5. Estruturas de Loop

(1) Loop for

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

: Loop for Tradicional

DART
void main() {
  // Loop for clássico
  for (int i = 0; i < 5; i++) {
    print('Processando lote ${i + 1}');
  }

  // Contagem regressiva
  for (int i = 10; i > 0; i -= 2) {
    print('Contagem regressiva: $i');
  }
}
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

(2) Loop for-in

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

: Travessia com for-in

DART
void main() {
  List<String> sources = ['orders.csv', 'products.csv', 'customers.csv'];

  // for-in com List
  for (final source in sources) {
    print('Carregando: $source');
  }

  // for-in com Set
  Set<String> uniqueStatuses = {'pending', 'shipped', 'delivered'};
  for (final status in uniqueStatuses) {
    print('Status: $status');
  }

  // for-in com entradas de Map
  Map<String, int> categoryCount = {
    'Eletrônicos': 500,
    'Roupas': 300,
    'Livros': 200,
  };
  for (final entry in categoryCount.entries) {
    print('${entry.key}: ${entry.value} produtos');
  }
}
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

(3) Loops while e do-while

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

: while e do-while

DART
void main() {
  // while - verificar condição primeiro
  int retries = 0;
  bool connected = false;
  while (!connected && retries < 3) {
    print('Tentativa de conexão ${retries + 1}...');
    retries++;
    connected = retries >= 2;  // Sucesso simulado
  }

  // do-while - executar pelo menos uma vez
  int batchSize = 10000;
  int processed = 0;
  do {
    int chunk = (batchSize - processed > 1000) ? 1000 : batchSize - processed;
    print('Processando $chunk registros...');
    processed += chunk;
  } while (processed < batchSize);
}
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.
Tipo de Loop Verificação Inicial Execuções Mínimas Caso de Uso
for Antes da entrada 0 Número conhecido de vezes
for-in Antes da entrada 0 Percorrendo coleções
while Antes da entrada 0 Dirigido por condição
do-while Após execução 1 Deve executar pelo menos uma vez

6. break, continue e Labels

(1) break e continue

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

: break e continue

DART
void main() {
  List<double> amounts = [1500, -50, 3200, 0, 890, -100, 2100];

  // continue - pular pedidos inválidos
  int validCount = 0;
  double totalValid = 0;
  for (final amount in amounts) {
    if (amount <= 0) continue;  // Pular inválidos
    validCount++;
    totalValid += amount;
  }
  print('Válidos: $validCount, Total: $totalValid USD');

  // break - parar no primeiro erro
  for (final amount in amounts) {
    if (amount < 0) {
      print('Erro: Valor negativo $amount encontrado!');
      break;
    }
    print('Processando: $amount USD');
  }
}
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

: Controle com Labels

DART
void main() {
  // Label para controle de loop aninhado
  outer:
  for (int batch = 0; batch < 3; batch++) {
    for (int record = 0; record < 5; record++) {
      if (record == 2 && batch == 1) {
        print('Erro crítico no lote $batch, registro $record');
        break outer;  // Sair de ambos os loops
      }
      print('Lote $batch, Registro $record');
    }
  }
}
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

7. Cenário do Bob: Filtragem de Dados do DataPipeline

100%
flowchart TD
  A[Dados Brutos] --> B{Condição de Filtro}
  B -->|Pedido Válido| C[for-in Iterar]
  B -->|Dados Inválidos| D[continue Pular]
  C --> E[Cálculo de Agregação]
  E --> F[Resultado de Saída]
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

▶ Exemplo

TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

: Filtragem e Agregação de Dados de Pedidos

DART
void main() {
  List<Map<String, dynamic>> rawOrders = [
    {'id': 'ORD-001', 'amount': 1500.0, 'status': 'completed'},
    {'id': 'ORD-002', 'amount': -50.0, 'status': 'completed'},
    {'id': 'ORD-003', 'amount': 3200.0, 'status': 'pending'},
    {'id': 'ORD-004', 'amount': 0.0, 'status': 'completed'},
    {'id': 'ORD-005', 'amount': 890.0, 'status': 'completed'},
    {'id': 'ORD-006', 'amount': 2100.0, 'status': 'cancelled'},
  ];

  double totalRevenue = 0;
  int completedCount = 0;
  Map<String, double> revenueByStatus = {};

  for (final order in rawOrders) {
    final amount = order['amount'] as double;
    final status = order['status'] as String;

    // Pular pedidos inválidos
    if (amount <= 0) continue;

    // Pular pedidos cancelados
    if (status == 'cancelled') continue;

    // Agregar receita por status
    revenueByStatus[status] = (revenueByStatus[status] ?? 0) + amount;

    // Contar concluídos
    if (status == 'completed') {
      completedCount++;
      totalRevenue += amount;
    }
  }

  print('=== Relatório de Filtro do DataPipeline ===');
  print('Pedidos concluídos: $completedCount');
  print('Receita total: \$${totalRevenue.toStringAsFixed(2)} USD');
  for (final entry in revenueByStatus.entries) {
    print('  ${entry.key}: \$${entry.value.toStringAsFixed(2)} USD');
  }
}
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

8. Exemplo Completo: Controlador de Processamento em Lote do DataPipeline

DART
// ============================================
// Controlador de Processamento em Lote do DataPipeline
// Usa todas as estruturas de fluxo de controle
// ============================================

class BatchProcessor {
  final int batchSize;
  int processedCount = 0;
  int skippedCount = 0;
  double totalRevenue = 0;

  BatchProcessor({this.batchSize = 1000});

  String classifyAmount(double amount) => switch (amount) {
    >= 10000 => 'Enterprise',
    >= 1000 => 'Premium',
    > 0 => 'Standard',
    _ => 'Inválido',
  };

  void processBatch(List<Map<String, dynamic>> orders) {
    int batchNum = 0;

    for (int i = 0; i < orders.length; i += batchSize) {
      batchNum++;
      final end = (i + batchSize < orders.length) ? i + batchSize : orders.length;
      final batch = orders.sublist(i, end);

      print('\n--- Lote $batchNum (${batch.length} registros) ---');

      for (final order in batch) {
        final id = order['id'] as String?;
        final amount = order['amount'] as double?;
        final status = order['status'] as String?;

        // Pular registros inválidos
        if (id == null || amount == null || status == null) {
          skippedCount++;
          continue;
        }

        if (amount <= 0) {
          skippedCount++;
          continue;
        }

        final tier = classifyAmount(amount);

        if (status == 'completed') {
          processedCount++;
          totalRevenue += amount;
          print('  $id: \$${amount.toStringAsFixed(2)} USD [$tier]');
        } else if (status == 'pending') {
          print('  $id: PENDENTE - \$${amount.toStringAsFixed(2)} USD [$tier]');
        } else {
          skippedCount++;
        }
      }
    }
  }

  void printSummary() {
    print('\n=== Resumo do Processamento ===');
    print('Processados: $processedCount pedidos');
    print('Ignorados:   $skippedCount registros');
    print('Receita:     \$${totalRevenue.toStringAsFixed(2)} USD');
  }
}

void main() {
  final orders = <Map<String, dynamic>>[
    {'id': 'ORD-001', 'amount': 1500.0, 'status': 'completed'},
    {'id': 'ORD-002', 'amount': 15500.0, 'status': 'completed'},
    {'id': 'ORD-003', 'amount': -50.0, 'status': 'completed'},
    {'id': 'ORD-004', 'amount': 890.0, 'status': 'pending'},
    {'id': 'ORD-005', 'amount': 3200.0, 'status': 'completed'},
    {'id': 'ORD-006', 'amount': 0.0, 'status': 'cancelled'},
  ];

  final processor = BatchProcessor(batchSize: 3);
  processor.processBatch(orders);
  processor.printSummary();
}
TEXT 📖 Somente leitura
> **Saída:** Execute em seu DartPad local ou com `dart run`. Todos os exemplos do curso Dart são baseados em Dart 3.x / Flutter 3.x. Os resultados podem variar ligeiramente dependendo da versão do SDK.

Saída:

TEXT 📖 Somente leitura
--- Lote 1 (3 registros) ---
  ORD-001: $1500.00 USD [Premium]
  ORD-002: $15500.00 USD [Enterprise]
--- Lote 2 (3 registros) ---
  ORD-004: PENDENTE - $890.00 USD [Standard]
  ORD-005: $3200.00 USD [Premium]

=== Resumo do Processamento ===
Processados: 3 pedidos
Ignorados:   3 registros
Receita:     $20200.00 USD

❓ Perguntas Frequentes

P: O break é obrigatório em declarações switch? R: Sim, na declaração switch do Dart, cada case não vazio deve terminar com break, return, throw ou continue. Não há fall-through. No entanto, um case vazio pode fazer fall-through.

P: O que é o _ em uma switch expression? R: _ é um padrão curinga que corresponde a todos os casos restantes, equivalente ao default em uma declaração switch. O Dart 3 recomenda usar _ em vez de default.

P: O for-in pode modificar uma coleção? R: Não. Modificar uma coleção (adicionar/remover elementos) durante uma travessia for-in causará um ConcurrentModificationError. Se modificação for necessária, colete as mudanças primeiro e aplique-as depois.

P: Quando devo usar while em vez de for? R: Use while quando o número de iterações é incerto (ex: esperando uma resposta de rede). Use for/for-in quando o número de iterações é conhecido ou há uma coleção clara para percorrer.

P: Labels são comumente usados no desenvolvimento real? R: Não muito. break/continue com labels é usado principalmente para controle preciso em loops aninhados. Na maioria dos casos, aninhamento profundo pode ser evitado através de refatoração (extração de métodos, uso de funções de ordem superior).

P: A switch expression do Dart 3 suporta matching de múltiplos valores? R: Sim. Você pode usar | para combinar múltiplos padrões, como 'pending' | 'processing' => 'Em Andamento'.

P: Há diferença de desempenho entre do-while e while? R: Não há diferença de desempenho perceptível. A escolha depende da semântica: se o corpo do loop precisa executar pelo menos uma vez.


📖 Resumo


📝 Exercícios

  1. Básico (Dificuldade ⭐): Use for-in para percorrer uma List contendo 5 valores de pedidos. Calcule o total e a média, pulando pedidos com valor menor ou igual a 0.
  2. Intermediário (Dificuldade ⭐⭐): Use uma switch expression para implementar um classificador de status de pedidos que retorna diferentes rótulos de prioridade de processamento com base na combinação de (status, valor).
  3. Desafio (Dificuldade ⭐⭐⭐): Implemente um processador em lote paginado que processa N registros por lote, suporta interrupção com break (ao encontrar erro severo) e salto com continue (para registros inválidos), e gera um relatório final de estatísticas de processamento.

← Aula Anterior | Próxima Aula →

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%