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语言具有自动内存管理的特点,程序员不需要手动进行内存分配和释放操作。

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

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

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

相关推荐
蒙娜丽宁2 天前
Go语言错误处理详解
ios·golang·go·xcode·go1.19
qq_172805593 天前
GO Govaluate
开发语言·后端·golang·go
littleschemer3 天前
Go缓存系统
缓存·go·cache·bigcache
程序者王大川4 天前
【GO开发】MacOS上搭建GO的基础环境-Hello World
开发语言·后端·macos·golang·go
Grassto4 天前
Gitlab 中几种不同的认证机制(Access Tokens,SSH Keys,Deploy Tokens,Deploy Keys)
go·ssh·gitlab·ci
高兴的才哥5 天前
kubevpn 教程
kubernetes·go·开发工具·telepresence·bridge to k8s
少林码僧6 天前
sqlx1.3.4版本的问题
go
蒙娜丽宁6 天前
Go语言结构体和元组全面解析
开发语言·后端·golang·go
蒙娜丽宁6 天前
深入解析Go语言的类型方法、接口与反射
java·开发语言·golang·go
三里清风_6 天前
Docker概述
运维·docker·容器·go