# 变量作用域

作用域: 这个变量在哪个范围内可以被访问到

+ 基础作用域: 块作用域, {}, 在块作用域下的变量都是局部变量

## 局部变量

### 父作用域 不能访问子作用域的变量

```go
{
    {
        var a string
        a = "local var"
        fmt.Println(a)
    }
    // fmt.Println(a)
}

```

### 子作用域可以访问父作用域的变量

```go
{
    var a string
    a = "parent scope"
    {
        fmt.Println(a)
    }
}
```

### 变量值覆盖

子作用域的优先级是高于父作用域的优先级的, 因此子作用域可以覆盖父作用域的变量的值, 但是同一个变量不能声明2次

```go
package main

import "fmt"

func main() {
    var a = "parent"
    fmt.Println("outer:", a) // parent
    {
        a := "child" // 子作用域声明了同名新变量（遮蔽外层 a）
        fmt.Println("inner:", a) // child
    }
    fmt.Println("outer again:", a) // 仍为 parent
}
```

## 全局变量

在函数体外声明的变量称之为全局变量，全局变量可以在整个包甚至外部包（被导出后）使用, 全局变量相当于所有函数的父级变量, 所有函数都能访问

```go
var (
    a = "global parent scope var"
)

func main() {
    fmt.Println(a)
}
```

## 导出与不可导出（可见性）

约定：标识符以大写字母开头表示可导出（可被其他包访问），以小写字母开头表示仅包内可见。

```go
// 包内文件 a.go
package demo

var Exported = "可导出"
var internal = "包内可见"

// 其他包：import demo 后只能访问 demo.Exported
```