5.Go语言基础之变量和常量

目录

Go语言基础之变量和常量

标识符

关键字

变量

变量的来历

变量声明

标准声明

批量声明

变量的初始化

变量赋值

批量声明赋值

简短声明

匿名变量

常量

显式类型定义

隐式类型定义

值不可修改

用作枚举

iota

扩展

修改值

修改引用


Go语言基础之变量和常量

变量和常量是编程中必不可少的部分,也是很好理解的一部分。

标识符

在编程语言中标识符就是程序员定义的具有特殊意义的词,比如变量名、常量名、函数名等等。 Go语言中标识符由字母数字和_(下划线)组成,并且只能以字母和_开头。 举几个例子:abc, _, _123, a123

关键字

关键字是指编程语言中预先定义好的具有特殊含义的标识符。 关键字和保留字都不建议用作变量名。

Go 相必于其他编程语言拥有较少的关键字

5.Go语言基础之变量和常量_第1张图片

5.Go语言基础之变量和常量_第2张图片

break        default      func         interface    select
case         defer        go           map          struct
chan         else         goto         package      switch
const        fallthrough  if           range        type
continue     for          import       return       var

此外,Go语言中还有37个保留字。

5.Go语言基础之变量和常量_第3张图片

Constants:    true  false  iota  nil
​
Types:    int  int8  int16  int32  int64  
          uint  uint8  uint16  uint32  uint64  uintptr
          float32  float64  complex128  complex64
          bool  byte  rune  string  error
​
Functions:   make  len  cap  new  append  copy  close  delete
         complex  real  imag
         panic  recover

变量

我们经常看到这样的语句

var username string = "username"

我们来解读一下该语句:

  • var 关键字 用于声明变量

  • username 标识符, 给变量取的名字

  • string 表示该变量只能存储字符串类型的值

  • = 赋值运算符, 表示给一个变量赋

  • "username" 字面量(值), 这个是一个username的字符串

变量的来历

程序运行过程中的数据都是保存在内存中,我们想要在代码中操作某个数据时就需要去内存上找到这个变量,但是如果我们直接在代码中通过内存地址去操作变

的话,代码的可读性会非常差而且还容易出错,所以我们就利用变量将这个数据的内存地址保存起来,以后直接通过这个变量就能找到内存上对应的数据了。

变量声明

Go语言中的变量需要声明后才能使用,同一作用域内不支持重复声明。 并且Go语言的变量声明后必须使用。

标准声明

声明变量的一般形式是使用 var 关键字:

Go语言的变量声明格式为:

var 变量名 变量类型

比如:

var identifier1 string
var identifier2 int
var identifier3 bool

批量声明

如上的例子我们声明变量过多,每次都需要加关键字 var ,go可以使用 () 进行批量申请。

var (
    identifier1 string
    identifier2 int
    identifier3 bool    
)

变量的初始化

Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值

  • 整形(int uint): 0

  • 浮点型(float32 float64): 0

  • 布尔: false

  • 字符串: ""

  • 字符: ''

变量初始化的标准格式如下:

var 变量名 类型 = 表达式

比如

var identifier1 string = "GO-begin"
var identifier2 int = 16
var identifier3 bool = true

变量赋值

变量赋值的语法为

变量名 = 表达式

例如

var a string  // 变量声明
a = "test"    // 变量赋值

有多个变量需要赋值语法为: var1, var2 = value1, value2

var (
    a string
    b int
)
a, b = "string", 10

注意: 由于Go是强类型语言, 因此我们在进行赋值时,只能赋变量声明类型的值,比如下面方式就是错误的:

var a string
a = 10

批量声明赋值

var (
    a string  = "value1"
    b int     = 10
    c float32 = 0.01
)

简短声明

变量的类型使用值类型进行推导,因此我们可以省略类型的定义, 语法格式: a := b

a, b, c := "value1", 10, 0.01

注意: 简单声明只能用于函数内部, 不用用于全局声明

匿名变量

在使用多重赋值时,如果想要忽略某个值,可以使用匿名变量(anonymous variable)。 匿名变量用一个下划线_表示,例如:

func foo() (int, string) {
    return 10, "Go-begin"
}
func main() {
    x, _ := foo()
    _, y := foo()
    fmt.Println("x=", x)
    fmt.Println("y=", y)
}

匿名变量不占用命名空间,不会分配内存,所以匿名变量之间不存在重复声明。 (在Lua等编程语言里,匿名变量也被叫做哑元变量。)

