结构体的私有字段和方法

问题描述 投票:0回答:6

在下面的测试代码中,我希望同时拥有

mytype
doPrivate
方法 private,以便只有
mytype
的成员可以访问它,但不能访问
mypackage
范围内的其他类型函数包。

我可以在 Go 中执行此操作吗?

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")
}

字段

size
hash
以及
doPrivate
方法应该被封装,并且任何其他类型都不应访问它们。

go
6个回答
123
投票

在 Go 中,以大写字母开头的标识符是从包中导出的,并且可以被声明它的包之外的任何人访问。

如果标识符以小写字母开头,则只能从包内访问它。

如果您需要类型中的成员只能由该类型的成员访问,则需要将该类型及其成员函数放在单独的包中,作为该包中的唯一类型。


94
投票

这不是 Go 中“隐私”的运作方式:隐私的粒度是包。

如果您真的只想让

mytype
的成员访问某些字段,那么您必须将结构体和函数隔离在它们自己的包中。

但这不是通常的做法。 Go 是否是 OOP 是有争议的,但显然实践并不是像您似乎想要的那样通过结构封装代码。通常,包足够小以保持一致:如果您不想访问包内的字段,请不要访问它们。


47
投票

您可以使用您希望公开的方法创建一个接口,并且仅在包装到该接口中时才访问该对象。

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


14
投票

你无法在 Go 中执行此操作。可见性仅在每个包级别上。但您可以将包裹分成两份。


7
投票

在一个模块中可以有任意数量的包。

公共/私人仅适用于一个包。
所有 public 字段、方法和函数均以 uppercase 字符开头。
所有 private 字段、方法和函数均以 lowercase 字符开头。

要将包添加到模块或程序中,只需创建一个小写文件夹并将包名称添加到其中的所有文件即可。这是例子。

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

文件

./foo/foo.go

package foo

import "fmt"

func SomePublicFuncInFoo() {
    somePrivateFuncInFoo()
}

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

文件

./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)
}

文件

./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()
}

1
投票

您可以在 Go 中拥有私有变量和函数,但诀窍是您根本不在结构中定义它们。将它们绑定到闭包的调用堆栈,并且不返回它们。

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())
}
© www.soinside.com 2019 - 2024. All rights reserved.