Go语言学习之路-2-变量与常量

标识符

定义变量时,我们定义了: name、age 这样的名字,它们都是程序员自己起的,能够表达出变量的作用,这叫做标识符(Identifier

标识符就是程序员自己起的名字,名字也不能随便起,要遵守规范,在Go语言中标识符由

  • 只能以“字母”和“_”开头
  • 由“字母”、“数字”、“_”组成

Go语言保留的标识符,25个相对其他语言来很少

funcreturndefergoif
elseforrangecontinuegoto
breakswitchselectcasedefault
chanfallthroughpackageimportvar
consttypeinterfacemapstruct

关键字

关键字(Keywords)是由Go语言规定的具有特定意义的字符串,通常也称为保留字,例如 int、string、float64 等。

我们定义的标识符不能与关键字相同,否则会出现错误。---> 你也可以将关键字理解为具有特殊含义的标识符,它们已经被系统使用,我们不能再使用了。

内建常量:

true false iota

内建变量:

nil

内建类型:

int       int8          int16        int32    int64    uint
uint8     uint16        uint32       uint64   uintptr  float32 
float64   complex128    complex64    bool     byte     rune 
string    error

内建函数:

make      len       cap        new    append    copy    close
delete    complex   real       imag   panic     recover

更多:https://golang.org/pkg/builtin/#pkg-variables

变量与常量

从字面意思理解一个是变化、一个是常态的

变量

什么是变量

我们的程序运行的时候都是存储在内存中的,要想从内存中取出数据的先知道数据存放在哪里!内存地址类似与0x00000000,如果让你在代码中这么使用数据感觉如何?

  • 可读性差
  • 不易维护

Go语言帮我们做了个映射你不需要管数据存在哪里,你只需要知道怎么给数据取个名字并用这个名字进行数据的操作即可

好比有人问你家住哪里?

你说:北纬:xxx°7'5" 东经 xxx°15’29" ---->坐标系统(是描述物质存在的空间位置)

我的天啊谁记得住,变量就好比地名了:我家住:北京_XXXX小区

变量类型

每个变量都有一个类型,这个类型的作用对我们而言就是帮助开发者规避一些错误

举个例子来说:你是男生你只能去男生宿舍 , 你是女生只能进女生宿舍 , 给宿舍定义一个类型,就不容出现混乱男生跑女生宿舍区 - - !

变量声明

Go语言中要使用一个变量需要先声明这个变量,同一个作用域不能有相同的变量。 好比有一块地,你的先命名了【某某某小区】,以后用的时候XX小区就是去这块地

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

# var 变量名 变量类型

var name string
var age int
var isMan bool

批量变量声明:每个变量都写个var看着有点乱且繁琐可以简化为下面的方式

var (
    name string
    age int
    isMan bool
)

变量初始化

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

  • int、float32/64 默认是0
  • string 默认是空字符串

  • bool 默认是false

  • pointer, function, interface, slice, channel, map 对于复合类型, go语言会自动递归地将每一个元素初始化为其类型对应的默认值
# var 变量名 类型 = 表达式
var name string = "帅哥"
var age int = 18

# 一次初始化多变量
var name, age = "帅哥", 18

类型推导

有时候我们会将变量的类型省略,这个时候编译器会根据等号右边的值来推导变量的类型完成初始化

# var 变量 = 表达式
var name = "帅哥"
var age = 18

简短声明

函数内部,可以使用更简短的 := 方式声明并初始化变量

package main

import "fmt"

func main() {
    name := "帅哥"
    age := 18
    fmt.Println(name, age)
}

匿名变量(没有名字的变量)

如果想忽略某个值可以使用,匿名变量(anonymous variable)匿名变量用一个下划线"_"表示,例如

例1:

package main

import "fmt"

func main() {
    // 给3这个值声明并赋值给一个: 匿名变量(标识忽略它)
    a, b, _ := 1, 2, 3

    fmt.Println(a, b)
}

例2:

package main

import "fmt"

func main() {
    // 函数echo返回两个值,我们把第一个值赋值给name
    // 第二个值赋值给匿名变量
    name, _ := echo()

    fmt.Println(name)
}

func echo() (string, int) {
    return "帅哥", 18
}

小结:

  • 函数外的每个语句都必须以关键字开始(var、const、func等)
  • 变量不能和Go保留的标识符和关键字相同(简单记下就成后续随着使用慢慢就知道哪些了,一般编译器都会提示)
  • ":=" 简短声明只能在函数内部使用
  • "_" 匿名变量多用于忽略某个值

常量

常量与变量的区别

  • 变量声明的时候使用var,常量声明的时候使用const
  • 变量声明的时候可以不用赋值(var name string),常量声明的时候必须赋值(const WEB_SITE string = "https://www.toutiao.com/")
  • 变量在程序运行期间是允许修改变量的值,常量不允许修改
package main

import "fmt"

const PROJECT_NAME = "project"

// 可以同时定义多个常量
const (
    LISTING_PORT = 80
    LOG_PATH     = "/opt/project/log/"
)

func main() {
    // WEB_SITE = 10
    fmt.Println(LISTING_PORT, LOG_PATH, PROJECT_NAME)
}

定义常量组时,如果不提供初始值,则表示将使用上行的表达式

package main

import "fmt"


const (
    // 定义常量组时,如果不提供初始值,则表示将使用上行的表达式
    N1 = 10
    N2
    N3
    N4 = 20
    N5
    N6
)

func main() {
    fmt.Println(N1,N2,N3,N4,N5,N6)
}


// 结果:10 10 10 20 20 20

iota常量计数器

  • iota是常量的计数器,从0开始,常量组中每定义一个常量,自动递增1(例子1)
  • 每遇到一个const关键字(常量组外),iota就会重置为0(例子2)
  • 常用:常量组内如果省略了值,默认使用上一个表达式(例子3)自动枚举
  • 其他例子

iota是常量的计数器,从0开始,组中每定义一个常量,自动递增1

package main

import "fmt"

const (
    N1 = iota
    N2
    N3
)

func main() {
    fmt.Println(N1,N2,N3)
}

// 输出:0 1 2

应用场景

package main

import "fmt"

const (
        // KB,MB,GB,TB通过计数来得出实际的值
        _  = iota
        KB = 1 << (10 * iota) // 1 向左移动10位 10 * iota = 10 * 1
        MB                    // 1 向左移动20位 10 * iota = 10 * 2
        GB
        TB
)

func main() {
        fmt.Println(KB, MB, GB, TB)
        // 1024 1048576 1073741824 1099511627776
}

每遇到一个const关键字(常量组外),iota就会重置为0

package main

import "fmt"

const (
    N1 = 10
    N2
    N3
    N4 = iota
    N5
    N6
)
const (
    L1 = iota
    L2
    L3
    L4
)

func main() {
    fmt.Println(N1, N2, N3, N4, N5, N6)
    fmt.Println(L1, L2, L3, L4)
}

// 输出:
// 10 10 10 3 4 5
// 0 1 2 3

常量组内如果省略了值,默认使用上一个表达式

package main

import "fmt"

const (
    // 输出偶数
    N0 = iota * 2
    N1
    N2
    N3
    N4
)

func main() {
    fmt.Println(N0, N1, N2, N3, N4)
}

// 输出:0 2 4 6 8

其他例子

跳过某个值

package main

import "fmt"

const (
    N0 = iota * 2
    N1 = 10
    N2
    // 跳过某个值
    _
    N4
)

func main() {
    fmt.Println(N0, N1, N2, N4)
}

声明插队并通过iota进行续接

package main

import "fmt"

const (
    N0 = iota
    N1 = 10
    N2 = iota
    N3
    N4
)

func main() {
    fmt.Println(N0, N1, N2, N4)
}

//输出:0 10 2 4