【四】Golang 变量和常量

欢迎来到张胤尘的技术站
技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌

文章目录

  • 变量
    • 声明方式
      • 使用 `var` 关键字声明变量
      • 省略类型声明(类型推断)
      • 短变量声明
      • 多变量声明
    • 变量的初始化
    • 变量的作用域
      • 全局变量
      • 局部变量
  • 常量
    • 声明方式
      • 使用 `const` 关键字声明
      • 省略类型声明(类型推断)
      • 多常量声明
    • 常量的作用域
      • 全局常量
      • 局部常量
  • 代码示例

变量

变量来源于数学,是计算机语言中能储存计算结果或能表示值抽象概念。变量可以通过变量名访问。
golang 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。

声明方式

变量是存储数据的容器,其值在程序的运行过程中是可以被修改。由于 golang 是强类型语言,所以在变量声明时需要指定类型,但也可以通过编译器的自动类型推断来省略显式类型声明

使用 var 关键字声明变量

var a int = 10
var b string = "Hello"

这里 var 关键字用于声明变量,ab 分别是变量名,intstring 是变量类型,10"Hello" 是变量的初始值。

省略类型声明(类型推断)

var a = 10
var b = "Hello"

如果变量在声明时直接赋值,golang 语言会根据赋值的内容自动推断变量的类型。

短变量声明

a := 10
b := "Hello"

在函数内部,可以使用 := 来声明并初始化变量。但是这种方式只能在函数内部使用,且变量的类型会根据赋值的内容自动推断。

另外在使用短变量声明时需要注意的是,出现在 := 左侧的变量不应该是已经被声明过的,否则会导致编译错误

多变量声明

golang 中支持一次性声明多个变量,语法如下所示:

// 类型相同多个变量, 非全局变量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3

// 自动推断
var vname1, vname2, vname3 = v1, v2, v3 

// 短变量声明,自动推断
vname1, vname2, vname3 := v1, v2, v3

// 这种因式分解关键字的写法一般用于声明全局变量
var (
    vname1 v_type1
    vname2 v_type2
)

变量的初始化

变量在声明时可以初始化,也可以不初始化。未初始化的变量会自动赋予其类型的零值(如 int 的零值是0,string 的零值是空字符串""),具体如下表格所示:

类型 零值
intint8int16int32int64 0
uintuint8uint16uint32uint64uintptr 0
float32float64 0.0
complex64complex128 0 + 0i
bool false
string ""(空字符串)
[n]T(数组) 每个元素初始化为其类型的零值
[]T(切片) nil
map[K]V(字典) nil
struct(结构体) 每个字段初始化为其类型的零值
*T(指针) nil
chan T(通道) nil
interface{}(接口) nil
  • 数组:数组的零值是其所有元素都被初始化为其类型的零值。例如,[3]int 的零值是 [0 0 0]
  • 结构体:结构体的零值是其所有字段都被初始化为其类型的零值。例如:
type Person struct {
    Name string
    Age  int
}

Person 的零值是 {Name: "", Age: 0}

  • 切片、字典、指针、通道和接口:这些类型的零值是 nil,表示它们没有指向任何有效的内存地址或值。

变量的作用域

全局变量

全局变量是在函数外部定义的变量,它们在整个程序中都是可见的。全局变量在程序开始执行时分配内存,直到程序结束时才释放。

package main

import "fmt"

var g int = 10

func main() {
    // 输出全局变量的值 10
    fmt.Println(g) 
}

局部变量

局部变量是在函数内部或代码块(如 ifforswitch等语句)中声明的变量。它们的作用域仅限于声明它们的函数或代码块内部

package main

import "fmt"

func main() {
    x := 10 // 局部变量,作用域为main函数
    
    {
        y := 20 // 局部变量,作用域为这个代码块
        fmt.Println(y) // 可以访问
    }
    
    // fmt.Println(y) // 错误:y的作用域已结束
    fmt.Println(x) // 可以访问
}

当程序执行到局部变量的声明语句时(如 var x intx := 10),golang 运行时会为该变量分配内存。内存分配的具体位置(栈或堆)取决于变量的类型和使用方式

通常分配在栈上的变量:

  • 局部变量:在函数内部声明的简单类型变量(如 intfloat64string 等)通常会被分配在栈上。
  • 函数参数和返回值:函数的参数和返回值通常也会被分配在栈上。
  • 短生命周期的变量:那些在函数调用期间使用的变量,且生命周期仅限于函数内部的变量。
