Concluindo uma Tarefa
Parte da seção Lógica & Fluxo do Journey de GO da Coddy — lição 23 de 68.
Desafio
FácilNesta parte do seu sistema de gerenciamento de tarefas, você implementará a capacidade de marcar tarefas como concluídas. Este desafio foca no uso de receptores de ponteiro para modificar os dados originais da tarefa, demonstrando como os ponteiros permitem que você atualize campos de structs permanentemente.
Nota Importante: Como os nomes das tarefas podem conter espaços (como "Buy groceries"), você precisará usar bufio.Scanner para ler linhas inteiras de entrada. A função fmt.Scanf para de ler no primeiro espaço, o que quebraria nomes de tarefas com espaços. Use bufio.NewScanner(os.Stdin) e chame scanner.Scan() seguido de scanner.Text() para ler linhas completas.
Você receberá três entradas:
- Uma string representando o número de tarefas (ex:
"4") - Uma string contendo os dados das tarefas no formato:
"name1:status1,name2:status2,name3:status3"onde o status é"true"ou"false"(ex:"Buy groceries:false,Call dentist:true,Finish project:false,Review code:false") - Uma string representando o índice da tarefa a ser concluída (ex:
"2"para a terceira tarefa, usando indexação baseada em 0)
Sua tarefa é:
- Definir a mesma struct
Taskdos desafios anteriores com os camposName(string) eCompleted(bool) - Criar uma função chamada
completeTaskque recebe um ponteiro para um slice de structsTaske um índice (int) como parâmetros - Dentro da função
completeTask, modifique o campoCompletedda tarefa no índice fornecido paratrue - Usar
bufio.Scannerpara ler as linhas de entrada corretamente:- Criar um scanner:
scanner := bufio.NewScanner(os.Stdin) - Para cada linha de entrada: chame
scanner.Scan()e depoisscanner.Text() - Isso garante que nomes de tarefas com espaços sejam lidos corretamente
- Criar um scanner:
- Analisar os dados das tarefas da segunda entrada para criar seu slice de tarefas:
- Dividir a entrada por vírgulas para obter as entradas de tarefas individuais
- Para cada entrada, dividir por dois-pontos para separar o nome e o status
- Converter a string de status para um booleano (
"true"torna-setrue,"false"torna-sefalse)
- Converter a terceira string de entrada em um inteiro para obter o índice da tarefa
- Chamar sua função
completeTaskcom um ponteiro para seu slice e o índice - Após concluir a tarefa, exibir todas as tarefas usando o mesmo formato do desafio anterior:
- Para tarefas concluídas:
"[x] [task_name]" - Para tarefas incompletas:
"[ ] [task_name]"
- Para tarefas concluídas:
- Imprimir uma mensagem de confirmação:
"Task '[task_name]' marked as completed!" - Imprimir o resumo atualizado:
"Total: [total_count] tasks ([completed_count] completed, [incomplete_count] remaining)"
Use o pacote strconv para converter a string do índice em um inteiro. Este desafio demonstra como os receptores de ponteiro permitem que você modifique a estrutura de dados original, fazendo alterações permanentes em sua lista de tarefas que persistem após o retorno da função.
Experimente você mesmo
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
type Task struct {
Name string
Completed bool
}
func viewAllTasks(tasks []Task) {
for _, task := range tasks {
if task.Completed {
fmt.Printf("[x] %s\n", task.Name)
} else {
fmt.Printf("[ ] %s\n", task.Name)
}
}
}
func main() {
var numTasksStr string
fmt.Scanln(&numTasksStr)
numTasks, _ := strconv.Atoi(numTasksStr)
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
taskData := scanner.Text()
var tasks []Task
taskEntries := strings.Split(taskData, ",")
for _, entry := range taskEntries {
parts := strings.Split(entry, ":")
if len(parts) >= 2 {
name := parts[0]
completed, _ := strconv.ParseBool(parts[1])
task := Task{
Name: name,
Completed: completed,
}
tasks = append(tasks, task)
}
}
viewAllTasks(tasks)
completedCount := 0
for _, task := range tasks {
if task.Completed {
completedCount++
}
}
incompleteCount := numTasks - completedCount
fmt.Printf("Total: %d tasks (%d completed, %d remaining)\n", numTasks, completedCount, incompleteCount)
}Todas as lições de Lógica & Fluxo
1Fluxo de Controle Avançado
Switch com `fallthrough`Interrompendo Loops AninhadosContinuando um Loop EspecíficoA Instrução `goto`Recapitulação - Controle de Loop Avançado4Projeto: Lista de Tarefas Simples
Configuração do ProjetoAdicionando uma Tarefa2Structs e Métodos
Definindo Métodos em StructsRecebedores de ValorRecebedores de PonteiroEscolhendo RecebedoresMétodos vs FunçõesRecapitulação - Comportamento de Structs5Mapas em Profundidade
Mapas de StructsPonteiros como Valores de MapVerificando Mapas NilComparando MapasRecapitulação - Contador de Frequência de Palavras3Interfaces (O Básico)
O que é uma Interface?Definindo uma InterfaceImplementando uma InterfaceUsando Tipos de InterfaceInterface VaziaAsserções de TipoType SwitchRecapitulação - Formas e Comportamentos