1. 变量定义

Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。声明变量的一般形式是使用 var 关键字:

var varName dataType [= value]

Go 语言和许多编程语言不同,它在声明变量时将变量的类型放在变量的名称之后。

这样做的好处就是可以避免像 C 语言中那样含糊不清的声明形式,例如:

// C 语言写法
int* a, b, c;
// 创建一个 int 型指针 a 和两个 int 型变量 b,c

而在 Go 中,则可以轻松地将它们都声明为指针类型。

2. 变量声明

当一个变量被声明之后,系统自动赋予它该类型的零值: int 为 0, float 为 0.0, bool 为 false, string 为空字符串,指针为 nil 等。所有的内存在 Go 中都是经过初始化的。

在C语言中,变量在声明时,并不会对变量对应内存区域进行清理操作。此时,变量值可能是完全不可预期的结果。开发者需要习惯在使用C语言进行声明时要初始化操作,稍有不慎,就会造成不可预知的后果。

在网络上只有程序员才能看懂的“烫烫烫”和“屯屯屯”的梗,就来源于 C/C++ 中变量默认不初始化。

微软的 VC 编译器会将未初始化的栈空间以 16 进制的 0xCC 填充,而未初始化的堆空间使用 0xCD 填充,而 0xCCCC 和 0xCDCD 在中文的 GB2312 编码中刚好对应“烫”和“屯”字。

因此,如果一个字符串没有结束符\0,直接输出的内存数据转换为字符串就刚好对应“烫烫烫”和“屯屯屯”。

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

2.1 单变量声明

  1. 指定变量类型,声明后若不赋值,则使用该类型的默认值;
var varName dataType = value
  1. 根据值由编译器自行判定变量类型;
var varName = value
  1. 省略关键字 var , 注意 := 左侧的变量不应该是已经声明过的,否则会导致编译错误,该种声明只能使用于函数或者方法;
varName := value

例如:

var a int = 10var b = 10c := 10

使用示例:

package mainvar a = "卧虎藏龙"
var b string = "www.wohu.com"
var c boolfunc main() {d := 100println(a, b, c, d)
}

2.2 多变量声明

  1. 指定变量类型,声明后若不赋值,则使用默认值;
var name1 name2 name3 int = v1, v2, v3
  1. 根据值自行判定变量类型;
var name1, name2, name3 = v1, v2, v3
  1. 省略 var, 注意 := 左侧的变量不应该是已经声明过的,否则会导致编译错误;
name1, name2, name3 := v1, v2, v3
  1. 全局变量

    这种因式分解关键字的写法一般用于声明全局变量

var (name1 typename2 type)

注意: 一般建议一行只写一个变量,这样方便代码阅读

Go 语言中,定义变量要么通过声明、要么通过 makenew 函数,不一样的是 makenew 函数属于显式声明并初始化。

如果我们声明的变量没有显式声明初始化,那么该变量的默认值就是对应类型的零值。从下面的表格可以看到,可以称为引用类型的零值都是 nil

类型 零值
int、float 0
bool false
string “” 空字符串
struct 内部字段的零值
slice nil
map nil
指针 nil
函数 nil
chan nil
interface nil

3. 使用示例

package mainvar x, y int
var (a intb bool
)
var c, d int = 1, 2// "hello" 是字符串必须用双引号 " " 包含,如果用单引号包含则会报错,单引号只能包含单个字符
// invalid character literal (more than one character)var e, f = 123, "hello"// 这种不带声明格式的只能在函数体中出现,而不可以用于全局变量的声明与赋值
// g, h := 123, "hello"func main() {g, h := 123, "hello"println(x, y, a, b, c, d, e, f, g, h)
}

运行结果:

0 0 0 false 1 2 123 hello 123 hello

4. 注意事项

在相同的代码块中,我们不可以再次对于相同名称的变量使用初始化声明,如下代码

package mainimport "fmt"func main() {var a int = 2fmt.Println("a is ", a)a := 5fmt.Println("a is ", a)
}

编译器会报错误

# command-line-arguments
src/main.go:32:4: no new variables on left side of :=

但是 a = 20 是可以的,因为这是给相同的变量赋予一个新的值。

  1. 如果你在定义变量 a 之前使用它,则会得到编译错误 undefined: a

  2. 如果声明了一个局部变量却没有在相同的代码块中使用它,同样会得到编译错误 a declared and not used

  3. 空白标识符也被用于抛弃值,如值 5 在 _, b = 5, 7 中被抛弃。

_ 也叫作匿名变量,匿名变量不占用内存空间,不会分配内存。匿名变量与匿名变量之间也不会因为多次声明而无法使用。 实际上是一个只写变量,你不能得到它的值。这样做是因为 Go 语言中你必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。

注意:在多个短变量声明和赋值中,至少有一个新声明的变量出现在左值中,即便其他变量名可能是重复声明的,编译器也不会报错,代码如下,编译器不会报 err 重复定义。

conn, err := net.Dial("tcp", "127.0.0.1:8080")
conn2, err := net.Dial("tcp", "127.0.0.1:8080")

