一个结构体的私有字段和方法

huangapple go评论70阅读模式
英文:

Private fields and methods for a struct

问题

在下面的测试代码中,我希望mytypedoPrivate方法都是私有的,只有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")
}

sizehash字段以及doPrivate方法应该被封装起来,其他类型不应该能够访问它们。

英文:

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.

答案1

得分: 117

在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.

答案2

得分: 87

在Go语言中,"privacy"的工作方式并不是这样的:隐私的粒度是包级别的。

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

但这并不是通常的做法。关于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.

答案3

得分: 38

你可以创建一个接口来暴露你希望公开的方法,并且只有在将对象包装到该接口中时才能访问该对象。

package main

type mytype struct {
    size string
    hash uint32
}

// 暴露方法的接口
type myinterface interface {
    do() string
}

// 构造函数(可选)
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() {
    // 使用构造函数
    t := newMytype("100", 100)
    t.do()
    // t.doPrivate() // t.doPrivate 未定义(类型 myinterface 没有字段或方法 doPrivate)

    // 不使用构造函数
    t2 := myinterface(&mytype{"100", 100})
    t2.do()
    // t.doPrivate() // t.doPrivate 未定义(类型 myinterface 没有字段或方法 doPrivate)
}

你可以在 这里 查看代码的运行示例。

英文:

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

答案4

得分: 14

在Go语言中,你无法做到这一点。可见性仅限于每个包级别。但你可以将你的包拆分成两个。

英文:

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

答案5

得分: 3

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

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

要将包添加到你的模块或程序中,只需创建一个小写的文件夹,并将包名添加到其中的所有文件中。以下是一个示例。

./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 // 以大写字母开头
	myPrivateField string // 以小写字母开头
}

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" // 这一行应该由你的IDE添加
)

func main() {

	foo.SomePublicFuncInFoo()

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

	myStruct.SomePublicMethod()
}
英文:

In one module there can be any number of packages.

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

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 &quot;fmt&quot;

func SomePublicFuncInFoo() {
	somePrivateFuncInFoo()
}

func somePrivateFuncInFoo() {
	fmt.Println(&quot;somePrivateFuncInFoo call&quot;)
}

file ./foo/MyStruct.go:

package foo

import &quot;fmt&quot;

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

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

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

func (self *MyStruct) privateMethod() {
	fmt.Println(&quot;MyStruct&quot;, self.MyPublicField, self.myPrivateField)
}

file ./main.go:

package main

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

func main() {

	foo.SomePublicFuncInFoo()

	myStruct := foo.NewMyStruct(&quot;string1&quot;, &quot;string2&quot;)
	fmt.Println(&quot;myStruct.MyPublicField=&quot;, myStruct.MyPublicField)

	myStruct.SomePublicMethod()
}

答案6

得分: 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())
}
英文:

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 (
    &quot;fmt&quot;
)

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(&quot;100&quot;, 100)
    fmt.Println(instance.Do())
}

huangapple
  • 本文由 发表于 2014年3月3日 21:32:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/22148143.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定