2013-03-27 63 views
3

我測試Go的類型的知名度並獲得意外的行爲,當我通過一個公共職能暴露私人類型:通過公共函數暴露私有類型

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? 
} 

沒有顯式聲明的f類型,它打印:

*pak.foo 
Hello, World! 

但與*pak.foo它無法編譯。

爲什麼它在這兩種情況下都失敗?

(這question是有點相關,但它並沒有回答這個問題)

回答

3

有效的聲明

var f = pak.NewFoo("test") 

爲您提供了一個匿名的,隱藏的地址structfoo。您不能使用它讀取或寫入pak包外的structfoo。您可以並且通常會使用它來調用pak包裝方法。例如,

p := f.PakMethod() 

無效語句

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

試圖獲得的structfoo地址。如果允許,這將允許您讀取和寫入pak包外的structfoo

+0

我不知道有匿名類型。但是在'pak'之外讀/寫'struct foo'是有效的。它不是一個純粹的匿名結構/接口,它和'* pak.foo'完全一樣,但是你不能寫它,因爲你看不到'pak.foo'。但是你必須知道'pak.foo'的全部內容,因爲你可以調用它的所有方法,通過參數類型爲'pak.foo'的'pak'中的函數傳遞它,或者訪問這些字段。這似乎對我來說是悖論。無論如何,我認爲公開一個私有結構並沒有什麼意義。 – eber