什么时候应该初始化Golang变量

There are some kind of variables in Golang:

  1. global variable: var a int
  2. local variable: func hello() { var a int }
  3. return variable: func hello() (a int) {}

Golang sometimes will auto-init some variables,
but I don't know when and why? It confused me.

Example:

type User struct {
  Name string `json:"name"`
  Age  int    `json:"age"`
}

func foo(bts []byte) {
  var a User
  err := json.Unmarshal(bts, &a)  // It's ok
}

func bar(bts []byte) (a *User) {
  err := json.Unmarshal(bts, a) // It will crash
}

which one should I have to initialize before use?

Golang will init all variables (not sometimes, not some):

In your code:

func bar(bts []byte) (a *User) {
  err := json.Unmarshal(bts, a) // It will crash
}

You passed a nil pointer but you need a value pointed to by a , not a nil pointer:
So you may create a Value then store the address of this Value inside a:


When you use var a *User or func bar(bts []byte) (a *User):
The a is a pointer to the User type, and it is initialized to it's zero value, which is nil,
see (The Go Playground):

package main

import "fmt"

func main() {
    var a *User
    fmt.Printf("%#v

", a)    
}

type User struct {
    Name string `json:"Name"`
    Age  int    `json:"Age"`
}

output:

(*main.User)(nil)

And You may use a = &User{} to initialize it, like this working code (The Go Playground):

package main

import (
    "encoding/json"
    "fmt"
)

func foo(bts []byte) (*User, error) {
    var a User
    err := json.Unmarshal(bts, &a) // It's ok
    return &a, err
}

func bar(bts []byte) (a *User, err error) {
    a = &User{}
    err = json.Unmarshal(bts, a) // It's ok
    return
}
func main() {
    str := `{ "Name": "Alex", "Age": 3 }`
    u, err := foo([]byte(str))
    if err != nil {
        panic(err)
    }
    fmt.Printf("%#v

", u) // &main.User{Name:"Alex", Age:3}

    u, err = bar([]byte(str))
    if err != nil {
        panic(err)
    }
    fmt.Printf("%#v

", u) // &main.User{Name:"Alex", Age:3}

}

type User struct {
    Name string `json:"Name"`
    Age  int    `json:"Age"`
}

output:

&main.User{Name:"Alex", Age:3}

&main.User{Name:"Alex", Age:3}

Variable declarations:

A variable declaration creates one or more variables, binds corresponding identifiers to them, and gives each a type and an initial value.

The initial value (zero value):

When storage is allocated for a variable, either through a declaration or a call of new, or when a new value is created, either through a composite literal or a call of make, and no explicit initialization is provided, the variable or value is given a default value. Each element of such a variable or value is set to the zero value for its type: false for booleans, 0 for integers, 0.0 for floats, "" for strings, and nil for pointers, functions, interfaces, slices, channels, and maps. This initialization is done recursively, so for instance each element of an array of structs will have its fields zeroed if no value is specified.

And see func Unmarshal(data []byte, v interface{}) error Docs:

Unmarshal parses the JSON-encoded data and stores the result in the value pointed to by v.

Go is a very consistent language: it always automatically initializes variables:

A variable's value is retrieved by referring to the variable in an expression; it is the most recent value assigned to the variable. If a variable has not yet been assigned a value, its value is the zero value for its type.

The zero value is:

0 for numeric types,

false for the boolean type, and

"" (the empty string) for strings.

In the case of maps, slices, pointers, and interfaces, the zero value is nil.

For custom types, it is idiomatic (i.e. generally considered best practice) to make the zero value useful somehow, usually as a default value or important sentinel.


Edit: your example does not crash. Maybe one of the things you removed from it was causing the crash instead?