func myFunction() {
    x := 10       // 局部变量,分配在栈上
    y := "Hello"  // 局部变量,分配在栈上
    z := [3]int{1, 2, 3} // 数组,分配在栈上
}

通常分配在堆上的变量:

  • 切片([]T):切片本身是一个引用类型,它包含一个指向底层数组的指针、长度和容量。底层数组通常会被分配在堆上。
  • 字典(map[K]V):字典是一个复杂的数据结构,其内部实现使用了动态分配的内存,通常会被分配在堆上。
  • 结构体(struct):如果结构体的大小较大,或者结构体被分配到一个更大的数据结构中(如切片或字典),那么结构体可能会被分配在堆上。
  • 指针(*T):指针本身是一个简单的类型,通常分配在栈上,但指针指向的对象可能会被分配在堆上。
  • 接口(interface{}):接口是一个引用类型,其内部实现使用了动态分配的内存,通常会被分配在堆上。
func myFunction() {
    var x *int = new(int) // 指针,指向的值分配在堆上
    y := []int{1, 2, 3}   // 切片,底层数组分配在堆上
    z := make(map[string]int) // 字典,分配在堆上
}

需要额外说明的是,golang 编译器也会根据变量的使用方式和生命周期来决定内存分配的位置。即使是一个简单的类型(如 int),如果它的生命周期超出了函数调用范围,或者需要动态分配,它也可能会被分配在堆上。

func myFunction() *int {
    x := 10 // 局部变量,但返回了它的地址
    return &x
}

在这个例子中,x 的生命周期超出了函数调用范围(因为返回了它的地址),因此编译器会将 x 分配在堆上,以确保返回的指针仍然有效。

常量

常量是一个简单值的标识符,在程序运行时,不会被修改的量。需要注意的是常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型

常量的定义格式如下所示:

const identifier [type] = value

声明方式

使用 const 关键字声明

const pi float64 = 3.14159
const max int = 100

这里 const 关键字用于声明常量,pimax 分别是常量名,float64int 是常量类型,3.14159100 是常量的值。

省略类型声明(类型推断)

const pi = 3.14159
const max = 100

如果常量在声明时直接赋值,golang 语言会根据赋值的内容自动推断常量的类型。

多常量声明

const c_name1, c_name2 = value1, value2

全局常量可以采用如下的形式进行多个常量的声明:

const (
    globalConst1 int = 100
    globalConst2 string = "Hello, World!"
)

常量的作用域

全局常量

全局常量是在函数外部声明的常量,它们的作用域是整个包(package)。全局常量可以在包内的任何地方访问,包括所有函数和代码块。

  • 作用域:全局常量的作用域是整个包,可以在包内的任何函数或代码块中访问。
  • 初始化:全局常量必须在声明时初始化,且值必须是编译时可知的常量表达式。
  • 用途:通常用于定义一些全局的、不变的配置参数或常量值。

局部常量

局部常量是在函数内部或代码块中声明的常量,它们的作用域仅限于声明它们的函数或代码块。

  • 作用域:局部常量的作用域仅限于声明它们的函数或代码块。在代码块结束时,局部常量的作用域也随之结束。
  • 初始化:局部常量同样必须在声明时初始化,且值必须是编译时可知的常量表达式。
  • 用途:局部常量通常用于在函数内部定义一些固定不变的值,以提高代码的可读性和可维护性。

代码示例

package main

import "fmt"

// 全局变量
var globalVar int = 100

// 全局常量
const globalConst int = 200

func main() {
    // 局部变量
    var localVar int = 50
    fmt.Println("局部变量 localVar:", localVar)

    // 使用短变量声明
    localVar2 := 60
    fmt.Println("局部变量 localVar2:", localVar2)

    // 局部常量
    const localConst int = 300
    fmt.Println("局部常量 localConst:", localConst)

    // 访问全局变量和全局常量
    fmt.Println("全局变量 globalVar:", globalVar)
    fmt.Println("全局常量 globalConst:", globalConst)
}

撒花!

如果本文对你有帮助,就点关注或者留个
如果您有任何技术问题或者需要更多其他的内容,请随时向我提问。
在这里插入图片描述

你可能感兴趣的:(Golang,golang,开发语言,后端)