How to use Object Oriented Programming in Go
Tags: go, oop, tutorial, programming
Published: 2022-12-13 22:36:49

Go is not an Object Oriented Programming language. It is definitely aimed more at the functional crowd, as its support for OOP is lacking at best, preferring C-style structs that can have methods attached to the more traditional style of OOP that Java, Javascript, Python, and C++ support. 

## How would I get started?

To create a class in Go, you can use the type keyword, followed by the name of the class, and then the struct that represents the data for the class. Here is an example of a simple class called Person that has two fields, name and age:

```go
type Person struct {
  Name string
  Age int
}
```

You can then create an instance of this class by using the new keyword, like this:

```go
p := new(Person)
```

To set the values of the fields in the class, you can use the dot notation, like this:

```go
p.Name = "John"
p.Age = 20
```

You can also create a class with methods, which are functions that are associated with a specific class. Here is an example of a Person class with a greet method:

```go
type Person struct {
  name string
  age int
}

func (p *Person) Greet() string {
  return "Hello, my name is " + p.Name
}

```

You can call the greet method on an instance of the Person class like this:

```go
p := new(Person)
p.Name = "John"
p.Age = 20

fmt.Println(p.Greet())  // Output: "Hello, my name is John"
```
Just like when writing other types of functions in Go, capital letters signify public functions that can be called externally. The same goes for the attributes of the struct.

## Constructor? I barely know her!

There is no concept of a constructor method in Go.

I like defining defaults as much as the next OOP programmer, and the easiest (and only) way to do it in Go is using a factory method that returns a new instance of said "class" (struct).

```go
type Person struct {
  Name string
  Age int
}

func NewPerson(name string, age int) *Person {
  p := new(Person)
  p.Name = name
  p.Age = age
  return p
}
```

## What about my inheritance?


In Go, class inheritance works by allowing type embedding. Type embedding allows you to use one type as a part of another type. This is similar to class inheritance in other languages, but instead of subclassing one type from another, a type is embedded inside another type. This allows the embedded type to inherit the properties and methods of the containing type. Type embedding is a powerful technique that can be used to create complex types with a lot of functionality.

Let's say we have a type "Vehicle" and a type "Car" which embeds Vehicle. Car will inherit all the properties and methods of Vehicle, as well as any additional ones it may have. So, for example, if Vehicle has a "Drive()" method, Car will also have this method. This allows us to reuse code and create complex types.

```go
package main

import "fmt"

type Vehicle struct {
    Wheels int
}

func (v *Vehicle) Drive() {
    fmt.Println("Driving")
}

type Car struct {
    Vehicle
    Doors int
}

func main() {
    c := Car{}
    c.Drive()
}
```

You can override the `Drive()` function by making a new one but instead of passing in a pointer to a vehicle, you do a pointer to a Car.

```go
func (c *Car) Drive() {
    fmt.Println("Driving on a road")
}
```

This is not the same for attributes (in this case `Doors` for the Car and `Wheels` for both). If we want to set the number of wheels on the Car, we will need to create an instance of Vehicle in the Car. Here is an example factory function that does just that.

```go

func NewCar(doors int) *Car {
    c := Car{
       Vehicle{Wheels: 4},
       Doors: doors,
    }
    return &c
}

// and if we want to access the Wheels on the Car
mustang := NewCar(4)
fmt.Println("A car has ", mustang.Vehicle.Wheels)
```

One more thing of note, pointers allow more control with the structs than using by value, so always try to use a pointer when working with classes in Golang.

I hope this tutorial helped. Question? Comments? Concerns? Leave them below!