Private fields and methods for a struct

Go

Go Problem Overview


In the following test code I would like to have both mytype and the doPrivate method private, so that only members of mytype can access it, but not other types\functions in the scope of the mypackage package.

Can I do this in golang?

package mypackage

type mytype struct {
	size          string
	hash          uint32
}

func (r *mytype) doPrivate() string {
    return r.size
}

func (r *mytype) Do() string {
    return doPrivate("dsdsd")
}

Fields size and hash as well as the doPrivate method should be encapsulated and no other type should have access to them.

Go Solutions


Solution 1 - Go

In Go, an identifier that starts with a capital letter is exported from the package, and can be accessed by anyone outside the package that declares it.

If an identifier starts with a lower case letter, it can only be accessed from within the package.

If you need members in a type to only be accessed by members of that type, you then need to place that type and its member functions in a separate package, as the only type in that package.

Solution 2 - Go

That's not how "privacy" works in Go: the granularity of privacy is the package.

If you really want only the members of mytype to access some fields, then you must isolate the struct and the functions in their own package.

But that's not the usual practice. Whether Go is OOP or not is debatable but clearly the practice isn't to encapsulate the code by a struct like you seem to want to do. Usually a package is small enough to be coherent: if you don't want to access fields from within the package, don't access them.

Solution 3 - Go

You can create an interface with the method you wish to expose and only access the object when wrapped into that interface.

package main

type mytype struct {
	size string
	hash uint32
}

// interface for exposed methods
type myinterface interface {
	do() string
}

// constructor (optional)
func newMytype(size string, hash uint32) myinterface {
	return &mytype{size, hash}
}

func (r *mytype) doPrivate() string {
	return r.size
}

func (r *mytype) do() string {
	return r.doPrivate()
}

func main() {
	// with constructor
	t := newMytype("100", 100)
	t.do()
	// t.doPrivate() // t.doPrivate undefined (type myinterface has no field or method doPrivate)
	
	// without constructor
	t2:= myinterface(&mytype{"100", 100})
	t2.do()
	// t.doPrivate() // t.doPrivate undefined (type myinterface has no field or method doPrivate)doPrivate)
}

https://play.golang.org/p/awjIIj8Kwms

Solution 4 - Go

You cannot do this in Go. Visibility is on a per package level only. But you may split your package into two.

Solution 5 - Go

In one module there can be any number of packages.

Public/Private works only across one package.
All public fields, methods and functions starts with uppercase char.
All private fields, methods and functions starts with lowercase char.

To add package to your module or program just create a lowercase folder and add package name to all files inside. Here is the example.

./main.go
./foo/foo.go
./foo/MyStruct.go

file ./foo/foo.go:

package foo

import "fmt"

func SomePublicFuncInFoo() {
	somePrivateFuncInFoo()
}

func somePrivateFuncInFoo() {
	fmt.Println("somePrivateFuncInFoo call")
}

file ./foo/MyStruct.go:

package foo

import "fmt"

type MyStruct struct {
	MyPublicField  string // starts with uppercase char
	myPrivateField string // starts with lowercase char
}

func NewMyStruct(publicField string, privateField string) *MyStruct {
	return &MyStruct{
		MyPublicField:  publicField,  
		myPrivateField: privateField, 
	}
}

func (self *MyStruct) SomePublicMethod() {
	self.privateMethod()
}

func (self *MyStruct) privateMethod() {
	fmt.Println("MyStruct", self.MyPublicField, self.myPrivateField)
}

file ./main.go:

package main

import (
	"fmt"
	"{your-module-name}/foo" // this line should be added by your IDE
)

func main() {

	foo.SomePublicFuncInFoo()

	myStruct := foo.NewMyStruct("string1", "string2")
	fmt.Println("myStruct.MyPublicField=", myStruct.MyPublicField)

	myStruct.SomePublicMethod()
}

Solution 6 - Go

You can have private variables and functions in Go, but the trick is that you simply don't define them in the struct. Bind them to the call stack of a closure, and simply don't return them.

package main

import (
    "fmt"
)

type mytype struct {
    Do func() string
}

func MyType(size string, hash uint32) mytype {
    doPrivate := func() string {
        return size
    }
    return mytype{
        Do: func() string {
            return doPrivate()
        },
    }
}

func main() {
    instance := MyType("100", 100)
    fmt.Println(instance.Do())
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionandrew.foxView Question on Stackoverflow
Solution 1 - GonosView Answer on Stackoverflow
Solution 2 - GoDenys SéguretView Answer on Stackoverflow
Solution 3 - GoFarshid TView Answer on Stackoverflow
Solution 4 - GoVolkerView Answer on Stackoverflow
Solution 5 - GoLexView Answer on Stackoverflow
Solution 6 - GoMichael GreenView Answer on Stackoverflow