Percursos
/
Go
Go
/
Exercícios
/
Need for Speed
Need for Speed

Need for Speed

Exercício de aprendizagem

Introdução

Em Go, um struct é uma sequência de elementos com nome chamados campos; cada campo tem um nome e um tipo. O nome de um campo tem de ser único dentro do struct. Os structs podem ser comparados às classes do paradigma da programação orientada a objetos.

Definir um struct

Crias um novo struct com as palavras-chave type e struct e defines explicitamente o nome e o tipo dos campos. Por exemplo, aqui definimos o struct Shape, que guarda o nome de uma forma e o seu tamanho:

type Shape struct {
    name string
    size int
}

Os nomes dos campos nos structs seguem a convenção de Go: os campos cujo nome começa com uma letra minúscula só são visíveis para o código do mesmo pacote, enquanto os que começam com uma letra maiúscula são visíveis noutros pacotes.

Criar instâncias de um struct

Depois de definires o struct, tens de criar uma nova instância, indicando os campos pelo respetivo nome, por qualquer ordem:

s := Shape {
    name: "Square",
    size: 25,
}

Para leres ou alterares os campos de uma instância, usa a notação .:

// Update the name and the size
s.name = "Circle"
s.size = 35
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 35

Os campos que não tenham um valor inicial atribuído ficam com o seu valor zero. Por exemplo:

s := Shape{name: "Circle"}
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 0

Podes criar uma instância de um struct sem usares os nomes dos campos, desde que os definas por ordem:

s := Shape {
	"Oval",
	20,
}

No entanto, esta sintaxe é considerada código frágil, porque pode quebrar-se quando se acrescenta um campo, sobretudo se o novo campo for de um tipo diferente. No exemplo seguinte, acrescentamos um campo extra ao Shape:

type Shape struct {
	name        string
	description string // new field 'description' added
	size        int
}

s := Shape{
    "Circle",
    20,
}
// Since the second field of the struct is now a string and not an int,
// the compiler will throw an error when compiling the program:
// Output: cannot use 20 (type untyped int) as type string in field value
// Output: too few values in Shape{...}

Funções "New"

Por vezes, é útil ter funções que nos ajudem a criar instâncias de structs. Por convenção, estas funções chamam-se normalmente New ou têm nomes que começam por New, mas, como são apenas funções normais, podes dar-lhes o nome que quiseres. Podem fazer-te lembrar os construtores de outras linguagens, mas em Go são apenas funções normais.

No exemplo seguinte, uma destas funções New é usada para criar uma nova instância de Shape e definir automaticamente um valor predefinido para o size da forma:

func NewShape(name string) Shape {
	return Shape{
		name: name,
		size: 100, //default-value for size is 100
	}
}

NewShape("Triangle")
// => Shape { name: "Triangle", size: 100 }

Usar funções New pode trazer as seguintes vantagens:

  • validação dos valores dados
  • gestão de valores predefinidos
  • como as funções New são frequentemente declaradas no mesmo pacote dos structs que inicializam, podem inicializar até os campos privados do struct

Instruções

Neste exercício vais organizar corridas entre vários tipos de carros telecomandados. Cada carro tem as suas próprias características de velocidade e de consumo de bateria.

Os carros começam com a bateria cheia (100%). Sempre que conduzes o carro com o telecomando, este percorre uma distância em metros igual à velocidade do carro e reduz a percentagem de bateria restante no valor do seu consumo de bateria.

Se a bateria de um carro estiver abaixo da percentagem do seu consumo de bateria, já não podes conduzir o carro.

Cada pista de corrida tem a sua própria distância. Os carros são testados verificando se conseguem terminar a pista sem ficar sem bateria.

1. Cria um carro telecomandado

Define uma struct Car com os seguintes campos do tipo int:

  • battery
  • batteryDrain
  • speed
  • distance

Permite criar um carro telecomandado definindo uma função NewCar que recebe a velocidade do carro em metros e a percentagem de consumo de bateria como os seus dois parâmetros (ambos do tipo int) e devolve uma instância de Car:

speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
// => Car{speed: 5, batteryDrain: 2, battery:100, distance: 0}

2. Cria uma pista de corrida

Define outro tipo de struct chamado Track com o campo distance do tipo inteiro. Permite criar uma pista de corrida definindo uma função NewTrack que recebe a distância da pista em metros como o seu único parâmetro (que é do tipo int):

distance := 800
track := NewTrack(distance)
// => Track{distance: 800}

3. Conduz o carro

Implementa a função Drive, que atualiza o número de metros percorridos com base na velocidade do carro e reduz a bateria de acordo com o consumo de bateria. Se não houver bateria suficiente para conduzir mais uma vez, o carro não avança:

speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
car = Drive(car)
// => Car{speed: 5, batteryDrain: 2, battery: 98, distance: 5}

4. Verifica se um carro telecomandado consegue terminar uma corrida

Para terminar uma corrida, um carro tem de conseguir percorrer a distância da corrida. Isso significa não esgotar a bateria antes de cruzar a linha de chegada. Implementa a função CanFinish, que recebe uma instância de Car e uma de Track como parâmetros e devolve true se o carro conseguir terminar a corrida; caso contrário, devolve false.

Assume que estás na linha de partida da corrida e ligas o motor do carro para a corrida. Tem em conta que a bateria do carro pode não estar totalmente carregada quando a corrida começa:

speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)

distance := 100
track := NewTrack(distance)

CanFinish(car, track)
// => true
Editar via GitHub A ligação abre numa nova janela ou separador
Go Exercism

Estás pronto para começar Need for Speed?

Inscreve-te no Exercism para aprenderes e dominares Go com 34 conceitos165 exercícios, e mentoria humana real, tudo grátis.