Golang 学习笔记-----变量

命名

命名规则

关键字重复

访问范围

命名风格 

声明

初始化

一般变量初始化 

默认变量初始化

简短变量初始化

new变量初始化
使用 
原理 
make变量初始化
使用
原理 

作用范围

生命周期
           垃圾回收机制 

赋值

基本赋值操作
元组赋值操作 


命名

命名规则

一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意 数量的字母、数字或下划线。
大写字母和小写字母是不同的:heapSort和Heapsort是两个不 同的名字。 

关键字重复

关键字不能用于自定义名字,只能在特定语法结构 中使用。 

关键字如下
break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var

 

这些内部预先定义的名字并不是关键字,你可以再定义中重新使用它们。
在一些特殊的场景 中重新定义它们也是有意义的,但是也要注意避免过度而引起语义混乱。 

访问范围

1.如果一个名字是在函数内部定义,那么它的就只在函数内部有效。


2.如果是在函数外部定义, 那么将在当前包的所有文件中都可以访问。


3.名字的开头字母的大小写决定了名字在包外的可 见性。如果一个名字是大写字母开头的,那么它将是导出的,
也就是说可以被外部的包访问,例如fmt包的 Printf函数就是导出的,可以在fmt包外部访问。
包本身的名字一般总是用小写字母。

命名风格 

1,名字的长度没有逻辑限制,但是Go语言的风格是尽量使用短小的名字
2,在习惯上,Go语言程序员推荐使用 驼峰式 命名,比如QuoteRuneToASCII和parseRequestLine 这样的函数命名 

 

声明

 

1.var、const、type和func,分别对应变量、常量、类型和函数实体对象的声明。
 var 变量名字 类型 = 表达式 
2.可以在一个声明语句中同时声明一组变量, 
var i, j, k int // int, int, int

 

初始化

一般变量初始化 

1. 一般语法如下: var 变量名字 类型 = 表达式

2.可以初始化多组: var b, f, s = true, 2.3, "four" // bool, float64, string

3.一组变量也可以通过调用一个函数,
由函数返回的多个返回值初始化: var f, err = os.Open(name) // os.Open returns a file and an error

默认变量初始化 

其中“类型”或“= 表达式”两个部分可以省略其中的一个。

如果省略的是类型信息,那么将根据 初始化表达式来推导变量的类型信息。

如果省略的是"="表达式,那么将用零值初始化该变 量。
数值类型变量对应的零值是0,
布尔类型变量对应的零值是false,
字符串类型对应的零 值是空字符串,
接口或引用类型(包括slice、map、chan和函数)变量对应的零值是nil。
数 组或结构体等聚合类型对应的零值是每个元素或字段都是对应该类型的零值。 
零值初始化机制可以确保每个声明的变量总是有一个良好定义的值
因此在Go语言中不存在 未初始化的变量。

在包级别声明的变量会在main入口函数执行前 完成初始化,
局部变量将在声明语句被执行到的时候完成初始化。 

 



 

简短变量初始化

1. 一般语法如下:以“名字 := 表达式”形式声明变量,变量的类型根据表达式来自动推导类型 从而初始化。

2.可以初始化多组: i,j := 0,1

3.一组变量也可以通过调用一个函数,
由函数返回的多个返回值初始化:  f, err: = os.Open(name) // os.Open returns a file and an error

new变量初始化

对于引用类型的变量(指针,切片 ,字典等),我们不光要声明它,还要为它分配内容空间,否则我们的值放在哪里去呢?

对于值类型的声明不需要,是因为已经默认帮我们分配好了,所以用上面的三种初始化的方式就可以了

要分配内存,就引出来new和make。

使用 

func main() {
 var i *int
 i=new(int)
 *i=10
 fmt.Println(*i)
}

原理 

1.首先 new 是内建函数,它的定义也很简单:
func new(Type) *Type


2.官方文档对于它的描述是:
内建函数 new 用来分配内存,它的第一个参数是一个类型,不是一个值,
它的返回值是一个指向新分配类型零值的指针



3.根据这段描述,我们可以自己实现一个类似 new 的功能:

func newInt() *int {
  var i int
  return &i
}
someInt := newInt()

我们这个函数的功能跟 someInt := new(int) 一模一样。
所以在我们自己定义 new 开头的函数时,出于约定也应该返回类型的指针。


4.new用来分配内存,但与其他语言中的同名函数不同,它不会初始化内存,只会讲内存置零;
也就是说,new(T)会为类型为T的新项分配已置零的内存空间,并返回他的地址,也就是一个类型为*T的值。

make变量初始化

使用

func main() {

    m := make(map[int]int)

    m[1] = 2

    fmt.Println(m)
}

// Output:
map[1:2]

原理 

同:

1.make和new都是golang用来分配内存的內建函数 在堆上分配内存 


异:

1.make返回的还是引用类型本身;而new返回的是指向类型的指针。
2.make只能用来分配及初始化类型为slice,map,channel的数据;new可以分配任意类型的数据。
3.make返回已初始化(非零值)的值 new返回值为0的地址的指针

作用范围

 


生命周期

 

1.变量的生命周期指的是在程序运行期间变量有效存在的时间间隔。

2.对包一级声明的变量来说:
它们的生命周期和整个程序的运行周期是一致的。

3.对局部变量来说:
 从每次创建一个新变量的声明语句开始,
直到该变量不再被引用为止,然后 变量的存储空间可能被回收。

垃圾回收机制 

上面说到new和make 设计到变量的内存开辟与使用 
也就相应的会涉及到内存管理的问题
曾几何时,内存管理是程序员开发应用的一大难题。
传统的系统级编程语言(主要指C/C++)中,
程序员必须对内存小心的进行管理操作,控制内存的申请及释放。
稍有不慎,就可能产生内存泄露问题,
这种问题不易发现并且难以定位,
一直成为困扰开发者的噩梦。

如何解决这个头疼的问题呢?过去一般采用两种办法:
1.内存泄露检测工具。这种工具的原理一般是静态代码扫描,
通过扫描程序检测可能出现内存泄露的代码段。
然而检测工具难免有疏漏和不足,只能起到辅助作用。


2.智能指针。这是 c++ 中引入的自动内存管理方法,
通过拥有自动内存管理功能的指针对象来引用对象,
是程序员不用太关注内存的释放,而达到内存自动释放的目的。
这种方法是采用最广泛的做法,
但是对程序员有一定的学习成本(并非语言层面的原生支持),
而且一旦有忘记使用的场景依然无法避免内存泄露。


3.为了解决这个问题,后来开发出来的几乎所有新语言(java,python,php等等)
都引入了语言层面的自动内存管理 – 
也就是语言的使用者只用关注内存的申请而不必关心内存的释放,
内存释放由虚拟机(virtual machine)或运行时(runtime)来自动进行管理。
而这种对不再使用的内存资源进行自动回收的行为就被称为垃圾回收。

关于Golang的垃圾回收机制 可以看这篇博文
https://www.cnblogs.com/diegodu/p/9150840.html
 

赋值

基本赋值操作

 

元组赋值操作 

 

发布了84 篇原创文章 · 获赞 18 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/vjhghjghj/article/details/104083753