作为参数传递时结构成员的作用域可见性?

While calling json.Decoder.Decode by passing a struct, for instance

type _Sample struct {
    first string // this will not be filled because it starts with lower case letter
    Second string // it is OK. 
}

...
var sample _Sample
err := decoder.Decode(&sample)

According to the Language Specification that writes:

Exported identifiers ¶

An identifier may be exported to permit access to it from another package. An identifier is exported if both:

  • the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); and
  • the identifier is declared in the package block or it is a field name or method name.

All other identifiers are not exported.

The question is the struct _Sample is not exported, why it is visible by the package json?

Access permission is checked when

  1. You're creating/declaring a variable. The compiler will check the visibility of the name of the type identifier.
  2. Using reflect package to modify a variable.
  3. Calling a constant, global variable, or a function. The visibility of constant/variable/function name will be checked.

Once the variable is created/defined, and when you pass this variable as a function/method argument, the copy (If it is a value, the value is being copied. If it is a pointer, the address is being copied) will be passed to the function/method, and always accessible from the function body through the argument name and type. In encoding/json package, the Decoder.Decode method is defined as,

func (dec *Decoder) Decode(v interface{}) error

thus, anything you passed to the Decoder.Decode method, is always accessible from inside the method body through argument v. Note that the type of v is interface{} not _Sample struct. The visibility is checked when you defined the variable as

var sample _Sample

which was OK since it is done from within the same package. Even an anonymous struct (i.e. no type name identifier is defined for the struct)

aSample := struct {
    first  string // this will not be filled because it starts with lower case letter
    Second string // it is OK.
}{}

//...
err := decoder.Decode(&aSample)

will works. Next, when the decoder fills the struct (through reflection), the visibility of struct members will be checked, and _Sample.first is not visible from inside the json package.