Go中变量与常量的使用,你都知道哪些~

思维导图~

常量

常量是恒定不变的值,多用于定义程序运行期间不会改变的那些值。 常量的声明和变量声明非常类似,需要把var换成了const,常量在定义的时候必须赋值。

go 复制代码
const pi = 3.14
const e = 2.7182

同样,常量也可以批量声明

go 复制代码
const (
    pi = 3.14
    e = 2.7182
)

在使用const声明多个常量时,如果省略初始化值则表示与上一行的常量值相同。

go 复制代码
const (
    a = 1314
    b
    c
)

func main() {
    fmt.Printf("a = %d\n", a)
    fmt.Printf("b = %d\n", b)
    fmt.Printf("c = %d\n", c)
}

// 执行结果
a = 1314
b = 1314
c = 1314

iota

在 Go 语言中,iota 是一个预定义标识符,它是一个常量计数器,只能在常量的表达式中使用。

iota表示一个整数值,在const关键字出现时将被重置为0,const中每新增一行常量声明时,iota计数一次。

iota可以被用于枚举类型(enum)的定义中,用于简化代码并使得代码更加易读。

使用_iota的变化:

go 复制代码
const (
    a = iota
    b
    _
    c
)

func main() {
    fmt.Printf("a = %d\n", a)
    fmt.Printf("b = %d\n", b)
    fmt.Printf("c = %d\n", c)
}

// 执行结果
a = 0
b = 1
c = 3

iota声明中插入其他常量声明:

go 复制代码
const (
    a = iota
    b
    name = "serena"
    c    = iota
)

const d = iota

func main() {
    fmt.Printf("a = %d\n", a)
    fmt.Printf("b = %d\n", b)
    fmt.Printf("c = %d\n", c)
    fmt.Printf("d = %d\n", d)
}

// 执行结果
a = 0
b = 1
c = 3
d = 0

多个iota定义在一行:

go 复制代码
const (
    a, b = iota + 1, iota + 2 // 1, 2
    c, d                      // 2, 3
    e, f                      // 3, 4
)

变量

Golang语言是静态类型语言,因此Go变量有明确的数据类型,编译器也会检查变量类型的正确性。变量需要声明后才能使用,同一作用域内不支持重复声明。 并且Go语言的变量声明后必须使用。

变量声明

Go变量的标准声明如下:

go 复制代码
var 变量名 变量类型

例如,声明一个名为name的变量,该变量的类型为string

go 复制代码
var name string

变量的命名规则遵循驼峰命名法 ,即首个单词小写,每个新单词的首字母大写 ,例如:firstName

另外在变量声明时,可以实现批量声明

go 复制代码
package main

import "fmt"

var (
    a int
    b string
    c float32
)

func main() {
    //%d 整数占位符,%s 字符串占位符, %f 浮点数占位符(默认精度为6)
    fmt.Printf("%d, %s, %f", a, b, c)
}

// 执行结果
0, , 0.000000

变量初始化

当一个变量被声明之后,系统自动赋予它该类型的零值: int 为 0float 为 0.0bool 为 falsestring 为空字符串指针为 nil

go 复制代码
func main() {
    var a int
    var b float32
    var c bool
    var d string
    var e *struct{}
    fmt.Println(a)
    fmt.Println(b)
    fmt.Println(c)
    fmt.Println(d)
    fmt.Println(e)
}

// 执行结果
0
0
false

<nil>

类型推导

当声明且初始化变量时,如果没有指明变量类型,则会在编译时自动推导类型

go 复制代码
func main() {
    var name = "Ming"
    fmt.Printf("%T", name)
}

// 执行结果
string

短变量声明

在Go中可以使用简短格式声明并初始化变量 ,同样,Go在编译时会进行自动推导类型

go 复制代码
变量名 := 值/表达式
name := "value" // name是变量名 "value"可以是值,或者是表达式

使用简短格式声明并初始化变量时,需要注意一下几点

  • 简短格式声明变量时,需要同时显示初始化变量;
  • 简短格式声明变量时,不能提供数据类型,Go 会根据右侧的值自动推断变量的数据类型;
  • 简短格式声明变量只能在函数内使用,不能在函数外使用;

在初始化变量时,不能够重复初始化

go 复制代码
func main() {
    var age int = 10
    // 再次声明并赋值 会报错
    // No new variables on the left side of ':='(左边的变量已经被声明了,不能重复声明)
    age := 20
}

但是有特例,在多个短变量声明和赋值中,至少有一个新声明的变量出现在左值中,即便其他变量名可能是重复声明,编译器也不会报错

go 复制代码
package main

import (
    "fmt"
    "net"
)

func main() {
    connOne, err := net.Dial("tcp", "127.0.0.1:8080")
    connTwo, err := net.Dial("tcp", "127.0.0.1:8080")
    fmt.Println(connOne)
    fmt.Println(connTwo)
    fmt.Println(err)
}

匿名变量

当使用多重变量赋值时,如果不需要接收特定的返回值,可以使用匿名变量,匿名变量以"_"下划线表示,例如:

go 复制代码
func main() {
    //connOne, err := net.Dial("tcp", "127.0.0.1:8080")
    // 如果不想接收err的值,则可以使用匿名变量,_ 表示
    connTwo, _ := net.Dial("tcp", "127.0.0.1:8080")
    fmt.Println(connTwo)
    
}

匿名变量的特点在于既不会分配内存,也不会占用命名空间,可以重复声明使用。

