结构的私有字段和方法

and*_*fox 40 go

在下面的测试代码中,我希望将两者mytypedoPrivate方法都设置为私有,以便只有成员mytype可以访问它,而不是mypackage包的范围内的其他类型\函数.

我可以在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")
}
Run Code Online (Sandbox Code Playgroud)

sizehash以及该doPrivate方法应该被封装并没有其他类型应有权访问它们.

nos*_*nos 54

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

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

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


Den*_*ret 44

这并不是Go中"隐私"的工作原理:隐私的粒度就是包.

如果您真的mytype想要访问某些字段的成员,那么您必须将结构和函数隔离在它们自己的包中.

但这不是通常的做法.Go是否是OOP是值得商榷的,但很明显,这种做法不是通过你似乎想要做的结构来封装代码.通常,程序包足够小,可以保持一致:如果您不想访问程序包中的字段,请不要访问它们.

  • 我建议你阅读Go的一些主要标准包的代码.是的,整个包裹.您会对这个选择允许的清晰度和简洁性感到惊讶.不要试图在Go中模仿另一种语言. (16认同)
  • 好吧,糟透了:)封装是现代编程的支柱之一.它将强制每个"类"创建一个包.我想知道它背后的设计决定是什么. (11认同)
  • 但是,一句话,"如果你不想从包中访问字段,不要访问它们"这句话 - 你可以说一般关于封装,但这并不能解决任何问题.似乎Golang将抽象从类范围转移到包范围.在我看来,它可能使程序难以维护.就像JavaScript中的模块一样(私有字段除外). (10认同)
  • 好的一点,我不喜欢也不理解为什么人们在JavaScript中模仿"类"或"经典继承".在这个时间点,似乎有线. (5认同)
  • 隐含的推理背后是包装简单而且足够小,因此没有一致性问题,也不需要内部隐私强制执行.如果你觉得它更难维护,也许你的包装太大了.当然,我们在这里的意见和不同的程序员实践和经验. (4认同)
  • 这样的事情应该是语言的一部分。稍后加入团队的软件设计和开发人员会很感激,他们不必处理熔岩流、重复的巨型泥球整体应用程序 (2认同)

Far*_*d T 16

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

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)
}
Run Code Online (Sandbox Code Playgroud)

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

  • 在所有答案中,这个答案结合了世界上最好的答案,应该更高。正确的编程确实涉及接口,因此更有理由使用它们。做得很好! (7认同)

Vol*_*ker 8

你不能在Go中这样做.可见性仅适用于每个包级别.但是你可以将你的包分成两部分.


Lex*_*Lex 7

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

公共/私有仅适用于一个包。
所有公共字段、方法和函数均以大写字符开头。
所有私有字段、方法和函数均以小写字符开头。

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

./main.go
./foo/foo.go
./foo/MyStruct.go
Run Code Online (Sandbox Code Playgroud)

文件./foo/foo.go

./main.go
./foo/foo.go
./foo/MyStruct.go
Run Code Online (Sandbox Code Playgroud)

文件./foo/MyStruct.go

package foo

import "fmt"

func SomePublicFuncInFoo() {
    somePrivateFuncInFoo()
}

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

Run Code Online (Sandbox Code Playgroud)

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

Run Code Online (Sandbox Code Playgroud)