Você está na página 1de 10

Go é orientado a

objetos ?
Jefferson Otoni Lima

Fala comigo galerinha, a semana começou agitada 😂, este post


é sobre Orientação Objeto na linguagem de
programação Go. É um assunto que tornou-se recorrente
em listas de discussões, MeetUp, grupos etc. Quando o
assunto é Programação Orientada a Objetos em Go
causa uma polêmica.

Sabemos que a Linguagem Go é um Like C e também


sabemos que a linguagem Go teve influências de diversas
outras linguagens de programação e paradigmas diferentes,
dentre elas: Alef, APL, BCPL, C,
CSP, Limbo, Modula, Newsqueak, Oberon, occam,Pa
scal, Smalltalk e Cristal. Como podem perceber temos
uma miscelânea de paradigmas porém o paradigma
Imperativo e Concorrente são os que mais predominam
em Go.

Go é uma linguagem orientada a objetos a resposta para


esta pergunta é SIM e NÃO. No site oficial Go em faq
encontraremos alguns pontos sobre isto caso queira da uma
conferida só clicar aqui Go an object-oriented language
Em Go conseguimos desenvolver um estilo de
programação orientada a objetos permitindo construir
tipos e métodos porém não há hierarquia de tipos, é bem
diferente da implementação que conhecemos em outras
linguagens de programação porque não temos um arsenal de
recursos como Linguagens desenvolvidas para o
paradigma orientadas a objetos.

O que temos em Go é uma abstração para flexibilizar e ajudar


quando precisarmos utilizar diferentes tipos de structs sem
nos preocupar qual struct estará sendo utilizada e o mais legal
deixa encapsulado seu método de forma segura.

Bem para que isto seja possível em Go temos


