Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >《快学 Go 语言》第 2 课 —— 变量什么的最讨厌了

《快学 Go 语言》第 2 课 —— 变量什么的最讨厌了

作者头像
老钱
发布于 2018-12-13 09:48:21
发布于 2018-12-13 09:48:21
44500
代码可运行
举报
文章被收录于专栏:码洞码洞
运行总次数:0
代码可运行

任何一门语言里面最基础的莫过于变量了。如果把内存比喻成一格一格整齐排列的储物箱,那么变量就是每个储物箱的标识,我们通过变量来访问计算机内存。没有变量的程序对于人类来说是可怕的,需要我们用数字位置来定位内存的格子,人类极不擅长这样的事。这就好比一岁半左右的幼儿还没有学会很多名词,只能用手来对物体指指点点来表达自己的喜好。变量让程序逻辑有了丰富的表达形式。

定义变量的三种方式

Go 语言的变量定义有多种形式,我们先看最繁琐的形式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import "fmt"

func main() {
    var s int = 42
    fmt.Println(s)
}

-------------
42

注意到我们使用了 var 关键字,它就是用来显式定义变量的。还注意到在变量名称 s 后面声明了变量的类型为整形 int,然后再给它赋上了一个初值 42。上面的变量定义可以简化,将类型去掉,因为编译器会自动推导变量类型,效果也是一样的,如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import "fmt"

func main() {
    var s = 42
    fmt.Println(s)
}

---------------
42

更进一步,上面的变量定义还可以再一次简化,去掉 var 关键字。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import "fmt"

func main() {
    s := 42
    fmt.Println(s)
}

---------------
42

注意到赋值的等号变成了 :=,它表示变量的「自动类型推导 + 赋值」。

这三种变量定义方式都是可行的,各有其优缺点。可读性最强的是第一种,写起来最方便的是第三种,第二种是介于两者之间的形式。

类型是变量身份的象征,如果一个变量不那么在乎自己的身份,那在形式上就可以随意一些。var 的意思就是告诉读者「我很重要,你要注意」,:= 的意思是告诉读者「我很随意,别把我当回事」。var 再带上显式的类型信息是为了方便读者快速识别变量的身份。

如果一个变量很重要,建议使用第一种显式声明类型的方式来定义,比如全局变量的定义就比较偏好第一种定义方式。如果要使用一个不那么重要的局部变量,就可以使用第三种。比如循环下标变量

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
for i:=0; i<10; i++ {
  doSomething()
}

那第二种方式能不能用在上面的循环下标中呢,答案是不可以,你无法将 var 关键字直接写进循环条件中的初始化语句中,而必须提前声明变量,像下面这样,这时就很明显不如简写的形式了

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
var i = 0
for ; i<10; i++ {
  doSomething()
}

如果在第一种声明变量的时候不赋初值,编译器就会自动赋予相应类型的「零值」,不同类型的零值不尽相同,比如字符串的零值不是 nil,而是空串,整形的零值就是 0 ,布尔类型的零值是 false。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import "fmt"

func main() {
    var i int
    fmt.Println(i)
}

-----------
0

全局变量和局部变量

上面我们在代码例子中编写的变量都是局部变量,它定义在函数内部,函数调用结束它就消亡了。与之对应的是全局变量,在程序运行期间,它一直存在,它定义在函数外面。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import "fmt"

var globali int = 24

func main() {
    var locali int = 42
    fmt.Println(globali, locali)
}

---------------
24 42

如果全局变量的首字母大写,那么它就是公开的全局变量。如果全局变量的首字母小写,那么它就是内部的全局变量。内部的全局变量只有当前包内的代码可以访问,外面包的代码是不能看见的。

学过 C 语言的同学可能会问,Go 语言里有没有静态变量呢?答案是没有。

变量与常量

Go 语言还提供了常量关键字 const,用于定义常量。常量可以是全局常量也可以是局部常量。你不可以修改常量,否则编译器会抱怨。常量必须初始化,因为它无法二次赋值。全局常量的大小写规则和变量是一致的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import "fmt"

const globali int = 24

func main() {
    const locali int = 42
    fmt.Println(globali, locali)
}

指针类型

Go 语言被称为互联网时代的 C 语言,它延续使用了 C 语言的指针类型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import "fmt"

func main() {
    var value int = 42
    var pointer *int = &value
    fmt.Println(pointer, *pointer)
}

--------------
0xc4200160a0 42

我们又看到了久违的指针符号 * 和取地址符 &,在功能和使用上同 C 语言几乎一摸一样。同 C 语言一样,指针还支持二级指针,三级指针,只不过在日常应用中,很少遇到。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main


import "fmt"