注意事项:

  1. 函数外的每个语句都必须以关键字开始(var、const、func等)

  2. 简单声明只能用于函数内部, 不用用于全局声明

  3. _多用于占位,表示忽略值。

常量

常量是一个简单值的标识符,在程序运行时,不会被修改的量。用于定义不可被修改的的值,需要在编译过程中进行计算,只能为基础的数据类型布尔、 数值、字符串,使用 const 进行常量定义

显式类型定义

一般情况下,我们再定义常量的时候 需要制定常量的类型与值 声明语法如下: const identifier type = value

const PI float32 = 3.14

通变量一样, 常量也支持批量定义:

// 单行的批量定义 只支持同一种类型
const c1, c2 string = "c1", "c2"
​
// 多行的批量定义支持不同类型
const (
    PI     float32 = 3.14
    PILong float64 = 3.14159
)

隐式类型定义

得益于Golang的类型推导, 常量也是可以省略类型的 隐式类型定义语法如下: const identifier = value

const PI = 3.14

批量语法如下:

const (
    PI     = 3.141
    PILong = 3.141592
)

值不可修改

定义多个变量并进行初始化,批量复制中变量类型可省略,并且除了第一个常量值外其他常量可同时省略类型和值,表示使用前一个常量的初始化表达式

常量之间的运算,类型转换,以及对常量调用函数 len、cap、real、imag、complex、unsafe.Sizeof 得到的结果依然为常量

由于常量不能修改,像下面这个就会报错

const (
    a = "sdf"
)
a = "bbb"

用作枚举

比如 我们定义一个性别的枚举

const (
    UNKNOWN = 0 // 保密
    FEMALE = 1  // 女
    MALE = 2      // 男
)

iota

iota是一种特殊常量,可以认为是一个可以被编译器修改的常量

iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)

const (
    UNKNOWN = iota   // UNKNOWN 0 
    FEMALE           // FEMALE +1
    MALE             // MALE   +1
)

如果你不想从0开始计数 你也可以这样写

const (
    UNKNOWN = iota + 5  // UNKNOWN 5
    FEMALE              // FEMALE +1
    MALE                // MALE   +1
)

几个常见的iota示例:

使用_跳过某些值

const (
        n1 = iota //0
        n2        //1
        _
        n4        //3
    )

iota声明中间插队

const (
        n1 = iota //0
        n2 = 100  //100
        n3 = iota //2
        n4        //3
    )
    const n5 = iota //0

定义数量级 (这里的<<表示左移操作,1<<10表示将1的二进制表示向左移10位,也就是由1变成了10000000000,也就是十进制的1024。同理2<<2表示将2的二进制表示向左移2位,也就是由10变成了1000,也就是十进制的8。)

const (
        _  = iota
        KB = 1 << (10 * iota)
        MB = 1 << (10 * iota)
        GB = 1 << (10 * iota)
        TB = 1 << (10 * iota)
        PB = 1 << (10 * iota)
    )

多个iota定义在一行

const (
        a, b = iota + 1, iota + 2 //1,2
        c, d                      //2,3
        e, f                      //3,4
    )

扩展

进程内存结构:

5.Go语言基础之变量和常量_第4张图片

  • 栈:存放基本类型的数据和对象的引用,但对象本身不存放在栈中,而是存放在堆中(new 出来的对象)

  • 堆: 存放用new产生的数据

值类型和引用类型 是什么?

  • 值类型: 这段内存里面存储的是基本类型的数据, 比如 "a", 10, 0.01

  • 引用类型: 这段内存里面存储的是一个地址, 比如 0xc00011e370 0xc00011e380

修改值

比如 下面这段代码中 a, b 10 存在在哪儿? 当执行赋值操作时 都发生了什么?

var a int 
a = 10
​
var b int 
b = 10
​
a = 20

5.Go语言基础之变量和常量_第5张图片

  • 编译器先处理 var a int, 首先它会在栈中创建一个变量为a的引用

  • a = 10,查找栈中是否有10这个值, 没找到,就将10存放进来, 然后让a指向10

  • var b int, 创建一个变量为b的引用

  • b = 10, 查找栈中是否有10这个值, 找到10, 让b指向10

  • a = 20, 查找栈中是否有20这个值, 为找到, 将20放进去, 然后让a指向20

修改引用

看看下面这段代码, 修改了j的值,为啥没修改i的值

i := "this is i"
j := i
j := "this is j"

5.Go语言基础之变量和常量_第6张图片

下面我们修改了j的值, 为啥i的值也被修改了

i := "this is a"
j := &i
*j = "this is j"

你可能感兴趣的:(Go学习之路,golang,go语言,go)