diff --git a/pt-br/02.6.md b/pt-br/02.6.md index ec7196af..6d882f78 100644 --- a/pt-br/02.6.md +++ b/pt-br/02.6.md @@ -2,23 +2,23 @@ ## Interface -One of the subtlest design features in Go are interfaces. After reading this section, you will likely be impressed by their implementation. +Uma das características de projeto mais sutil em Go são interfaces. Depois de ler esta seção, você provavelmente ficará impressionado com sua implementação. -### What is an interface +### O que é uma interface -In short, an interface is a set of methods that we use to define a set of actions. +Resumidamente, uma interface é um conjunto de métodos que usamos para definir um conjunto de ações. -Like the examples in previous sections, both Student and Employee can `SayHi()`, but they don't do the same thing. +Como os exemplos nas seções anteriores, tanto Student (Estudante) quanto Employee (Empregado) podem `SayHi()` (DigaOi()), mas não fazem a mesma coisa. -Let's do some more work. We'll add one more method `Sing()` to them, along with the `BorrowMoney()` method to Student and the `SpendSalary()` method to Employee. +Vamos fazer mais trabalho. Vamos adicionar mais um método `Sing()` (Cantar()) para eles, juntamente com o método `BorrowMoney()` (EmprestarDinheiro()) para Student e `SpendSalary()` (GastarSalario()) para Employee. -Now, Student has three methods called `SayHi()`, `Sing()` and `BorrowMoney()`, and Employee has `SayHi()`, `Sing()` and `SpendSalary()`. +Agora, Student tem três métodos chamados `SayHi()`, `Sing()` e `BorrowMoney()`, e Employee tem `SayHi()`, `Sing()` e `SpendSalary()`. -This combination of methods is called an interface and is implemented by both Student and Employee. So, Student and Employee implement the interface: `SayHi()` and `Sing()`. At the same time, Employee doesn't implement the interface: `SayHi()`, `Sing()`, `BorrowMoney()`, and Student doesn't implement the interface: `SayHi()`, `Sing()`, `SpendSalary()`. This is because Employee doesn't have the method `BorrowMoney()` and Student doesn't have the method `SpendSalary()`. +Esta combinação de métodos é chamada de interface e é implementada por ambos Student e Employee. Então, Student e Employee implementam a interface: `SayHi()` e `Sing()`. Ao mesmo tempo, Employee não implementa a interface: `SayHi()`, `Sing()`, `BorrowMoney()`, e Student não implementa a interface: `SayHi()`, `Sing()`, `SpendSalary()`. Isso ocorre porque Employee não tem o método `BorrowMoney()` e Student não tem o método `SpendSalary()`. -### Type of Interface +### Tipo de Interface -An interface defines a set of methods, so if a type implements all the methods we say that it implements the interface. +Uma interface define um conjunto de métodos, portanto, se um tipo implementa todos os métodos, dizemos que ele implementa a interface. type Human struct { name string @@ -50,18 +50,18 @@ An interface defines a set of methods, so if a type implements all the methods w fmt.Println("Guzzle Guzzle Guzzle...", beerStein) } - // Employee overloads Sayhi + // Employee sobrecarrega Sayhi func (e *Employee) SayHi() { fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name, - e.company, e.phone) //Yes you can split into 2 lines here. + e.company, e.phone) // Sim, você pode dividir em 2 linhas aqui. } func (s *Student) BorrowMoney(amount float32) { - s.loan += amount // (again and again and...) + s.loan += amount // (novamente e novamente e...) } func (e *Employee) SpendSalary(amount float32) { - e.money -= amount // More vodka please!!! Get me through the day! + e.money -= amount // Mais vodka por favor!!! Para aguentar o dia! (More vodka please!!! Get me through the day!) } // define interface @@ -83,117 +83,117 @@ An interface defines a set of methods, so if a type implements all the methods w SpendSalary(amount float32) } -We know that an interface can be implemented by any type, and one type can implement many interfaces simultaneously. +Sabemos que uma interface pode ser implementada por qualquer tipo, e um tipo pode implementar muitas interfaces simultaneamente. -Note that any type implements the empty interface `interface{}` because it doesn't have any methods and all types have zero methods by default. +Observe que qualquer tipo implementa a interface vazia `interface{}` porque ela não tem nenhum método e todos os tipos possuem zero métodos por padrão. -### Value of interface +### Valor da interface -So what kind of values can be put in the interface? If we define a variable as a type interface, any type that implements the interface can assigned to this variable. +Então, que tipo de valores podem ser colocados na interface? Se definirmos uma variável como uma interface de tipo, qualquer tipo que implemente a interface pode ser atribuído a essa variável. -Like the above example, if we define a variable "m" as interface Men, then any one of Student, Human or Employee can be assigned to "m". So we could have a slice of Men, and any type that implements interface Men can assign to this slice. Be aware however that the slice of interface doesn't have the same behavior as a slice of other types. +Como no exemplo acima, se definirmos uma variável "m" como interface Men, então qualquer Student, Human ou Employee pode ser atribuído a "m". Então nós poderíamos ter um slice de Men, e qualquer tipo que implemente a interface Men pode atribuir a este slice. Lembre-se no entanto que o slice da interface não tem o mesmo comportamento de uma slice de outros tipos. package main - + import "fmt" - + type Human struct { name string age int phone string } - + type Student struct { Human school string loan float32 } - + type Employee struct { Human company string money float32 } - + func (h Human) SayHi() { fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone) } - + func (h Human) Sing(lyrics string) { fmt.Println("La la la la...", lyrics) } - + func (e Employee) SayHi() { fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name, - e.company, e.phone) //Yes you can split into 2 lines here. + e.company, e.phone) // Sim, você pode dividir em 2 linhas aqui. } - - // Interface Men implemented by Human, Student and Employee + + // Interface Men implementada por Human, Student e Employee type Men interface { SayHi() Sing(lyrics string) } - + func main() { mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00} paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100} sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000} tom := Employee{Human{"Sam", 36, "444-222-XXX"}, "Things Ltd.", 5000} - + // define interface i var i Men - - //i can store Student + + // posso armazenar Student i = mike fmt.Println("This is Mike, a Student:") i.SayHi() i.Sing("November rain") - - //i can store Employee + + // posso armazenar Employee i = tom fmt.Println("This is Tom, an Employee:") i.SayHi() i.Sing("Born to be wild") - - // slice of Men + + // slice de Men fmt.Println("Let's use a slice of Men and see what happens") x := make([]Men, 3) - // these three elements are different types but they all implemented interface Men + // Estes três elementos são de tipos diferentes, mas todos eles implementam a interface Men x[0], x[1], x[2] = paul, sam, mike - + for _, value := range x { value.SayHi() } } - -An interface is a set of abstract methods, and can be implemented by non-interface types. It cannot therefore implement itself. -### Empty interface +Uma interface é um conjunto de métodos abstratos, e pode ser implementada por tipos não interface. Não pode, portanto, implementar-se. -An empty interface is an interface that doesn't contain any methods, so all types implement an empty interface. This fact is very useful when we want to store all types at some point, and is similar to void* in C. +### Interface vazia - // define a as empty interface +Uma interface vazia é uma interface que não contém nenhum método, portanto, todos os tipos implementam uma interface vazia. Esse fato é muito útil quando queremos armazenar todos os tipos em algum momento, e é semelhante ao void* em C. + + // define a como interface vazia var a interface{} var i int = 5 s := "Hello world" - // a can store value of any type + // a pode armazenar valor de qualquer tipo a = i a = s -If a function uses an empty interface as its argument type, it can accept any type; if a function uses empty interface as its return value type, it can return any type. +Se uma função usa uma interface vazia como seu tipo de argumento, ela pode aceitar qualquer tipo; Se uma função usa a interface vazia como seu tipo de valor de retorno, ela pode retorna qualquer tipo. -### Method arguments of an interface +### Argumentos de métodos de uma interface -Any variable can be used in an interface. So how can we use this feature to pass any type of variable to a function? +Qualquer variável pode ser usada em uma interface. Então, como podemos usar esse recurso para passar qualquer tipo de variável para uma função? -For example we use fmt.Println a lot, but have you ever noticed that it can accept any type of argument? Looking at the open source code of fmt, we see the following definition. +Por exemplo, usamos muito fmt.Println, mas você já notou que ele pode aceitar qualquer tipo de argumento? Olhando para o código aberto de fmt, vemos a seguinte definição. type Stringer interface { String() string } - -This means any type that implements interface Stringer can be passed to fmt.Println as an argument. Let's prove it. + +Isso significa que qualquer tipo que implemente a interface Stringer pode ser passada para fmt.Println como um argumento. Vamos provar isso. package main @@ -208,7 +208,7 @@ This means any type that implements interface Stringer can be passed to fmt.Prin phone string } - // Human implemented fmt.Stringer + // Human implementa fmt.Stringer func (h Human) String() string { return "Name:" + h.name + ", Age:" + strconv.Itoa(h.age) + " years, Contact:" + h.phone } @@ -218,51 +218,51 @@ This means any type that implements interface Stringer can be passed to fmt.Prin fmt.Println("This Human is : ", Bob) } - -Looking back to the example of Box, you will find that Color implements interface Stringer as well, so we are able to customize the print format. If we don't implement this interface, fmt.Println prints the type with its default format. + +Olhando para o exemplo anterior de Box (Caixa), você verá que Color (Cor) implementa a interface Stringer também, assim que somos capazes de personalizar o formato de impressão. Se não implementarmos essa interface, fmt.Println imprime o tipo com seu formato padrão. fmt.Println("The biggest one is", boxes.BiggestsColor().String()) fmt.Println("The biggest one is", boxes.BiggestsColor()) - -Attention: If the type implemented the interface `error`, fmt will call `error()`, so you don't have to implement Stringer at this point. -### Type of variable in an interface +Atenção: Se o tipo implementa a interface `error`, fmt chamará `error()`, então você não tem que implementar Stringer neste momento. -If a variable is the type that implements an interface, we know that any other type that implements the same interface can be assigned to this variable. The question is how can we know the specific type stored in the interface. There are two ways which I will show you. +### Tipo de variável em uma interface -- Assertion of Comma-ok pattern +Se uma variável é o tipo que implementa uma interface, sabemos que qualquer outro tipo que implementa a mesma interface pode ser atribuído a essa variável. A questão é como podemos saber o tipo específico armazenado na interface. Há duas maneiras que vou lhe mostrar. -Go has the syntax `value, ok := element.(T)`. This checks to see if the variable is the type that we expect, where "value" is the value of the variable, "ok" is a variable of boolean type, "element" is the interface variable and the T is the type of assertion. +- Declaração do padrão Comma-ok (Vírgula-ok) -If the element is the type that we expect, ok will be true, false otherwise. +Go possui a sintaxe `value, ok := element.(T)`. Isso verifica se a variável é o tipo que esperamos, onde "value" (valor) é o valor da variável, "ok" é uma variável de tipo booleano, "element" (elemento) é a variável da interface e T é o tipo da declaração. -Let's use an example to see more clearly. +Se o elemento é o tipo que esperamos, ok será verdadeiro, e falso caso contrário. + +Vamos usar um exemplo para ver mais claramente. package main - + import ( "fmt" "strconv" ) - + type Element interface{} type List []Element - + type Person struct { name string age int } - + func (p Person) String() string { return "(name: " + p.name + " - age: " + strconv.Itoa(p.age) + " years)" } - + func main() { list := make(List, 3) - list[0] = 1 // an int - list[1] = "Hello" // a string + list[0] = 1 // um int (inteiro) + list[1] = "Hello" // uma string (cadeia de caracteres) list[2] = Person{"Dennis", 70} - + for index, element := range list { if value, ok := element.(int); ok { fmt.Printf("list[%d] is an int and its value is %d\n", index, value) @@ -276,37 +276,37 @@ Let's use an example to see more clearly. } } -It's quite easy to use this pattern, but if we have many types to test, we'd better use `switch`. +É muito fácil usar esse padrão, mas se tivermos muitos tipos para testar, é melhor usar `switch`. -- switch test +- teste de comutação (switch test) + +Vamos usar `switch` para reescrever o exemplo acima. -Let's use `switch` to rewrite the above example. - package main - + import ( "fmt" "strconv" ) - + type Element interface{} type List []Element - + type Person struct { name string age int } - + func (p Person) String() string { return "(name: " + p.name + " - age: " + strconv.Itoa(p.age) + " years)" } - + func main() { list := make(List, 3) - list[0] = 1 //an int - list[1] = "Hello" //a string + list[0] = 1 // um int (inteiro) + list[1] = "Hello" // uma string (cadeia de caracteres) list[2] = Person{"Dennis", 70} - + for index, element := range list { switch value := element.(type) { case int: @@ -321,75 +321,75 @@ Let's use `switch` to rewrite the above example. } } - -One thing you should remember is that `element.(type)` cannot be used outside of the `switch` body, which means in that case you have to use the `comma-ok` pattern . -### Embedded interfaces +Uma coisa que você deve lembrar é que `element.(type)` não pode ser usado fora do corpo do `switch`, o que significa que nesse caso você tem que usar o padrão `comma-ok`. -The most beautiful thing is that Go has a lot of built-in logic syntax, such as anonymous fields in struct. Not suprisingly, we can use interfaces as anonymous fields as well, but we call them `Embedded interfaces`. Here, we follow the same rules as anonymous fields. More specifically, if an interface has another interface embedded within it, it will have as if it has all the methods that the embedded interface has. +### Interfaces incorporadas (embedded interfaces) -We can see that the source file in `container/heap` has the following definition: +A coisa mais bonita é que Go tem várias sintaxes lógicas incorporadas, como campos anônimos em estruturas. Não supreendentemente, podemos usar interfaces como campos anônimos também, mas chamamos-lhes de `Embedded interfaces` (interfaces incorporadas). Aqui, seguimos as mesmas regras que campos anônimos. Mais especificamente, se uma interface tiver outra interface incorporada no seu interior, isso será como se ela possuísse todos os métodos que a interface incorporada tem. + +Podemos ver que o arquivo fonte em `container/heap` tem a seguinte definição: type Interface interface { - sort.Interface // embedded sort.Interface - Push(x interface{}) //a Push method to push elements into the heap - Pop() interface{} //a Pop elements that pops elements from the heap + sort.Interface // sort.Interface incorporado + Push(x interface{}) // um método Push para empurrar elementos para a pilha + Pop() interface{} // um método Pop para remover elementos da pilha } -We see that `sort.Interface` is an embedded interface, so the above Interface has the three methods contained within the `sort.Interface` implicitly. +Vemos que `sort.Interface` é uma interface incorporada, então a interface acima tem os três métodos contidos em `sort.Interface` implicitamente. type Interface interface { - // Len is the number of elements in the collection. + // Len é o número de elementos na coleção. Len() int - // Less returns whether the element with index i should sort - // before the element with index j. + // Less retorna se o elemento com índice i deve ser ordenado + // antes do elemento com o índice j. Less(i, j int) bool - // Swap swaps the elements with indexes i and j. + // Swap troca os elementos com índices i e j. Swap(i, j int) } - -Another example is the `io.ReadWriter` in package `io`. + +Outro exemplo é o `io.ReadWriter` no pacote `io`. // io.ReadWriter type ReadWriter interface { Reader Writer } - + ### Reflection -Reflection in Go is used for determining information at runtime. We use the `reflect` package, and this official [article](http://golang.org/doc/articles/laws_of_reflection.html) explains how reflect works in Go. +Reflection em Go é usado para determinar informações em tempo de execução. Usamos o pacote `reflect`, e este [artigo](http://golang.org/doc/articles/laws_of_reflection.html) oficial explica como reflect funciona em Go. -There are three steps involved when using reflect. First, we need to convert an interface to reflect types (reflect.Type or reflect.Value, this depends on the situation). +Há três etapas envolvidas quando usamos reflect. Primeiro, precisamos converter um interface para tipos reflect (reflect.Type ou reflect.Value, isso depende da situação). - t := reflect.TypeOf(i) // get meta-data in type i, and use t to get all elements - v := reflect.ValueOf(i) // get actual value in type i, and use v to change its value - -After that, we can convert the reflected types to get the values that we need. + t := reflect.TypeOf(i) // recebe meta-dados no tipo i, e usa t para receber todos os elementos + v := reflect.ValueOf(i) // recebe o valor atual no tipo i, e usa v para alterar seu valor + +Depois disso, podemos converter os tipos reflect para obter os valores que precisamos. var x float64 = 3.4 v := reflect.ValueOf(x) fmt.Println("type:", v.Type()) fmt.Println("kind is float64:", v.Kind() == reflect.Float64) fmt.Println("value:", v.Float()) - -Finally, if we want to change the values of the reflected types, we need to make it modifiable. As discussed earlier, there is a difference between pass by value and pass by reference. The following code will not compile. + +Finalmente, se quisermos mudar os valores dos tipos reflect, precisamos torná-los modificáveis. Como discutido anteriormente, há uma diferença entre passar por valor e passar por referência. O código a seguir não compilará. var x float64 = 3.4 v := reflect.ValueOf(x) v.SetFloat(7.1) - -Instead, we must use the following code to change the values from reflect types. + +Em vez disso, precisamos usar o seguinte código para alterar os valores dos tipos reflect. var x float64 = 3.4 p := reflect.ValueOf(&x) v := p.Elem() v.SetFloat(7.1) -We have just discussed the basics of reflection, however you must practice more in order to understand more. +Acabamos de discutir os fundamentos de reflect, no entanto você deve praticar mais para entender mais. ## Links -- [Directory](preface.md) -- Previous section: [Object-oriented](02.5.md) -- Next section: [Concurrency](02.7.md) +- [Sumário](preface.md) +- Seção Anterior: [Orientação a Objetos](02.5.md) +- Próxima Seção: [Concorrência](02.7.md)