通过公共功能公开私有类型

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
", f)
    fmt.Printf("%s
", 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)

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.