通过公共函数暴露私有类型

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

exposing a private type through a public function

问题

我正在测试Go语言的类型可见性,并在通过公共函数公开私有类型时遇到了意外的行为:

package pak

type foo struct { // 不应该对除了pak之外的任何其他包可见
	Bar string
}

func NewFoo(str string) *foo {
	return &foo{Bar: str}
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package main

import (
	"fmt"
	"pak"
)

func main() {
	// 这两行应该是等价的...
	var f = pak.NewFoo("Hello, World!")			// 这个可以正常工作...
	var f *pak.foo = pak.NewFoo("Hello, World!") // 错误:无法引用未导出的名称pak.foo
	
	fmt.Printf("%T\n", f)
	fmt.Printf("%s\n", f.Bar)  // 如果它看不到pak.foo,它是如何知道.Bar的存在的?
}

在没有显式声明f的类型时,它打印出:

*pak.foo
Hello, World!

但是使用*pak.foo时,它无法编译通过。

为什么两种情况下都没有失败?

英文:

I was testing go's type visibility and received unexpected behavior when I exposed a private type through a public function:

package pak

type foo struct { // shoudn't be visible to any other package than pak
	Bar string
}

func NewFoo(str string) *foo {
	return &foo{str}
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

package main

import (
	"fmt"
	"pak"
)

func main() {
	// these lines should be equivalent...
	var f = pak.NewFoo("Hello, World!")			// this works fine...	
	var f *pak.foo = pak.NewFoo("Hello, World!") // ERROR: cannot refer to unexported name pak.foo
	
	fmt.Printf("%T\n", f)
	fmt.Printf("%s\n", f.Bar)  // how does it know about .Bar, if it can't see pak.foo?
}

Without explicitly declaring the type of f, it prints:

*pak.foo
Hello, World!

but with *pak.foo it fails to compile.

Why doesn't it fail in both cases?

(this question is sort of related, but it does not answer this question)

答案1

得分: 3

有效的语句

var f = pak.NewFoo("test")

struct foo提供了一个匿名的、隐藏的地址。你不能在pak包之外使用它来读取或写入struct foo。你可以使用它来调用pak包的方法。例如,

p := f.PakMethod()

无效的语句

var f *pak.foo = pak.NewFoo("test")

试图获取struct foo的地址。如果允许,这将允许你在pak包之外读取和写入struct foo

英文:

The valid statement

var f = pak.NewFoo("test")

gives you an anonymous, hidden address for the struct foo. You can't use it to read from or write to the struct foo outside the pak package. You can, and usually will, use it to call a pak package method. For example,

p := f.PakMethod()

The invalid statement

var f *pak.foo = pak.NewFoo("test")

attempts to obtain the address of the struct foo. If permitted, this would allow you to read from and write to the struct foo outside the pak package.

huangapple
  • 本文由 发表于 2013年3月28日 03:41:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/15667963.html
匿名

发表评论

匿名网友

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

确定