func main() {
    var value int = 42
    var p1 *int = &value
    var p2 **int = &p1
    var p3 ***int = &p2
    fmt.Println(p1, p2, p3)
    fmt.Println(*p1, **p2, ***p3)
}

----------
0xc4200160a0 0xc42000c028 0xc42000c030
42 42 42

指针变量本质上就是一个整型变量,里面存储的值是另一个变量内存的地址。* 和 & 符号都只是它的语法糖,是用来在形式上方便使用和理解指针的。* 操作符存在两次内存读写,第一次获取指针变量的值,也就是内存地址,然后再去拿这个内存地址所在的变量内容。

图片

如果普通的变量是一个储物箱,那么指针变量就是另一个储物箱,这个储物箱里存放了普通变量所在储物箱的钥匙。通过多级指针来读取变量值就好比在玩一个解密游戏。

Go 语言基础类型大全

Go 语言定义了非常丰富的基础类型,下面我列举了所有的基础数据类型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package main

import "fmt"

func main() {
    // 有符号整数,可以表示正负
    var a int8 = 1 // 1 字节
    var b int16 = 2 // 2 字节
    var c int32 = 3 // 4 字节
    var d int64 = 4 // 8 字节
    fmt.Println(a, b, c, d)

    // 无符号整数,只能表示非负数
    var ua uint8 = 1
    var ub uint16 = 2
    var uc uint32 = 3
    var ud uint64 = 4
    fmt.Println(ua, ub, uc, ud)

    // int 类型,在32位机器上占4个字节,在64位机器上占8个字节
    var e int = 5
    var ue uint = 5
    fmt.Println(e, ue)

    // bool 类型
    var f bool = true
    fmt.Println(f)

    // 字节类型
    var j byte = 'a'
    fmt.Println(j)

    // 字符串类型
    var g string = "abcdefg"
    fmt.Println(g)

    // 浮点数
    var h float32 = 3.14
    var i float64 = 3.141592653
    fmt.Println(h, i)
}

-------------
1 2 3 4
1 2 3 4
5 5
true
abcdefg
3.14 3.141592653
97

还有另外几个不常用的数据类型,读者可以暂不理会。

  1. 复数类型 complex64 和 complex128
  2. unicode字符类型 rune
  3. uintptr 指针类型

复数类型用于科学计算,平时基本上用不上。rune 和 uintptr 的用法在后续文章中会详细讲解。简单一点说 rune 和 byte 的关系就好比 Python 里面的 unicode 和 byte 、Java 语言里面的 char 和 byte 。uintptr 相当于 C 语言里面的 void* 指针类型。

