Technically, Go is not an object-oriented programming language. It doesn’t have classes, objects, and inheritance. However, you can define custom tyes with methods(receiver functions) as alternative in Go. For exmaple:
decks.go
package main
import "fmt"
// Create a new type of 'deck'
// which is a slice of strings
type decks []string
// 'd' is the copy of the variable of type 'decl'
// that has access to this NewStandardDeck() method
func (d decks) newStandardDeck() decks {
	newDecks := []string{}
	suits := [4]string{"Clubs", "Diamonds", "Hearts", "Spades"}
	ranks := [13]string{"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}
	for _, s := range suits {
		for _, r := range ranks {
			newDecks = append(newDecks, s+" "+r)
		}
	}
	return newDecks
}
func (d decks) print() {
	for _, value := range d {
		fmt.Println(value)
	}
}
main.go
package main
func main() {
	deck := decks{"Test"}
	deck = deck.newStandardDeck()
	deck.print()
}
A struct is a user-defined type which contains properties that are related together.
For example, we can define a struct Card to reprecent a card in a standard deck.
// Create a new type call Card
type card struct {
	suit string
	rank string
}
// Create a new type of 'deck'
// which is a slice of strings
type decks []card
// 'd' is the copy of the variable of type 'decl'
// that has access to this NewStandardDeck() method
func (d decks) newStandardDeck() decks {
	newDecks := []card{}
	suits := [4]string{"Clubs", "Diamonds", "Hearts", "Spades"}
	ranks := [13]string{"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"}
	for _, s := range suits {
		for _, r := range ranks {
			// you can initial card via "card{suit: s, rank: r}" as well
			newDecks = append(newDecks, card{s, r})
		}
	}
	return newDecks
}
func (d decks) print() {
	for _, value := range d {
		fmt.Println(value.suit, value.rank)
	}
}
func (d decks) printWithField() {
	for _, value := range d {
		fmt.Printf("%+v\n", value)
	}
}
We can use struct in a struct as well.
type contactInfo struct {
	phone string
	email string
}
type player struct {
	name    string
	coins   int
	contact contactInfo
}
func main() {
	player1 := player{name: "Brandon", coins: 1000}
	player1.contact = contactInfo{"0987123456", "1989@TS64.com"}
	player2 := player1
	fmt.Printf("%+v\n", player1)
}
When you assign one struct variable to another, a new copy of the struct is created and assigned. For example:
player1 := player{name: "Brandon", coins: 1000}
player1.contact = contactInfo{"0987123456", "1989@TS64.com"}
player2 := player1
player2.name = "Kobe"
fmt.Printf("%s\n", player1.name) // output = Brandon
fmt.Printf("%s\n", player2.name) // output = Kobe
Because Go does not support overloading of methods and operators, you have to implement function for comparing two variables of same struct.
type contactInfo struct {
	phone string
	email string
}
type player struct {
	name    string
	coins   int
	contact contactInfo
}
func (a player) isRicherThan(b player) bool {
	if a.coins > b.coins {
		return true
	}
	return false
}
func main() {
	player1 := player{name: "Brandon", coins: 5000}
	player2 := player{name: "Mark", coins: 1000}
	if player1.isRicherThan(player2) {
		fmt.Printf("%s has more coins.\n", player1.name)
	}
	if !player2.isRicherThan(player1) {
		fmt.Printf("%s has less coins.\n", player2.name)
	}
}