变量
变量可以通过变量名访问。Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。
声明变量的一般形式是使用 var 关键字:
var 变量名 变量类型也可以一次声明多个变量
var 变量名1,变量名2 变量类型package main
import "fmt"
func main() {
   var a string = "zouzou"  // 定义了个变量 a,类型为 string,值为 邹邹
   fmt.Println(a)
   var b, c int = 1, 2 // 定义了两个变量 b 和 c,类型为 int,b 的值为 1,c 的值为 2
   fmt.Println(b, c)
}结果
zouzou
1 2如果没有初始化,则变量默认为零值
零值就是变量没有做初始化时系统默认设置的值。
package main
import "fmt"
func main() {
   // 声明一个变量并初始化
   var a = "zouzou"
   fmt.Println(a)
   // 没有初始化就为零值
   var b int
   fmt.Println(b)
   // bool 零值为 false
   var c bool
   fmt.Println(c)
}结果
zouzou
0
false零值的有
- 数值类型(包括complex64/128)为 0
 - 布尔类型为 false
 - 字符串为 ""(空字符串)
 - 以下几种类型为 nil:
 
var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error 是接口类型推导
如果声明了一个变量,没有声明类型,会根据值进行类型推导
package main
import "fmt"
func main() {
   var d = true // 没有声明类型,会自动推导
   fmt.Println(d)
}结果
true如果变量已经使用 var 声明过了,再使用 := 声明变量,就产生编译错误,格式
v_name := value例如
var intVal int 
intVal :=1 // 这时候会产生编译错误,因为 intVal 已经声明,不需要重新声明直接使用下面的语句即可:
intVal := 1 // 此时不会产生编译错误,因为有声明新的变量,因为 := 是一个声明语句intVal := 1
var intVal int 
intVal =1可以将 var f string = "zouzou" 简写为 f := "zouzou":
package main
import "fmt"
func main() {
   f := "zouzou" // 等价于 var f string = "zouzou"
   fmt.Println(f)
}还有其他的声明方式
package main
var x, y int
var ( // 这种因式分解关键字的写法一般用于声明全局变量
   a int
   b bool
)
var c, d int = 1, 2
var e, f = 123, "hello"
//这种不带声明格式的只能在函数体中出现
//g, h := 123, "hello"
func main() {
   g, h := 123, "hello"
   println(x, y, a, b, c, d, e, f, g, h)
}使用 := 赋值操作符
我们知道可以在变量的初始化时省略变量的类型而由系统自动推断,声明语句写上 var 关键字其实是显得有些多余了,因此我们可以将它们简写为 a := 50 或 b := false。
a 和 b 的类型(int 和 bool)将由编译器自动推断。
这是使用变量的首选形式,但是它只能被用在函数体内,而不可以用于全局变量的声明与赋值。使用操作符 := 可以高效地创建一个新的变量,称之为初始化声明。
常量
常量是一个简单值的标识符,在程序运行时,不会被修改的量。
常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
常量的定义格式:
const 常量名 [type] = value你可以省略类型说明符 [type],因为编译器可以根据变量的值来推断其类型。
- 显式类型定义: 
const b string = "abc" - 隐式类型定义: 
const b = "abc" 
package main
import "fmt"
func main() {
   const LENGTH int = 10           // 常量 LENGTH
   const WIDTH int = 5             // 常量 WIDTH
   var area int                    // 变量
   const a, b, c = 1, false, "zou" //多重赋值
   area = LENGTH * WIDTH
   fmt.Printf("面积为 : %d", area)
   println()
   println(a, b, c)
}结果
面积为 : 50
1 false zou在常量组中,如果不指定类型和值,则和上一行的类型还有值都一样
package main
import "fmt"
func main() {
   // 常量组如果不指定类型和值,则和上一行的类型的值一样
   const (
      x int = 10
      y
      a = "abc"
      b
   )
   fmt.Print(x, y, a, b)
}结果
10 10 abc abciota
- iota,特殊常量,可以认为是一个可以被编译器修改的常量。
 - iota 只能在常量组中使用
 - 不同的 const 块中互相不影响
 - 从第一行开始,每一行 iota 都会加 1
 