um coadjuvante que se chama “interface” 💪🏼 ou
seja type MyInterface interface{ // assinatura } e sua
abordagem como dissemos é diferente das implementações
que conhecemos em outras langs, interface é a única forma de
permitir o despacho de métodos dinâmicos em Go e
podemos conter valores de qualquer tipo. (Cada tipo
implementa pelo menos zero métodos).

Interfaces vazias são usadas por código que lida com


valores de tipo desconhecido que é definido da seguinte
forma interface{} olha um exemplo abaixo.
exemplo de interface vazia

No exemplo acima mostramos como a interface recebe


qualquer tipo em Go, usando interface podemos passar
qualquer tipo para ela isto nos permite a criar funções que o
tipo é desconhecido vamos ver um exemplo:
interface utilizada como parâmetros da função

Criamos uma função que recebe qualquer tipo, e demonstrei


no exemplo acima como acessar seus valores quando temos
um tipo interface. Para acessar seus respectivos valores
temos que fazer um Assertion.

Um type assertion permite o acesso a valores de um tipo


através de uma valor concreto t := v.(T). Essa expressão
declara que o valor de v é um tipo concreto de T e
define v como T e atribui a t.

É recomendado sempre testarmos antes utilizando switch.

Isto é um erro comum quando usamos


type assertion devemos testar se v é do tipo T ates de
realizar assertion, isso gera um panic na nosso programa.
Quando fazemos o test ele evita esse tipo de erro e ainda
permite verificar se a conversão funcionou.t, ok := v.(T)

O type switch é igual a uma expressão switch normal, porém


o switch irá ser aplicado sobre o tipo e não o valor. O tipo do
valor é comparado a vários tipos. A declaração realiza os teste
e executa o bloco de código quando o tipo do valor contiver o
tipo testado.
Agora que já vimos um exemplo da utilização de interface
vazia Iremos abordar interface como uma coleção de
métodos.
Alguns pontos importantes sobre interface
- Um tipo de interface é definido como um conjunto de
assinaturas de método.
- Um valor do tipo de interface pode conter qualquer valor que
implemente esses métodos.
- As interfaces são implementadas implicitamente.
- Não há declaração explícita.
- Nos bastidores, os valores da interface podem ser
considerados como uma tupla de um valor e um tipo concreto:
(value, type)
- Um valor de interface contém um valor de um tipo concreto
subjacente específico.
- Chamar um método em um valor de interface executa o
método de mesmo nome em seu tipo subjacente.
- Se o valor concreto dentro da própria interface for nulo, o
método será chamado com um receptor nulo.
- um valor de interface que contém um valor concreto nulo é
ele próprio não nulo.
- Um valor de interface nulo não contém valor nem tipo
concreto.
- Chamar um método em uma interface nula é um erro em
tempo de execução porque não há nenhum tipo dentro da
tupla da interface para indicar qual método concreto chamar.
type myInface interface { //assinatura }
Então o que temos até o momento em Go é uma forma de
fazer polimorfismo utilizando interface, encapsulament
o de métodos e disponibiliza-los de forma
dinâmica tudo isto é muito semelhante ao “Duck typing”.

O que é Duck typing


O Go suporta “Duck typing”, é um estilo de tipagem em que
os métodos e propriedades de um objeto determinam
a semântica válida, em vez de sua herança de uma classe
particular ou implementação de uma interface explicita. O
nome do conceito refere-se ao teste do pato, atribuído à James
Whitcomb Riley. Isso faz com que o Go se pareça com uma
linguagem dinâmica.

Go usa “Tipagem Estrutural“ em métodos para

determinar a compatibilidade de um tipo com uma interface.


Não há hierarquias de tipos e a “Tipagem Estrutural” é uma
alternativa interessante à herança clássica em linguagens com
tipagem estática. Ele permite que você escreva algoritmos
genéricos sem obscurecer a definição de um tipo em um mar
de interfaces. Talvez mais importante, ajuda as linguagens
com tipagem estática a capturar a sensação e a
produtividade das linguagens dinamicamente
tipificadas.

D uck typing ocorre em tempo de execução e “Tipagem

Estrutural” que ocorre em tempo de compilação. Go não da


suporte a orientação a objetos como é implementado nas
linguagens como C#, Java ou mesmo C ++, não possui
herança e honestamente fico muito feliz com isto, mas oferece
alguns recursos como composição e interfaces como
descrevemos acima.

O exemplo abaixo demonstra o comportamento do que


seria “Dunk typing” e polimorfismo utilizando Go.

Caso queira executar o exemplo basta clicar no


link: play.golang.org/familia-interface.go

A interface é uma coleção de métodos, além de ser um tipo


personalizado.

Dizemos que algo satisfaz esta interface (ou implementa esta


interface ) se tiver um método com a assinatura
exata Dados() string.

Por exemplo, a struct Pai satisfaz a interface porque tem


um Dados() string definido como método.

Não é realmente importante o que esse “Pai” é ou faz. A única


coisa que importa é que tem um método
chamado Dados() que retorna uma string.

Ou, como Filhos, o tipo a seguir também satisfaz


a “interface Familia” novamente porque tem um método
com a assinatura exata Dados() string.
O importante aqui é que temos três tipos diferentes Pai,
Filho e Filhos, que fazem coisas diferentes. Mas o que eles
têm em comum é que ambos satisfazem a interface Familia.

Podemos pensar sobre isto de outra maneira. Se você sabe que


um objeto satisfaz a interface Familia, pode confiar que ele
tem um método com a assinatura exata Dados() string que
pode ser chamada.

Agora vamos conferir nossa função showDados(…) que será


responsável por acessar todos nossos métodos diferentes
atendendo a mesma interface, agora você poderá usar objetos
de qualquer tipo desde que satisfaça a interface.

Olha o exemplo abaixo, temos vários tipos de objetos sendo


passado para a função showDados(…).

As possibilidades são diversas, podemos definir uma


interface recebendo outra interface, podemos criar
outras funções que satisfaça a interface como o exemplo
abaixo:

A função showDados2(f []Familia) recebe um vetor


da interface Familia.

Simples não é ? Com esta definição temos diversas


possibilidades que poderá utilizar interface em seus projetos.
Clean Architecture é um bom exemplo desta utilização
também, toda sua arquitetura se baseia-se em interfaces caso
queiram da uma conferida alguns links legais “Clean
Architecture using Golang” e Clean Architecture, 2 years
later

Existem alguns motivos pelos quais você poderia usar


interface em Go, vou listar os três mais comuns:

. Para ajudar a reduzir a duplicação ou código padrão.

. Para tornar mais fácil usar mocks em vez de objetos reais em


testes de unidade.

. Como uma ferramenta de arquitetura, para ajudar a impor o


desacoplamento entre as partes de sua base de código.

Algumas interfaces utilizada em Go em


sua strand libray default
Uma pequena lista de algumas das interfaces mais comuns e
úteis na biblioteca padrão.

 builtin.Error
 fmt.Stringer
 io.Reader
 io.Writer
 io.ReadWriteCloser
 http.ResponseWriter
 http.Handler
 Sort
Vamos da uma olhada no pkg sort
Um tipo, normalmente uma coleção, que satisfaz a
classificação. A interface pode ser classificada pelas funções
neste pacote. Os métodos requerem que os elementos da
coleção sejam enumerados por um índice inteiro.

O que vemos logo abaixo são as assinaturas que a interface


Sort possui

Quando formos usar a interface iremos ter que criar os três


métodos que satisfaça exatamente a Interface, e o que muda
sempre são os tipos e structs que poderão implementar os
métodos que satisfaça a interface.

A desvantagem aqui é que não necessariamente precisaria dos


três métodos para Ordenar minha struct precisaria somente
do Less(…), porém somos obrigados a satisfazer a interface
exatamente como ele está assinada ou seja precisaremos
sempre implementar Less(…), Len(…), Swap(…).
Como boa prática sempre é interessante termos interfaces
mais enxutas possíveis.

Uma curiosidade aqui neste pkg é a possibilidade de utilizar


uma interface incorporada e que o Reverse use os métodos de
implementação de outra interface 😱.

Legal não é ? Ou seja o Less retorna o oposto


do método Less da implementação incorporada.
E para fechar temos diversos tipos diferentes criando e
implementando seus próprios métodos Less(…), Len() e
Swap(..)

Aqui uma lista completa de interfaces em


Go
Lista completa

Caso queiram acessar o código fonte do exemplo apresentado


e mais exemplos basta visitar este link.

github.com/jeffotoni/goexample

Conclusão
Espero que tenha gostado do resumo e uma breve introdução
do que podemos fazer em Go quando o assunto é Orientação a
Objeto. Qualquer observação, dica, melhoria etc.. no conteúdo
por favor só enviar para melhora-lo ainda mais.
Percebemos que na prática a utilização de interfaces é bem
mais simples do que a explicação teórica. E com a chegada de
generics os problemas que resolvemos utilizando interface
serão todos repensados após o lançamento de generics.

Você também pode gostar