Go编程 – 使用指针绕过访问权限

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

Go Programming - bypassing access privileges using pointers

问题

让我们假设我有以下项目的层次结构:

fragment/fragment.go
main.go

fragment.go中,我有以下代码,其中有一个getter和没有setter:

package fragment

type Fragment struct {
    number int64   // 私有变量 - 小写
}

func (f *Fragment) GetNumber() *int64 {
    return &f.number
}

在main.go中,我创建了一个Fragment并尝试在没有setter的情况下更改Fragment.number

package main

import (
    "fmt"
    "myproject/fragment"
)

func main() {
    f := new(fragment.Fragment)

    fmt.Println(*f.GetNumber()) // 打印0

    //f.number = 8 // 错误 - number是私有的

    p := f.GetNumber()
    *p = 4                      // 成功。现在f.number是4
    fmt.Println(*f.GetNumber()) // 打印4
}

因此,通过使用指针,我在fragment包之外更改了私有变量。我理解,在例如C中,指针有助于避免复制大型结构/数组,并且它们应该使您能够更改它们指向的任何内容。但是,我不太明白它们如何与私有变量一起使用。

所以我的问题是:

  1. 私有变量不应该保持私有吗,无论如何访问它们?
  2. 这与其他语言(如C++/Java)相比如何?在那些语言中,私有变量是否可以使用指针在类之外更改?

背景:我了解一些C/C++,对Python相当流利,对Go还不太熟悉。我以业余爱好的方式学习编程,所以对幕后发生的技术事务了解不多。

英文:

Let's say I have the following hierarchy for my project:

fragment/fragment.go
main.go

And in the fragment.go I have the following code, with one getter and no setter:

package fragment

type Fragment struct {
    number int64   // private variable - lower case
}

func (f *Fragment) GetNumber() *int64 {
    return &f.number
}

And in the main.go I create a Fragment and try to change Fragment.number without a setter:

package main

import (
    "fmt"
    "myproject/fragment"
)

func main() {
    f := new(fragment.Fragment)

    fmt.Println(*f.GetNumber()) // prints 0

    //f.number = 8 // error - number is private

    p := f.GetNumber()
    *p = 4                      // works. Now f.number is 4
    fmt.Println(*f.GetNumber()) // prints 4
}

So by using the pointer, I changed the private variable outside of the fragment package. I understand that in for example C, pointers help to avoid copying large struct/arrays and they are supposed to enable you to change whatever they're pointing to. But I don't quite understand how they are supposed to work with private variables.

So my questions are:

  1. Shouldn't the private variables stay private, no matter how they are accessed?
  2. How is this compared to other languages such as C++/Java? Is it the case there too, that private variables can be changed using pointers outside of the class?

My Background: I know a bit C/C++, rather fluent in Python and new to Go. I learn programming as a hobby so don't know much about technical things happening behind the scenes.

答案1

得分: 8

没有绕过任何访问权限。如果你从任何导入的包中获取了T,那么你总是可以改变T,也就是整个指针,就像赋值一样。导入包的设计者控制你可以从包中获取什么,所以访问控制不是你的。

上述限制适用于结构化类型(structs),在这种情况下,前面的情况仍然成立,但是对于特定字段的访问控制的细粒度由字段的名称大小写控制,即使通过指向整个结构的指针引用。字段名称必须大写才能在其包外可见。

关于C++:我相信你可以用C++的几十种指针类型之一实现相同的功能。不过我不确定是哪一种。

关于Java:不,Java没有指针。与Go(C、C++等)中的指针没有真正可比性。

英文:

You're not bypassing any access privilegies. If you acquire a *T from any imported package then you can always mutate *T, ie. the pointee at whole, as in an assignment. The imported package designer controls what you can get from the package, so the access control is not yours.

The restriction to what's said above is for structured types (structs), where the previous still holds, but the finer granularity of access control to a particular field is controlled by the field's name case even when referred to by a pointer to the whole structure. The field name must be uppercase to be visible outside its package.

Wrt C++: I believe you can achieve the same with one of the dozens C++ pointer types. Not sure which one, though.

Wrt Java: No, Java has no pointers. Not really comparable to pointers in Go (C, C++, ...).

huangapple
  • 本文由 发表于 2013年5月21日 03:47:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/16657201.html
匿名

发表评论

匿名网友

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

确定