iota 可以被用作枚举值:
const (
    a = iota // iota = 0
    b = iota // iota = 1,每一行 iota 加 1
    c = iota // iota = 2,每一行 iota 加 1
)第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;所以 a=0, b=1, c=2 可以简写为如下形式:
const (
    a = iota
    b
    c
)看下面的例子
package main
import "fmt"
func main() {
   const (
      a    = iota       // 0
      b    = 10         // iota = 1
      c                 // 和上一行的值相等
      d, e = iota, iota // iota = 3,所以 d、e 都等于 3
      f    = iota       // iota = 4
   )
   fmt.Println(a, b, c, d, e, f)
}结果
0 10 10 3 3 4例子二
package main
import "fmt"
func main() {
   const (
      a = iota // 0
      b        // 1
      c        // 2
      d = "ha" //独立值,iota = 3
      e        //没有值和上一行的值相等 "ha"   iota = 4
      f = 100  //iota = 5
      g        //没有值和上一行的值相等 100  iota = 6
      h = iota // 7,恢复计数
      i        // 8
   )
   fmt.Println(a, b, c, d, e, f, g, h, i)
}输出结果
0 1 2 ha ha 100 100 7 8作用域
package main
import "fmt"
func main() {
   name := "zouzou" // 只在当前的 {} 里有效
   fmt.Println(name)
   if true {
      fmt.Println(name)
      age := 18 // 只在当前的 {} 里有效
      fmt.Println(age)
      name := "邹邹"
      fmt.Println(name)
   }
   println(name)
   //fmt.Println(age) 错误,因为 age 是局部变量
}结果
zouzou
zouzou
18
邹邹
zouzou- 全局变量,未写在函数中的变量称为全局变量;不可以使用
v1:=xx方式进行简化;可以基于因式分解方式声明多个变量; - 局部变量,编写在 {} 里面的变量;可以使用任意方式简化;可以基于因式分解方式声明多个变量;
 
package main
import "fmt"
// 全局变量(不能以省略的方式)
var school string = "北京大学" // 可以
//var school = "北京大学"   // 可以
//school := "北京大学"         // 不可以,不能简写
var ( // 全局变量
   v1 = 123
   v2 = "你好"
   v3 int
)
func main() {
   name := "zouzou" // 局部变量
   fmt.Println(name)
   if true {
      age := 18    // 局部变量
      name := "邹邹" // 局部变量
      fmt.Println(age)
      fmt.Println(name)
   }
   fmt.Println(name)
   fmt.Println(school)
   fmt.Println(v1, v2, v3)
}结果
zouzou
18
邹邹
zouzou
北京大学
123 你好 0赋值与内存相关
name := "zouzou"如上代码,定义了一个变量,会在内存中开辟出一块地址,赋值给变量 name

name := "zouzou"
nickname := name如上如果定义了一个变量 name,在定义了一个变量 nickname,将 name 赋值给 nickname。在 go 中,会将 name 的拷贝一份,如下

package main
import "fmt"
func main() {
   name := "zouzou"
   nickName := name
   fmt.Println(name, &name)         // &name 是 name 变量的内存地址
   fmt.Println(nickName, &nickName) // &nickName 是 nickName 变量的内存地址
}结果
zouzou 0xc000010250
zouzou 0xc000010260可以看到,我们把一个变量赋值给另一个变量后,内存地址是不一样的,因为会新开辟一块内存地址。不像 python 语言,会指向同一块内存地址
例子
package main
import "fmt"
func main() {
   name := "zouzou"
   nickName := name
   fmt.Println(name, &name)
   fmt.Println(nickName, &nickName)
   name = "daliu" // 修改了name 的值,但是内存地址还是之前的,只是在之前的内存地址上修改了值
   fmt.Println(name, &name)
   fmt.Println(nickName, &nickName) // 值类型,会拷贝一份
}结果
zouzou 0xc000010250
zouzou 0xc000010260
daliu 0xc000010250
zouzou 0xc000010260可以看到,当我们改变变量的值后,内存地址没有变,只是改变了内存地址里对应的数据。而赋值后的变量 nickName 是不会变的,因为是新开辟的内存地址,没有改变这个内存地址的值
注意:使用 int、string、bool、数组 这几种数据类型时,如果遇到变量的赋值则会拷贝一份。【值类型】
    
    









