【go语言】变量和常量

一、变量

1.1 变量的定义

  • 程序 : 我们向电脑说了一段话,需要电脑才能理解 (沟通机制 ,xxx语言 -- 汇编 -- 机器码),电脑实际上识别的是机器码 : 0 1 1 1 0 1 (高低电频)
  • 机器码 : 穿孔纸带
  • 汇编:早些时候,现在的很多机器硬件底层代码,都是汇编
  • 人能读懂的代码:英文、中文

将我们的语言和机器进行对接 (C、Java、Go ---> 编译器 --> 计算机中去执行:无需理解的,我们只需要写我们能看懂的代码即可 ),我们理解的世界、和计算机的世界要一一对应:

定义:一切都是需要去定义的。计算机也需要去定义一些东西。

人名: 名字 name = 秦疆 字符串。

名字(变量)

name = 张三

name = 李四

计算机也需要这样来认识我们写的代码,也需要一个格式

通过 var 关键字来定义变量

变量名字 需要告诉计算机这个信息(变量)是什么类型的,数据类型:数字、字符串、小数.... = "变量的值"

Go 复制代码
//用程序描述一个人的信息
// string 字符串类型
var name string = "秦疆"
// int 数字类型
var age int = 27

var sex string = "男"

// Java
String name = "秦疆"

公式:定义变量 var 变量名 变量类型

Go 复制代码
package main

import "fmt"

func main() {

   // 只定义变量,不使用可以吗. 理论可以,实际在Go语言中不行。
   // 无意义代码,报错!

   // 问题1 :能不能不写数据类型
   // 问题2 :不用var 直接定义变量呢?

   // 自动推导,一个短变量声明
   name := "kuangshen"
   age := 18
   // 语法糖(偷懒,简化开发!)
   // := 相当于快递定义变量。如果给这个变量赋值了,那么会自动推导它的类型
   // var 、 数据类型的定义都被省略的。
   // 数据类型 go语言中基本的数据类型。

   fmt.Println(name)
   fmt.Println(age)

   // 定义了变量name2
   var name2 string
   // 在快速声明中,如果 := 左边的变量已经存在了,那么它将无法创建,无法重新定义
   name3 := "qinjiang222"
   fmt.Println(name2)
   fmt.Println(name3)
   name3 = "zhangsan666"
}

1、定义变量使用定式 var 变量名称 变量数据类型

2、给变量赋值 。 定义的时候直接赋值、 通过变量名来赋值、

3、语法糖 := 。 可以通过它来快速定义变量,如果是基本数据类型,字符串、数字,它会自动推导类型。所谓的基础语法,所有的编程语言大同小异。

1.2 变量的交换

Go 复制代码
package main

import "fmt"

func main() {
   /* 在编程中遇到的第一个问题:变量交换
   var a int = 100
   var b int = 200

   var t int
   t = a
   a = b
   b = t
   */
   // 在Go语言中,程序变量交换,也有语法糖
   var a int = 100
   var b int = 200
   // fmt.Println 可以传递多个参数,用逗号隔开,直接打印
   fmt.Println("a=", a, ",b=", b)
   // 把a,b赋值给b,a  语法糖, 底层本质还是用到了临时变量。简化我们的开发
   b, a = a, b
   fmt.Println("交换后 a=", a, ",b=", b)
   
   // 复杂的问题都给我们简单化了,我们开发很轻松,编译器帮我们在底层处理。
}

1.3 理解变量

Go 复制代码
package main

import "fmt"

func main() {
   // 变量到底是个什么玩意?
   // num 实际上是一片内存空间
   // 我们想要看一个变量的内存地址,只需要在变量名前加上 & 即可。
   // 取地址符 (指针)
   var num int
   num = 1000
   // 思考:这个num在计算机中是什么样子的。 num
   fmt.Printf("num的值:%d,内存地址:%p\n", num, &num)
   num = 2000
   fmt.Printf("num的值:%d,内存地址:%p\n", num, &num)

   // 汇编。理解一切

   var name string
   name = "张三"
   // 思考:这个num在计算机中是什么样子的。 num
   fmt.Printf("num的值:%s,内存地址:%p\n", name, &name)
   name = "李四"
   fmt.Printf("num的值:%s,内存地址:%p\n", name, &name)

   // 打印内存地址的方式之一。 Print  f格式化输出
   // 内存
   // 第一个参数 输出字符串
   // % 占位符。
   // 占位符的数量,要和后面待输出的数量一直
   // %d 数字 int d
   // %p 内存地址,num需要取出变量的地址。
   // %s 字符串。
   // \n 换行
   //fmt.Printf("num的值:%d",num)
}

