Go Encapsulation and Access Control: Mastering Privacy with Naming Conventions

Lesson Overview

Hello! In this lesson, we're diving into Encapsulation and access control in Go. Unlike some languages, Go manages encapsulation through capitalization conventions. Imagine encapsulation as an invisible barrier that protects the internals of your code. In Go, identifiers (like struct fields and methods) are kept safe using naming conventions: uppercase indicates exported (public), while lowercase indicates unexported (private). This is crucial for creating robust and secure applications!

Into the Encapsulation

In Go, encapsulation is achieved through structs and methods. Structs bundle together data, while methods attach functionality. Please note that in Go, the distinction between exported (public) and unexported (private) identifiers in Go is meaningful only across package boundaries, so all code snippets we'll discuss today will span multiple files. As example, imagine to be coding a multiplayer game; you could create a Player struct, encapsulating fields (health, armor, stamina) and methods (ReceiveDamage, ShieldHit, RestoreHealth).

File content for player/player.go:

package player

type Player struct {
    health  int
    armor   int
    stamina int
}

// Constructor function for creating new Player
func NewPlayer(health, armor, stamina int) *Player {
    return &Player{health: health, armor: armor, stamina: stamina}
}

// Public method to receive damage
func (p *Player) ReceiveDamage(damage int) {
    p.health -= damage // Reduce health
}

// Public method to decrease armor
func (p *Player) ShieldHit(armorDecrease int) {
    p.armor -= armorDecrease // Decrease armor
}

// Public method to restore health
func (p *Player) RestoreHealth(healthIncrease int) {
    p.health += healthIncrease // Restore health
}

File content for main.go:

package main

import (
    "fmt"
    "player"
)

func main() {
    player := player.NewPlayer(100, 50, 77)
    player.ReceiveDamage(10)
    player.ShieldHit(5)
    player.RestoreHealth(15)
    fmt.Println("Player's Current Health:", player) // Output: Player's Current Health: &{105 45 77}
}

Here, player is an instance of the Player struct with methods you can call to manipulate its state.

Remark the Privacy

In Go, access control is managed through capitalization. An identifier, such as a field or method, is exported (similar to "public") if it begins with an uppercase letter. Conversely, if it starts with a lowercase letter, it remains unexported (similar to "private"). Note that this access control is enforced only across package boundaries.

File content for privacy/privacy.go:

package privacy

type PrivateExample struct {
    PublicAttribute  string
    privateAttribute string
}

// Constructor-like function for creating a new PrivateExample with privateAttribute
func NewPrivateExample(publicAttr, privateAttr string) *PrivateExample {
    return &PrivateExample{PublicAttribute: publicAttr, privateAttribute: privateAttr}
}

// Method that prints attributes (for demonstration purposes)
func (pe *PrivateExample) PrintAttributes() {
    fmt.Println("Public Attribute:", pe.PublicAttribute)
    fmt.Println("Private Attribute:", pe.privateAttribute)
}

File content for main.go:

package main

import (
    "fmt"
    "example"
)

func main() {
    example := privacy.NewPrivateExample("Public", "Private")
    example.PrintAttributes()
    fmt.Println(example.PublicAttribute) // Output: Public
    // Uncommenting the following line would cause an error because privateAttribute is unexported
    // fmt.Println(example.privateAttribute)
}
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal