何时需要初始化 Golang 变量?

7

在Golang中有几种类型的变量:

  1. 全局变量:var a int
  2. 局部变量:func hello() { var a int }
  3. 返回值变量:func hello() (a int) {}

Golang有时会自动初始化某些变量,但我不知道是何时和为什么?这让我感到困惑。

例如:

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
}

在使用之前,我应该初始化哪一个?

2个回答

14

Golang会初始化所有变量(不是“有时”,也不是“一些”):

在您的代码中:

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

您传递了一个空指针,但您需要一个由a指向的值,而不是一个空指针:
因此,您可以创建一个值,然后将该值的地址存储在a中:
当你使用var a *Userfunc bar(bts []byte) (a *User)时:
a是指向User类型的指针,并且它被初始化为其零值,即nil,参见(The Go Playground):
package main

import "fmt"

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

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

输出:

(*main.User)(nil)

你可以使用a = &User{}来初始化它,就像这个可工作的代码(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\n\n", u) // &main.User{Name:"Alex", Age:3}

    u, err = bar([]byte(str))
    if err != nil {
        panic(err)
    }
    fmt.Printf("%#v\n\n", u) // &main.User{Name:"Alex", Age:3}

}

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

输出:

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

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

变量声明

变量声明创建一个或多个变量,将相应的标识符绑定到它们上面,并为每个变量指定类型和初始值

初始值(零值)

当为变量分配存储空间时,可以通过声明或调用new,或创建一个新值(例如使用组合字面量或调用make)进行分配。如果没有提供明确的初始化,则该变量或值将被赋予默认值。这样变量或值的每个元素都会设置为其类型的零值:false表示布尔值,0表示整数,0.0表示浮点数,""表示字符串,而指针、函数、接口、切片、通道和映射等则会被设置为nil。此初始化是递归完成的,因此,如果未指定值,则结构体数组的每个元素的字段都将被清零。
请参阅func Unmarshal(data []byte, v interface{}) error文档:
解组(Unmarshal)函数可以解析JSON编码的数据,并将结果存储在指向v的值中。

4
Go是一种非常一致的语言:它始终自动初始化变量:

通过在表达式中引用变量来检索变量的值;它是分配给变量的最新值。如果一个变量还没有被赋值,那么它的值就是它所属类型的零值。

零值如下:

数值类型为 0

布尔类型为 false

字符串为空字符串 ""

对于映射、切片、指针和接口,零值为 nil
对于自定义类型,惯用法(即通常认为最佳实践)是使零值以某种方式有用,通常作为默认值或重要标记。

编辑:你的例子不会崩溃。也许你从中删除的东西导致了崩溃?


抱歉,我在示例中使用接口只是作为占位符,真正的接口是自定义结构。 - Allen Heavey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接