1.4 匿名变量

Go 复制代码
package main

import "fmt"

// 变量 ( 有名字、没有名字:匿名 )
// 十分特殊、匿名变量 (黑洞,一切东西丢进去,任何赋值给匿名变量的值都会被丢弃)
// _ 下划线,就是匿名变量在Go语言中

// 函数 一段代码的集合。
//
// func  test 函数名 (参数,参数....) 返回一些东西{
//  一段代码的集合,通过or不通过参数,返回结果
// }
//
// 基本的操作函数,调用函数,返回两个数字。
func test() (int, int) {
   // return 返回结果
   return 100, 200
}

// 在Go语言中会大量使用到
// 匿名变量不占用内存空间,不会分配内存。
func main() {
   // 调用这个test函数,应该会返回两个结果,100,200

   // 变量 : 除了直接定义之外,还可以是一个结果的赋值
   //var a int = 100
   // 只想要test返回的第一个结果,这时候就需要使用匿名变量 _。
   a, _ := test() // a,b := 100,200
   fmt.Println(a)
   // 只想要test返回的第二个结果,这时候就需要使用匿名变量 _。
   _, b := test()
   fmt.Println(b)
}

1.5 变量的作用域

Go 复制代码
package main

import "fmt"

// 全局变量:在当前go文件中生效...
// 定义在go文件非函数内,在package和import下面
// 全局变量的定义必须使用 var 关键字, 如果直接使用 := 则无法创建该变量
// 全局变量和局部变量是可以重名的,优先级。到底用谁
var c int

func main() {
   // 局部变量:只在一定的范围内生效...
   // 在函数体内声明变量
   var a int = 3
   var b int = 4
   // 如果全局变量有,那么直接使用全局变量来接收。
   c = a + b
   fmt.Printf("a=%d,b=%d,c=%d\n", a, b, c)
   fmt.Printf("c内存地址:%p\n", &c)
   b = 1
   // 但是如果在局部有和全局同名的变量,优先使用局部变量
   c := a + b
   fmt.Printf("a=%d,b=%d,c=%d\n", a, b, c)
   fmt.Printf("c内存地址:%p\n", &c)
   b = 5
   // 就近原则
   c = a + b
   fmt.Printf("a=%d,b=%d,c=%d\n", a, b, c)
   fmt.Printf("c内存地址:%p\n", &c)

   // Printf 格式化输出 (参数一:需要打印的内容,%是占位符,通过后续参数给他一一赋值)
   fmt.Printf("a=%d,b=%d,c=%d\n", a, b, c)
}

注意:

  • 变量必须先定义才能使用
  • go语言是静态语言,要求变量的类型和赋值类型一致
  • 变量名不能冲突
  • 简洁变量定义不能用于全局变量
  • 变量是有零值,也就是默认值
  • 定义了变量一定要使用,否则就会报错

二、常量

常量: 不能变化的量。 这个变量是一个特殊的变量,无法改变的。 关键字 const

两个区别:变量的定义使用 var 、常量的定义是使用const

在go语言中,是什么机制导致常量无法改变的?

在 Go 语言中,常量(const)的不可变性是由语言设计和编译器的行为机制决定的。

Go 语言中常量的不可变性来源于以下几点:

  1. 编译时确定值:常量在编译时确定其值,并且该值不可修改。
  2. 没有内存地址:常量不占用内存地址,而是直接嵌入到机器代码中。
  3. 避免错误修改:通过常量的不可变性,避免了程序员不小心改变本应固定的值,从而提高了代码的安全性和稳定性。

这些机制是为了确保常量在程序运行过程中始终保持一致,不会受到程序的其他部分的影响,从而保证程序的行为符合预期。

Go语言底层的约定,实际上它是可以改变的,需要跳过常量名,直接找到内存地址,进行修改值。

Go 复制代码
package main

import "fmt"

// 常量和变量放置的内存地址不同  (栈、堆、常量池)
// 程序正常执行,压栈

// 常量
func main() {
   // 规定:建议这么去做
   // 我们通过定义常量的时候,建议大家使用大写字母来定义。区分与普通变量
   // 一旦定义之后是不会发生变化的。
   // 定义格式  const 常量名[type] = value
   const URL string = "www.kuangstudy.com"

   // 隐式定义 常量的自动推导是可以省略一些基础类型,
   const URL2 = "www.baidu.com"

   // 可以同时定义多个常量
   const URL3, URL4 string = "www.kuangstudy.com", "www.baidu.com"

   //
   fmt.Println(URL)
   fmt.Println(URL2)
   fmt.Println(URL3)
   fmt.Println(URL4)

   // 在我们真实的世界也是有很多不会发生变化量,那在程序中对应的就是常量
   const PI = 3.14
   // 固定的东西,都建议统一定义成常量。
   const LENGTH int = 8000
   const WIDTH int = 8000

   // 常量是无法被修改的。
   //LENGTH = 13

   fmt.Println(LENGTH)

}

注意:

  • 常量类型只可以定义 bool,数值(整数、浮点数和复数)和字符串
  • 不曾使用的变量,没有强制使用的要求
  • 显示指定类型的时候,必须确保常量左右值类型一致

三、关键字 iota

在Go语言中,iota是一个非常特别的关键字,它用于在常量声明中生成一组递增的常量。iota的工作原理非常简单,它在每个const块内自动递增,可以用于简化常量值的定义。每当iota出现在一个新的常量声明块中时,它会被重置为0,并且在该块内的每一行常量值都会递增。

Go 复制代码
const (
    a = iota  // 0
    b         // 1
    c         // 2
)
Go 复制代码
package main

import "fmt"

const (
    Red = iota  // 0
    Green       // 1
    Blue        // 2
)

func main() {
    fmt.Println(Red)   // 输出: 0
    fmt.Println(Green) // 输出: 1
    fmt.Println(Blue)  // 输出: 2
}

iota 可以与其他表达式结合

与位操作结合
Go 复制代码
package main

import "fmt"

const (
    _  = iota             // 跳过0
    KB = 1 << (10 * iota) // 1024
    MB = 1 << (10 * iota) // 1048576
    GB = 1 << (10 * iota) // 1073741824
)

func main() {
    fmt.Println(KB) // 输出: 1024
    fmt.Println(MB) // 输出: 1048576
    fmt.Println(GB) // 输出: 1073741824
}
iota 和枚举

通过iota,我们还可以创建类似于枚举的结构。比如,我们可以给状态值分配有意义的数字:

Go 复制代码
package main

import "fmt"

const (
    Unknown = iota
    Started
    Stopped
    Paused
)

func main() {
    fmt.Println(Unknown)  // 输出: 0
    fmt.Println(Started)  // 输出: 1
    fmt.Println(Stopped)  // 输出: 2
    fmt.Println(Paused)   // 输出: 3
}

iota 的特点

  1. 自动递增 :每当iota出现在常量声明块中时,都会自动递增。
  2. 重置 :每次遇到新的常量声明块时,iota会被重置为0。
  3. 灵活使用:可以与位操作、数学计算等表达式配合使用,生成复杂的常量值。
  4. 跳过某些常量 :可以通过给常量分配_ = iota来跳过某些常量(如示例中的_)。

总结

iota是Go语言中的一个非常有用的工具,简化了常量的定义,特别是在需要递增或生成一组值时。在IOTA的Go语言实现中,iota通常不会直接用于IOTA协议本身,但可以在一些常量的定义中使用,比如网络协议类型、交易状态标识等。

相关推荐
数据小小爬虫1 分钟前
如何使用Python爬虫按关键字搜索AliExpress商品:代码示例与实践指南
开发语言·爬虫·python
好一点,更好一点16 分钟前
systemC示例
开发语言·c++·算法
不爱学英文的码字机器19 分钟前
[操作系统] 环境变量详解
开发语言·javascript·ecmascript
martian66524 分钟前
第17篇:python进阶:详解数据分析与处理
开发语言·python
五味香28 分钟前
Java学习,查找List最大最小值
android·java·开发语言·python·学习·golang·kotlin
时韵瑶33 分钟前
Scala语言的云计算
开发语言·后端·golang
卷卷的小趴菜学编程37 分钟前
c++之List容器的模拟实现
服务器·c语言·开发语言·数据结构·c++·算法·list
艾杰Hydra40 分钟前
LInux配置PXE 服务器
linux·运维·服务器
多恩Stone44 分钟前
【ubuntu 连接显示器无法显示】可以通过 ssh 连接 ubuntu 服务器正常使用,但服务器连接显示器没有输出
服务器·ubuntu·计算机外设
牙牙7051 小时前
ansible一键安装nginx二进制版本
服务器·nginx·ansible