Clique sobre os tópicos listados abaixo para navegar até o conteúdo desejado.

  1. Básico sobre interface em Go
  2. Entender como declarar um interface e usar
  3. Segregação de interface
  4. Interfaces composta de interface

Além da linguagem Go ter suporte à interface uma outra uma característica de O.O.

Interface é um tipo de dado em que definimos um ou mais métodos abstratos, sem implementação, servindo como um contrato que posteriomente são implementados e associados a algum tipo de dado receptor.

Para acompanhar esta parte do tutorial é necessário ter conhecimento do uso de métodos. Esse assunto pode ser visto em Go: Métodos.

Para a declaração de uma interface Go, utilizamos a palavra reservada interface como mostrado abaixo:

Sintaxe
type nome_interface interface {
    nome_metodo1(param1 tipo_param, paramN tipo_param) (tipo_retorno1, tipo_retornoN)
    nome_metodo2(param1 tipo_param, paramN tipo_param) (tipo_retorno2, tipo_retornoN)
    nome_metodoN(param1 tipo_param, paramN tipo_param) (tipo_retornoN, tipo_retornoN)
}
Onde
metodo1…N: nome do métodos que desejamos criar. 
param1…N: lista de parâmetros 
tipo_retorno: um ou mais tipos de retorno do método
tipo_param: tipo de dado do parâmetro

Como a interface é um tipo de dado, podemos criar uma variável do tipo interface e atribuir a essa variável outras tipos de dados que possuem métodos criados, respeitando as definições de uma interface.

Com o uso de interface em Go, utilizamos o conceito de abstração.

Exemplo 1
package main
import "fmt"

//declaração dos tipos
type meu_tipo uint8 
type meu_tipo2 uint8

//declaração da interface
type minha_interface interface {
  MostrarBinario()
}

//implementação da interface e associação de método aos tipos
func (val meu_tipo) MostrarBinario(){
  fmt.Printf("MostrarBinario meu_tipo :%08b\n", val) 
}

func (val meu_tipo2) MostrarBinario(){
  fmt.Printf("MostrarBinario meu_tipo2:%08b\n", val) 
}

func main() {
  
  var var_inter minha_interface //nil
  
  var_inter = meu_tipo(100)
  var_inter.MostrarBinario()
  
  var_inter = meu_tipo2(200)
  var_inter.MostrarBinario()
  
}
Saída
str1 declared and not used
str2 declared and not used

Ao declarar uma variável do tipo interface sem atribuição inicial, seu valor padrão ou inicial é nil.

Quando associamos um método a um tipo de dado por meio de interface, todos os métodos definidos na interface devem ser obrigatóriamente implementados.

A linguagem Go, além de permitir que utilizarmos o conceito de abstração por intermédio das interfaces. Go permite ainda que para um mesmo tipo de dados possamos implementar métodos de uma ou mais interfaces, ou seja, utilizar o conceito de segregação de interface.

Sintaxe
type nome_interface1 interface {
    nome_metodo1(param1 tipo_param, paramN tipo_param) (tipo_retorno1, tipo_retornoN)
}
type nome_interface2 interface {
    nome_metodo2(param1 tipo_param, paramN tipo_param) (tipo_retorno2, tipo_retornoN)
}

Com a utilização de segregação de interface, implementamos apenas as interfaces realmente necessárias para o uso em nossos tipos de dados.

Exemplo 2
package main

import (
	"fmt"
)

//declaração dos tipos
type meu_tipo uint8
type meu_tipo2 uint8

//definição de interfaces segregadas
type minha_interface interface {
	OutroMetodo(param int) string
}

type minha_interface2 interface {
	OutroMetodo2()
}

//Implementação de métodos e atribuição a tipos
func (val meu_tipo2) OutroMetodo(param int) string {
	fmt.Printf("OutroMetodo\nparam: %d\n", param)
	return "retornando string"
}

func (val meu_tipo2) OutroMetodo2() {
	fmt.Printf("minha_interface2 \nOutroMetodo2")
}

func main() {

	var var_inter minha_interface //nil
	
	var_inter = meu_tipo2(200)
	var_inter.OutroMetodo(100) //minha_interface

	var var_inter2 minha_interface2
	var_inter2 = meu_tipo2(200)
	var_inter2.OutroMetodo2() //minha_interface2
}
Saída
OutroMetodo
param: 100
minha_interface2 
OutroMetodo2

A linguagem Go permite que criemos uma interface composta de outras interfaces em seu corpo. Isso permite a criação de interfaces mais flexíveis, em que podemos escolher quais interfaces e quais métodos queremos utilizar de acordo com a necessidade.

Sintaxe
type nome_interface1 interface {
    nome_metodo1(param1 tipo_param, paramN tipo_param) (tipo_retorno1, tipo_retornoN)
}
type minha_interface2 interface {
    nome_interface1
}
Exemplo 3
package main

import "fmt"

type meu_tipo uint8
type meu_tipo2 uint8

// definição das interfaces segmentadas ou segregadas
type minha_interface interface {
	metodo1()
}
type minha_interface2 interface {
	metodo2()
}
type minha_interface3 interface {
	metodo3()
}

// declaração de interface composta
type interface_final interface {
	minha_interface
	minha_interface2
}

// minha_interface2 + minha_interface3
type interface_final2 interface {
	minha_interface2
	minha_interface3
}

// implementação de métodos
func (t meu_tipo) metodo1() {
	fmt.Printf("method1\n")
}

func (t meu_tipo) metodo2() {
	fmt.Printf("method2\n")
}

func (t meu_tipo) metodo3() {
	fmt.Printf("method3\n")
}

func main() {
	//usando minha_interface
	var var_inter interface_final = meu_tipo(100)
	var_inter.metodo1()
	var_inter.metodo2()

	//usando minha_interface2
	var var_inter2 interface_final2 = meu_tipo(255)
	var_inter2.metodo2()
	var_inter2.metodo3()

}
Saída
method1
method2
method2
method3

  1. 17/09/2024 - revisão 2 - Ajustes gramaticais, remoção de texto duplicado em 'Declaração'
  2. 03/10/2023 - revisão 1 - Correção em referências e erros gramaticais
  3. 21/08/2023 - versão inicial