变量作用域

Go 变量的作用域是指变量在程序中的可见性和可用性 ,变量的作用域由其声明的位置确定

函数内部声明 的变量只在函数内部可用,称为局部变量函数作用域变量

函数外部声明 的变量称为全局变量 或包作用域变量,在整个包中都可以被访问和使用。

在函数定义中的变量称为形式参数,简称形参。

Go(静态语言)会在编译时检查每个变量是否使用过,一旦出现未使用的变量,则会出现编译报错。

局部变量

函数体内声明 的变量称为局部变量。该类型变量的作用域为函数体内,在函数中的参数变量和返回值变量都属于局部变量的范畴。

go 复制代码
func main() {
    var num1 int = 10
    var num2 int = 20
    sum := num1 + num2
    fmt.Printf("num1 = %d, num2 = %d, sum = %d\n", num1, num2, sum)
}

// 执行结果
num1 = 10, num2 = 20, sum = 30

全局变量

在函数体外声明的变量称为全局变量,全局变量只需要在一个源文件中定义,就可以在所有源文件中使用

全局变量声明必须以 var 关键字开头

go 复制代码
package main

import "fmt"

// 声明全局变量
var sum int

func main() {
    // 声明局部变量
    var num1, num2 int
    // 初始化参数
    num1 = 10
    num2 = 20
    sum = num1 + num2
    fmt.Printf("num1 = %d, num2 = %d, sum = %d", num1, num2, sum)
}

// 执行结果
num1 = 10, num2 = 20, sum = 30

Go语言程序中全局变量与局部变量名称可以相同,但是函数体内的局部变量会被优先考虑。

go 复制代码
package main

import "fmt"

// 声明全局变量
var name string = "Krito"

func main() {
    name := "Asuna"
    fmt.Println(name)
}

// 执行结果
Asuna

如果一个 Go 源文件中定义了全局变量,并且其他包外源文件需要使用这个全局变量,那么这些源文件需要使用 import 关键字引入定义这个全局变量的源文件所在的包,并且该全局变量的首字母必须大写,才能够使用这个全局变量。

go 复制代码
// util.go
package util
// 声明全局变量,若需要外部包使用,则需要开头字母大写表示包外可见
var Global = "string"
go 复制代码
// main.go,注意main.go与util.go两个文件在不同的包下
package main

import (
    "fmt"
    "go-basic/variable/func/util"
)

func main() {
    fmt.Println(util.Global)
}

形式参数(形参)

在定义函数时函数后面括号中的变量称为形式参数,简称形参。

形参只会在函数调用时才会生效,函数调用结束后形参就会被销毁,在函数未被调用时,函数的形参并不会占用实际的存储单元且没有实际值。形式参数会作为函数的局部变量来使用

go 复制代码
package main

import "fmt"

// 全局变量 num1
var num1 int = 10

func main() {
    // 局部变量 num1 和 num2
    var num1 int = 20
    var num2 int = 30
    fmt.Printf("main() 函数中 num1 = %d\n", num1)
    fmt.Printf("main() 函数中 num2 = %d\n", num2)
    sum := sum(num1, num2)
    fmt.Printf("main() 函数中 sum = %d\n", sum)
}

func sum(num1, num2 int) int {
    fmt.Printf("sum() 函数中 num1 = %d\n", num1)
    fmt.Printf("sum() 函数中 num2 = %d\n", num2)
    cal := num1 + num2
    return cal
}

// 执行结果
main() 函数中 num1 = 20
main() 函数中 num2 = 30
sum() 函数中 num1 = 20
sum() 函数中 num2 = 30
main() 函数中 sum = 50

变量生命周期

在Go语言中,变量的生命周期由变量的作用域垃圾回收机制共同决定。

当一个变量超出其作用域时,将被自动释放。而垃圾回收机制负责回收不再使用的内存。

在Go语言中,所有变量的内存都是在堆上分配的 ,垃圾回收器会定期检查堆上的变量,回收那些不再使用的内存。

因此,Go语言具有自动内存管理的特点,程序员不需要手动进行内存分配和释放操作。

全局变量是定义在函数外部 的变量,具有全局可见性和生命周期,程序在整个执行期间都可以访问这些变量

局部变量是定义在函数内部 的变量,具有局部可见性和生命周期,变量在函数执行完成后就会被销毁

在使用变量时,需要考虑它们的作用域和生命周期,合理地选择变量的存储位置和释放时机,从而提高程序的性能和稳定性。

相关推荐
童先生3 小时前
Go 项目中实现类似 Java Shiro 的权限控制中间件?
开发语言·go
幼儿园老大*5 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
架构师那点事儿10 小时前
golang 用unsafe 无所畏惧,但使用不得到会panic
架构·go·掘金技术征文
于顾而言1 天前
【笔记】Go Coding In Go Way
后端·go
qq_172805591 天前
GIN 反向代理功能
后端·golang·go
follycat1 天前
2024强网杯Proxy
网络·学习·网络安全·go
OT.Ter1 天前
【力扣打卡系列】单调栈
算法·leetcode·职场和发展·go·单调栈
探索云原生1 天前
GPU 环境搭建指南:如何在裸机、Docker、K8s 等环境中使用 GPU
ai·云原生·kubernetes·go·gpu
OT.Ter2 天前
【力扣打卡系列】移动零(双指针)
算法·leetcode·职场和发展·go
码财小子2 天前
k8s 集群中 Golang pprof 工具的使用
后端·kubernetes·go