下一节我们开讲 Go 语言的条件判断与循环语句

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-11-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码洞 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
《快学 Go 语言》第 14 课 —— 反射
反射是 Go 语言学习的一个难点,但也是非常重要的一个知识点。反射是洞悉 Go 语言类型系统设计的法宝,Go 语言的 ORM 库离不开它,Go 语言的 json 序列化库离不开它,Go 语言的运行时更是离不开它。笔者在学习反射功能的时候也是费了好大一番功夫才敢说自己确实搞懂了。下面请读者跟着我的步伐来一步一步深入理解反射功能。
老钱
2018/12/28
4460
[GO语言基础] 三.变量声明、数据类型、标识符及编程练习12题
作为网络安全初学者,会遇到采用Go语言开发的恶意样本。因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识;另一方面是分享与读者,希望大家一起进步。前文介绍了Go的编译运行、语法规范、注释转义及API标准库知识;这篇文章将介绍Golang的变量、数据类型和标识符知识,并通过12道编程练习进行提升。 这系列文章入门部分将参考“尚硅谷”韩顺平老师的视频和书籍《GO高级编程》,详见参考文献,并结合作者多年的编程经验进行学习和丰富,且看且珍惜吧!后续会结合网络安全进行GO语言实战深入,加油~
Eastmount
2021/02/25
7880
详解Go变量类型的内存布局
每当我们编写任何程序时,我们都需要在内存中存储一些数据/信息。数据存储在特定地址的存储器中。内存地址看起来像0xAFFFF(这是内存地址的十六进制表示)。
sunsky
2020/08/20
1.9K0
详解Go变量类型的内存布局
[GO语言基础] 三.变量声明、数据类型、标识符及编程练习
作为网络安全初学者,会遇到采用Go语言开发的恶意样本。因此从今天开始从零讲解Golang编程语言,一方面是督促自己不断前行且学习新知识;另一方面是分享与读者,希望大家一起进步。前文介绍了Go的编译运行、语法规范、注释转义及API标准库知识;这篇文章将介绍Golang的变量、数据类型和标识符知识,并通过12道编程练习进行提升。这系列文章入门部分将参考“尚硅谷”韩顺平老师的视频和书籍《GO高级编程》,详见参考文献,并结合作者多年的编程经验进行学习和丰富,且看且珍惜吧!后续会结合网络安全进行GO语言实战深入,加油~
Eastmount
2021/12/03
6810
[GO语言基础] 三.变量声明、数据类型、标识符及编程练习
02.GO变量和数据类型(幼儿园级别教程 )
声明: (1) GO版本:go version go1.21.5 windows/amd64 (2) 开发工具:vscode (3) 微信公众号:给点知识 如果版本不一样再环境变量的配置上多少有点问题。1.11 GO版本之前使用GOPATH 之后可以使用go.mod 要不然导入模块包那块会有问题。
读懂原理
2024/01/21
3071
02.GO变量和数据类型(幼儿园级别教程 )
数据类型和表达式
需要注意的是,Go语言中支持隐式类型转换,但是不同类型之间的转换需要满足特定的规则。另外,Go还提供了一种复合类型complex,用于表示复数。complex由实部和虚部两个float32或float64类型组成,可以用于数学运算。
用户1413827
2023/11/28
3570
go 指针和内存分配详解
每当我们编写任何程序时,我们都需要在内存中存储一些数据/信息。数据存储在特定地址的存储器中。内存地址看起来像0xAFFFF(这是内存地址的十六进制表示)。
孤烟
2020/09/27
1K0
Go语言学习(二)
现在互联网的资源很多,所以对比学习很有必要,可以参考不同的教材Step by Step的学习,每天都有一点收获,而后才能真正的学有所用。
呱牛笔记
2023/05/02
2270
Go语言学习(二)
《快学 Go 语言》第 14 课 —— 魔术变性指针
本节我们要学习一些 Go 语言的魔法功能,通过内置的 unsafe 包提供的功能,直接操纵指定内存地址的内存。有了 unsafe 包,我们就可以洞悉 Go 语言内置数据结构的内部细节。
老钱
2018/12/28
5020
《快学 Go 语言》第 14 课 —— 魔术变性指针
Go语言的基本概念与语法 - Java技术债务
按照约定,包名与导入路径的最后一个元素相同。例如,"math/rand" 包中的源码均以packagerand` 语句开始.
Java技术债务
2024/06/21
1070
go语言基本数据类型和变量
使⽤关键字 var 定义变量,⾃动初始化为零值。如果提供初始化值,可省略变量类型,由编译器⾃动推断。
onenewcode
2024/02/09
1590
go 语言string之解析
string 在go中如何定义的? string 的底层原理与细节? string 如何具体使用?
Tim在路上
2021/02/04
6450
003.golang 类型与变量
零值并不等于空值,而是当变量被声明为某种类型后的默认值, 通常情况下值类型的默认值为0,bool为false,string为空字符串
qubianzhong
2018/08/02
3240
003.golang 类型与变量
go语言的变量声明
注意初始化器的个数必须与变量个数相同。 有初始化器时,变量类型可以省略,该变量的类型会根据初始化器自动推断。 例子:
梦飞
2022/06/23
1.2K0
Go语言学习(八)| 类型、指针
所有新定义的变量都被赋值为其类型的零值,而指针也一样。一个新定义的或者没有任何指向的指针,有值 nil 。 在其他语言中,这经常被叫做 空(NULL)指针 ,在 Go 中就是 nil 。让指针指向某些内容,可以使用取址操作符 &
Mervyn
2020/07/21
3780
第二章 Go变量
Title: Go变量 Author: 宇宙之一粟 Time: 2019年11月8日
宇宙之一粟
2020/10/26
2670
第二章  Go变量
Golang 学习笔记-1:变量&函数
最近在学习golang,写下学习笔记提升记忆。为了看起来不是那么枯燥,本学习笔记采用分析代码的形式。
goodspeed
2020/12/22
5390
Go 语言基本数据类型
注意: 在使用 int 和 uint 类型时,不能假定它是 32 位或 64 位的整型,而是考虑 int 和 uint可能在不同平台上的差异。
BUG弄潮儿
2024/01/22
1330
Go 语言基本数据类型
第一章 go基础语法
变量p编译都不通过, 因为最后的}换行了, 换行必须要有逗号. 写成pp的样子就可以了
用户7798898
2020/09/27
5670
第一章 go基础语法
go基础编程 day-2
  零值并不等于空值,而是当变量声明为某种来兴后的默认零值,通常情况下默认值为0,bool为false,string为空字符串。
Wyc
2018/09/11
6350
go基础编程  day-2
相关推荐
《快学 Go 语言》第 14 课 —— 反射
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验