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:
type Person struct {
Name string
Age int
}
You can then create an instance of this class by using the new keyword, like this:
p := new(Person)
To set the values of the fields in the class, you can use the dot notation, like this:
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:
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:
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).
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.
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.
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.
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!
Top comments (4)
easy to read and nice examples. Good Job @casualcoder
Hi! I have some comments for your post, especially under inheritance section:
1) In the last snippet you should create a new instance of Car as:
Otherwise you will get
mixture of field:value and value elements in struct literal
error on compile time.2) The next thing that irritates me (again in the last snippet) is accessing the wheel count of car object like
mustang.Vehicle.Wheels
. Even though it's fine to call like that, sinceVehicle
struct composited as anonymous struct insideCar
struct, it's better to call asmustang.Wheels
. Otherwise there no meaning to use anonymous definition.Or if we want to keep using
mustang.Vehicle.Wheels
, it's better to define Car struct as for readability purposes:Thanks for the post and take care!
I am a new GoLang programmer and this guide was instrumental to my learning journey
You would be surprised that the absence of inheritance doesn't imply absence of ability to follow OO paradigm.
And please learn the difference between association and generalization.