5. 变量作用域

Go 语言中变量可以在三个地方声明:

  1. 函数内定义的变量称为局部变量

  2. 函数外定义的变量称为全局变量

  3. 函数定义中的变量称为形式参数

  • 全局作用域

在任何地方都可以访问的变量,称其具有全局作用域。在 Go 语言中,全局作用域有两类:

  1. Go 语言内置的预声明标识符(包括预声明的类型名、关键字、内置函数等)它们具有全局作用域,在任意命名空间内都可见。

  2. Go 语言包内以大写字母开头的标识符( 包括变量、常量、函数和方法名、自定义类型、结构字段等),它们具有全局作用域,在任意命名空间内都可见。

  • 包内作用域

Go 语言包内定义的以小写字母开头的标识符(变量、常量、函数和方法名、自定义类型、结构字段等〉,它们在本包可见,在其他包都是不可见的,这些标识符具有包内作用域。

  • 隐式作用域

每个代码块内定义的变量称为“局部变量”这些局部变量只在当前代码块内可见,其作用域属于当前代码块的隐式作用域。

不要将作用域和生命周期混为一谈。声明语句的作用域对应的是一个源代码的文本区域;它是一个编译时的属性。一个变量的生命周期是指程序运行时变量存在的有效时间段,在此时间区域内它可以被程序的其他部分引用;是一个运行时的概念。

句法块是由花括弧所包含的一系列语句,就像函数体或循环体花括弧包裹的内容一样。句法块内部声明的名字是无法被外部块访问的。这个块决定了内部声明的名字的作用域范围。

我们可以把块(block)的概念推广到包括其他声明的群组,这些声明在代码中并未显式地使用花括号包裹起来,我们称之为词法块。对全局的源代码来说,存在一个整体的词法块,称为全局词法块;对于每个包、每个 forifswitch 语句,也都有对应词法块;

每个 switchselect 的分支也有独立的词法块;当然也包括显式书写的词法块(花括弧包含的语句)。

for 循环类似, ifswitch 语句也会在条件部分创建隐式词法域,还有它们对应的执行体词法域。下面的 if-else 测试链演示了 x 和 y 的有效作用域范围:

if x := f(); x == 0 {fmt.Println(x)
} else if y := g(x); x == y {fmt.Println(x, y)
} else {fmt.Println(x, y)
}
fmt.Println(x, y) // compile error: x and y are not visible here

第二个 if 语句嵌套在第一个内部,因此第一个 if 语句条件初始化词法域声明的变量在第二个 if 中也可以访问。 switch 语句的每个分支也有类似的词法域规则:条件部分为一个隐式词法域,然后是每个分支的词法域。

if f, err := os.Open(fname); err != nil { // compile error: unused: freturn err
}
f.ReadByte() // compile error: undefined f
f.Close()    // compile error: undefined f

变量 f 的作用域只在 if 语句内,因此后面的语句将无法引入它,这将导致编译错误。你可能会收到一个局部变量 f 没有声明的错误提示,具体错误信息依赖编译器的实现。

通常需要在 if 之前声明变量,这样可以确保后面的语句依然可以访问变量:

f, err := os.Open(fname)
if err != nil {return err
}
f.ReadByte()
f.Close()

5.1 局部变量

在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,参数和返回值变量也是局部变量。

package mainimport "fmt"func main() {/* 声明局部变量 */var a, b, c int /* 初始化参数 */a = 10b = 20c = a + bfmt.Printf ("结果: a = %d, b = %d and c = %d\n", a, b, c)
}

5.2 全局变量

在函数体外声明的变量称之为全局变量,全局变量声明必须以 var 关键字开头,如果想要在外部包中使用全局变量的首字母必须大写。全局变量可以在整个包甚至外部包(被导出后)使用。

package mainimport "fmt"/* 声明全局变量 */
var g intfunc main() {/* 声明局部变量 */var a, b int/* 初始化参数 */a = 10b = 20g = a + bfmt.Printf("结果: a = %d, b = %d and g = %d\n", a, b, g)
}

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

package mainimport "fmt"/* 声明全局变量 */
var g int = 20func main() {/* 声明局部变量 */var g int = 10fmt.Printf ("结果: g = %d\n",  g)
}

5.3 形式参数

package mainimport "fmt"/* 声明全局变量 */
var a int = 20;func main() {/* main 函数中声明局部变量 */var a int = 10var b int = 20var c int = 0fmt.Printf("main()函数中 a = %d\n",  a);c = sum( a, b);fmt.Printf("main()函数中 c = %d\n",  c);
}/* 函数定义-两数相加 */
func sum(a, b int) int {fmt.Printf("sum() 函数中 a = %d\n",  a);fmt.Printf("sum() 函数中 b = %d\n",  b);return a + b;
}

以上实例执行输出结果为:

main()函数中 a = 10
sum() 函数中 a = 10
sum() 函数中 b = 20
main()函数中 c = 30

Go 学习笔记(6)— 变量定义、变量声明、变量作用域相关推荐

  1. 1、C语言面试笔试---变量定义和声明

    文章目录 1.背景 2.变量定义和声明 1.局部变量和全局变量 2.变量的存储类别 3.例题 4.内存泄漏 1.背景 2019秋招马上开始了,今天已经是7月30号了,赶紧刷刷C语言,争取在8月中旬刷完 ...

  2. 汇川使用笔记2:变量定义和非法变量定义设置

    1.变量定义 1.1 局部变量定义 局部变量,即在每个程序PRG文件中定义的变量叫局部变量.如: ①是程序PLC_PRG,②是变量定义窗口,③是逻辑程序编写窗口 PROGRAM PLC_PRG VAR ...

  3. mysql分页概念_MySQL学习笔记之数据定义表约束,分页方法总结

    本文实例讲述了MySQL学习笔记之数据定义表约束,分页方法.分享给大家供大家参考,具体如下: 1. primary key 主键 特点:主键是用于唯一标识一条记录的约束,一张表最多只能有一个主键,不能 ...

  4. C++ 笔记(05)— 变量(变量定义、声明、初始化、extern关键字、变量之间转换)

    1. 变量定义 变量定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储.变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表,如下所示: type variable_list; ...

  5. 学习笔记(6):C#急速入门-变量的概念,声明和赋值

    立即学习:https://edu.csdn.net/course/play/20589/257716?utm_source=blogtoedu 变量:给存储地址起名字. 声明变量:像系统申请内存 方式 ...

  6. 【火同学】Java学习笔记——标识符,基本数据类型,变量

    Java学习笔记 Ps:素材来源:老韩校长的Java编程课.目的是记录自己的学习历程,与商业利益无关.所有步骤都是自己根据课程内容编写,所以投原创啦! ★哔哩哔哩~搜索:这里是火同学 观看视频介绍 大 ...

  7. shell脚本编程学习笔记4(xdl)——Bash常见环境变量

    shell脚本编程学习笔记4--Bash常见环境变量 非专业运维,例如开发人员,环境变量熟悉常见的,了解不常见的即可. 1,简介 环境变量配置文件中主要是定义对系统的 操作环境生效的系统默认环境变量, ...

  8. (2)shell编程学习 Shell中的变量(预设变量表)及变量定义与特殊变量 (脚本小子的进阶之路)

    这里尽量以较简略的篇幅讲解,如果之前有Python PHP语言基础的话,学习应该非常快.当然文章篇幅有限,只能讲一些主要的地方,一些偏的知识可能不讲. 目录 变量 局部变量 环境变量 自定义环境变量 ...

  9. HTML5学习笔记(十四):变量作用域

    在JavaScript中,用var申明的变量实际上是有作用域的. 如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量: function foo() {var x = ...

  10. 廖雪峰JavaScript学习笔记(基础及数据类型、变量)

    先睹为快 alert('我要学JavaScript!'); Run: 基本语法: 1.每个语句以;结束,不强制 2.语句块用{...} 3.//单行注释,/*...*/ 多行注释 数据类型: 1.不区 ...

最新文章

  1. React 项目---class 创建组件 (11)
  2. 揭秘:1.2亿美元光刻机内部视频曝光,像科幻片一样震撼!
  3. iOS底层(三)-状态寄存器
  4. activeRecord 绑定属性的属性
  5. 多线程:线程之间的协作(join、wait、notify、notifyAll、await、signal、signalAll)
  6. kaggle研究生招生(下)
  7. tvar julia pca_景德镇品种多样PCA牛卡纸追求品质
  8. Eclipse对类固醇的重构
  9. Java基础 系统注解 @Override @Deprecated @SuppressWarnings 使用的方法及原因
  10. 从读写角度,带你了解数仓的IO基本框架
  11. 安卓第三阶段实训项目:基于网络乐库音乐播放器V1.0
  12. Android语音识别(本地+第三方)
  13. 在linux下设置开机自动启动程序的方法
  14. 显示水晶报表的公用类
  15. 工具使用——印象笔记(5)
  16. fetch git pull 切换_git中fetch和pull的区别
  17. java 验证码图片不显示图片_验证码图片生成及无法显示问题的解决
  18. 【测绘程序设计】Excel度分秒(° ‘ “)转换度(°)模板附代码超实用版
  19. c语言编程文曲星猜数字,文曲星里的猜数字代码(原创)
  20. MongoDB 学习笔记

热门文章

  1. 如果你没用过maven的install,你应该了解一下!maven中的install功能及用法。
  2. 使用myeclipse的第一步
  3. 2022-2028年中国EMI膜产业发展态势及市场发展策略报告
  4. Go 学习笔记(80)— Go 标准库 container/list(单链表、双链表)
  5. linux系统管理必备知识之关机命令
  6. 什么阻碍了人工智能在制造业的应用?
  7. 适用于Linux 2的Windows子系统上的CUDA
  8. php配置mongodb扩展、安装mongodb服务教程
  9. vim的简单介绍与使用
  10. java gui 案例_JavaGui入门—布局的嵌套使用附实例