Um método é uma função com um argumento especial, o recetor.
O recetor aparece na sua própria lista de argumentos, entre a palavra-chave func e o nome do método.
func (receiver type) MethodName(parameters) (returnTypes) {
}
Só podes definir um método com um recetor cujo tipo esteja definido no mesmo pacote que o método.
package person
type Person struct {
Name string
}
func (p Person) Greetings() string {
return fmt.Sprintf("Welcome %s!", p.Name)
}
O método do tipo struct pode ser chamado com a notação de ponto.
p := Person{Name: "Bronson"}
fmt.Println(p.Greetings())
// Output: Welcome Bronson!
Repara como chamámos o método Greetings() à instância p de Person.
É exatamente como chamas métodos numa linguagem de programação orientada a objetos.
Lembra-te: um método é apenas uma função com um argumento recetor. Os métodos ajudam a evitar conflitos de nomes, pois, como um método está associado a um tipo de recetor específico, podes ter o mesmo nome de método em tipos diferentes.
import "math"
type rect struct {
width, height int
}
func (r rect) area() int {
return r.width * r.height
}
type circle struct {
radius int
}
func (c circle) area() float64 {
return math.Pow(float64(c.radius), 2) * math.Pi
}
Há dois tipos de recetores: os recetores de valor e os recetores de ponteiro.
Todos os métodos que vimos até agora têm um recetor de valor, o que significa que recebem uma cópia do valor passado ao método. Por outras palavras, qualquer modificação feita ao recetor dentro do método não é visível para quem o chama.
Podes declarar métodos com recetores de ponteiro para modificar o valor para o qual o recetor aponta.
Para isso, coloca um * antes do nome do tipo.
Por exemplo, com o tipo rect, um recetor de ponteiro seria declarado como *rect.
Essas modificações também são visíveis para quem chama o método.
type rect struct {
width, height int
}
func (r *rect) squareIt() {
r.height = r.width
}
r := rect{width: 10, height: 20}
fmt.Printf("Width: %d, Height: %d\n", r.width, r.height)
// Output: Width: 10, Height: 20
r.squareIt()
fmt.Printf("Width: %d, Height: %d\n", r.width, r.height)
// Output: Width: 10, Height: 10
Nota: Este exercício é uma continuação do exercício need-for-speed.
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%). Cada vez que conduzes o carro com o telecomando, ele percorre em metros uma distância igual à velocidade do carro e a percentagem de bateria restante diminui 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.
O carro telecomandado tem um ecrã LED sofisticado que mostra duas informações:
"Driven <METERS> meters"."Battery at <PERCENTAGE>%".Cada pista tem a sua própria distância. Os carros são testados verificando se conseguem terminar a pista sem ficar sem bateria.
Implementa o método Drive no Car, 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:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
car.Drive()
// car is now Car{speed: 5, batteryDrain: 2, battery: 98, distance: 5}
Nota: Não deves tentar conduzir o carro se isso fizer com que a bateria do carro fique abaixo de 0.
Implementa um método DisplayDistance no Car para devolver a distância tal como é apresentada no ecrã LED, como string:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
fmt.Println(car.DisplayDistance())
// Output: "Driven 0 meters"
Implementa o método DisplayBattery no Car para devolver a percentagem da bateria tal como é apresentada no ecrã LED, como string:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
fmt.Println(car.DisplayBattery())
// Output: "Battery at 100%"
Para terminar uma corrida, um carro tem de conseguir percorrer a distância da corrida.
Isto significa não ficar sem bateria antes de cruzar a linha de chegada.
Implementa o método CanFinish, que recebe um trackDistance int como parâmetro e devolve true se o carro conseguir terminar a corrida; caso contrário, devolve false:
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
trackDistance := 100
car.CanFinish(trackDistance)
// => true
Inscreve-te no Exercism para aprenderes e dominares Go com 34 conceitos166 exercícios, e mentoria humana real, tudo grátis.