Aunque Go no es un lenguaje de programación orientado a objetos (OOP) en el sentido tradicional (como Java o C++), proporciona formas idiomáticas de manejar conceptos comunes de OOP como encapsulación, herencia y polimorfismo. Esta es una guía básica para aplicar principios de OOP en Go de manera idiomática:
En Go, la encapsulación se logra utilizando la visibilidad basada en el caso de la primera letra. Los identificadores que comienzan con una letra mayúscula son exportados (públicos), mientras que los que comienzan con una letra minúscula son no exportados (privados).
Ejemplo:
package main
import "fmt"
type Person struct {
Name string // Exportado (público)
age int // No exportado (privado)
}
func NewPerson(name string, age int) *Person {
return &Person{Name: name, age: age}
}
func (p *Person) GetAge() int {
return p.age
}
func (p *Person) SetAge(age int) {
p.age = age
}
func main() {
p := NewPerson("Alice", 30)
fmt.Println(p.Name) // Acceso permitido
fmt.Println(p.GetAge()) // Acceso permitido mediante método público
}
Go favorece la composición sobre la herencia. En lugar de crear una jerarquía de clases, se pueden combinar tipos usando estructuras anidadas (embedding).
Ejemplo:
package main
import "fmt"
type Engine struct {
Power int
}
func (e Engine) Start() {
fmt.Println("Engine starting with power:", e.Power)
}
type Car struct {
Engine
Model string
}
func main() {
myCar := Car{
Engine: Engine{Power: 200},
Model: "Tesla",
}
fmt.Println("Car model:", myCar.Model)
myCar.Start() // Llamada al método embebido
}
Las interfaces en Go son implementadas de forma implícita. Cualquier tipo que implemente los métodos definidos por una interfaz se considera que implementa esa interfaz.
Ejemplo:
package main
import "fmt"
type Speaker interface {
Speak()
}
type Dog struct{}
func (d Dog) Speak() {
fmt.Println("Woof!")
}
type Cat struct{}
func (c Cat) Speak() {
fmt.Println("Meow!")
}
func MakeSpeak(s Speaker) {
s.Speak()
}
func main() {
d := Dog{}
c := Cat{}
MakeSpeak(d)
MakeSpeak(c)
}
El polimorfismo en Go se logra a través del uso de interfaces.
Ejemplo:
package main
import "fmt"
type Shape interface {
Area() float64
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
type Rectangle struct {
Width, Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func PrintArea(s Shape) {
fmt.Println("Area:", s.Area())
}
func main() {
c := Circle{Radius: 5}
r := Rectangle{Width: 10, Height: 5}
PrintArea(c)
PrintArea(r)
}
Aunque Go no tiene constructores en el sentido tradicional, es común definir funciones que inicialicen y devuelvan instancias de un tipo.
Ejemplo:
package main
import "fmt"
type Employee struct {
Name string
Salary float64
}
func NewEmployee(name string, salary float64) *Employee {
return &Employee{Name: name, Salary: salary}
}
func main() {
e := NewEmployee("John Doe", 50000)
fmt.Println(e)
}
En Go, los métodos pueden ser definidos en cualquier tipo (no solo en estructuras). La sintaxis de los métodos es similar a la de las funciones, pero con un receptor adicional.
Ejemplo:
package main
import "fmt"
type Point struct {
X, Y int
}
func (p Point) Add(q Point) Point {
return Point{p.X + q.X, p.Y + q.Y}
}
func main() {
p1 := Point{2, 3}
p2 := Point{4, 5}
p3 := p1.Add(p2)
fmt.Println(p3) // Output: {6 8}
}
En Go, se evita la herencia de subtipo utilizando interfaces y composición, promoviendo un diseño más flexible y menos acoplado.
Ejemplo:
package main
import "fmt"
type Printer interface {
Print()
}
type TextPrinter struct {
text string
}
func (tp TextPrinter) Print() {
fmt.Println(tp.text)
}
type HTMLPrinter struct {
html string
}
func (hp HTMLPrinter) Print() {
fmt.Println(hp.html)
}
func main() {
var p Printer
p = TextPrinter{text: "Hello, World!"}
p.Print() // Output: Hello, World!
p = HTMLPrinter{html: "<h1>Hello, World!</h1>"}
p.Print() // Output: <h1>Hello, World!</h1>
}
-
SOLID en Go guia basica: https://gist.github.com/zeroidentidad/334cd6fcd338ebeff3a5161f1a6b729e
-
Patrones de diseño de código en Go: https://refactoring.guru/es/design-patterns/go
-
Arquitectura limpia con Go: https://medium.com/nerd-for-tech/clean-architecture-with-golang-3fa1a1c2b6d6