Go não é POO!
É isso mesmo, você não leu errado. Go não é POO e por padrão não possui suporte para o paradigma.
"Mas como assim? Eu ja vi vários vídeos no YouTube de pessoas explicando como podemos utilizar Go com POO..."
Esse também foi meu argumento quando estava aprendendo. Apesar de Go suportar métodos, composição, polimorfismo e encapsulamento não há suporte para herança por padrão e também não existem objetos. Talvez essas informações sejam um balde de agua fria para alguns e para outros nem tanto.
Vindo de uma linguagem que suporta fortemente os recursos da POO (Typescript e Java), só depois de um tempo fazendo alguns projetos que pude notar o erro que estava cometendo. É natural que tentamos replicar o que estamos acostumados a fazer todos os dias, afinal esse paradigma é algo tipico das linguagens de programação de mercado, além de que POO é uma opção quase que indispensável para se trabalhar e construir a maioria dos softwares e aplicações do cotidiano.
É possivel que podemos programar OO com Go, não de forma natural e padronizada, mas como uma espécie de POO virtualizada, pois utilizamos de alguns artificios a partir do recurso que a linguagem nos oferece para o estilo de programar com a mesma. Veja este exemplo abaixo:
package main
import (
"fmt"
"time"
)
type User struct {
name, country string
age int
}
type IUser interface {
calcBirthYear() int
}
func (u *User) calcBirthYear() int {
return time.Now().Year() - u.age
}
func calcBirthYear(u IUser) {
fmt.Printf("Your age is %d", u.calcBirthYear())
}
func main() {
user := User{
name: "Fulano de Tal",
country: "Brasil",
age: 23,
}
calcBirthYear(&user) //Your age is 2000
}
Criamos uma struct bem simples com 3 dados, name, country e age, uma interface com um metodo chamado "calcBirthYear" que abaixo satisfaz esta mesma interface que calculará o ano de nascimento do usuário e em seguida hidratamos a struct com os dados que foram definidos. até ai bem parecido com a POO, mas perceba que logo de cara, notamos que uma struct não é uma classe, a principal diferença é que uma struct armazena tipos de dados enquanto uma classe contém um modelo de tipos de dados e comportamentos e pode server como modelo para vários dados. Um exemplo:
interface IUser {
calcBirthYear(): number;
}
class User implements IUser {
public name: string;
public country: string;
public age: number;
constructor(name: string, country: string, age: number) {
this.name = name;
this.country = country;
this.age = age;
}
calcBirthYear(): number {
return new Date().getFullYear() - this.age;
}
}
const user = new User("Fulano de Tal", "Brasil", 23)
console.log(`age: ${user.calcBirthYear()}`) //age: 2000
A principal diferença esta exatamente nos recursos e no objetivo que ambas as linguagens oferecem para trabalhar com tal paradigma pois ambas se assemelham muito quando o assunto é sintaxe, mesmo assim Go não foi feito para a programação OO, sim, pode não fazer tanto sentido vendo esses exemplos, na verdade parece estar na cara que dá sim para usar OO com Go, mesmo de uma forma não natural, no entanto quanto mais vamos utilizando a linguagem mais entendemos suas limitações quando queremos criar algo mais complexo com POO.
Então você deve estar se perguntando "Se Go não é OO e algumas pessoas programam mesmo assim, qual paradigma serve melhor para Go?"
A comunidade do Go costuma não rotular a linguagem a partir de um paradigma X ou Y, sendo assim Go tem seu próprio jeito de codar, o famoso Go way. E isso também se aplica ao objetivo de cada linguagem, Go não foi pensado numa linguagem para suportar a OO, mas sim para ter bastante performance ao mesmo tempo que se mantém simples. Muito cuidado ao adicionar complexidade onde não deveria existir.