惯例书名放在最上面《go语言高并发与微服务实战》
开始基础语法和关键字之前,上一篇遗留了几个问题:
go语言debug之Gdb Version,之前没用过C++和C,所以对于Gdb不是很熟悉,也不想特别麻烦去搞,于是想偷个懒,利用网上的方法,去下载liteidex,准备利用里面的gdb64.exe,但下载了最新版,里面没有gdb的可执行文件。但是通过liteIde发现了另外一个调试工具Delve,但是实际运行,本机的go语言版本太高,delve版本太低,空欢喜一场。于是去下载老板本的liteidex希望能在老版本里找到gdb64.exe
黄天不负有心人,终于让我找到了,接下来就是配置gdb了
配置完毕,满心欢喜
xxx.exe not in executable format: Invalid operation。
好吧,这个问题我就不擅长定位了,于是只好问baidu,结果baidu有一次告诉我,我不知道。好吧,我也没打算深入研究。放一放吧。后面回来再解决他。继续把这个归入遗留问题。我初步怀疑不像编译格式问题,有点儿可能我本机c版本的问题,因为我的eclipse之前是配置了PHP,没有用CDT那个,是不是缺少基础类库。后边继续研究吧。(有经验的可以私信我,省的我再去研究了)
那么进入正题,go语言基础语法和关键字。上一篇 其实有一个关键字是func用来声明函数。
变量的声明和初始化
通过var关键字声明变量。
变量声明的基本格式:var 变量名 数据类型 (数据类型在后)
另外还可以通过 var(变量名1 数据类型 变量名2 数据类型....)来同时声明一组变量。
**Go语言规定每一个声明的变量都必须被使用,否则编译不过。**
声明变量时,会自动把变量对应的内存区域初始化。
变量赋值Go语言和其他语言没什么差别,都通过“=”进行赋值,但Go语言本身具有强大的类型推导机制,编译器会尝试根据等号右边的表达式推导出变量的类型。
同时Go语言提供了段变量声明格式“:=”,
var a=100
b:="hello"
****":="运算符不能出现在全局变量和初始化中。同时左值中的变量最少有一个变量必须是未定义过的变量**************
和C语言相比,除了类型推导特性,Go语言还提供了多重赋值和匿名变量的语法糖特性。
比如交换a,b两个变量的值
var a int =1
var b int=2
b,a=a,b
在多重赋值中,变量的左值和右值按照从左到右的顺序赋值。有些时候我们不需要使用某些左值,可以使用匿名变量处理。通过在不需要的变量声明的地方使用“_”代替变量名,我们就可以忽略部分不需要的左值,匿名变量不占用命名空间。不会分配内存。
数据类型
数据类型各个语言都大同小异,这里只列举Go 语言的一些特性。
1.Go语言的布尔型不可与整型进行强制类型转换,并且无法参与数值运算
2.G语言中的字符串是原生数据类型,基于UTF-8编码实现,所以使用byte进行字符串遍历时,要注意汉字在utf-8中占3个字节,如果要统计字符个数,可以使用uft8.RuneCountInString()方法。
3.为了规避C语言指针编程造成的指针便宜,内存释放可能引发的错误,Go语言限制了指针类型的偏移和运算能力。使得指针类型具备高效访问的特性,但又不会发生指针偏移。Go语言中提供的自动垃圾回收机制,也减少了对指针占用内存回收的复杂性。
4.除了大家熟悉的“&”地址符职位,Go语言可以通过new函数直接分配内存,并返回指向内存的指针。
常量与类型别名
1.通过const关键字可以声明常量。声明常量的样式与声明变量非常相似.
2.可以通过type name=T,来定义类型别名。这样声明变量的时候可以用类型别名,但变量的实际类型不会变化。也可以通过type name T来声明一种新类型,,新类型原类型的特性
分支与循环控制
1.Go语言中规定与if匹配的“{”必须和表达式位于同一行,同样的,else也必须与上一个分支的“}“位于同一行,表达式两边可以省略();
2.Switch语句不需要break关键之跳出当前分支,如果需要执行接下来的case判断,需要提价fallthrough关键字对两个case进行连接。另外Go语言,Switch还能对字符串和表达式等复杂情况进行处理。
3.Go语言中循环仅提供了for关键字,没有其他语言的while或者do-while
Go中的常用容器
其实刚看到容器还是有点儿懵的,仔细一看是数组啊,切片啊,双向列表,key-value这些,我仿佛记得这在其他语言中被成为集合类型
- 数组其实相对其他语言没有什么之处。声明语法如下:
- var name [size] T
- 数组声明还可以通过new 关键字比如:students :=new([3] string)
- 数组初始化可以分别对成员进行初始化,也可以通过[...] T{"child1","child2"...}的方式来初始化,需要注意前面中括号里如果写明size,需要跟后面的元素个数相同,如果不写,用“...”代替,系统会根据成员的数量自动确定数组的大小。
- 切片
- 切片作为go语言比较特殊的一种类型,在我看来切片是对数组的动态引用,看起来之所以存在肯定是提供了附加的灵活性或者效率等的考虑,但是相比于直接操作数组,现在还没看到突出优势,回头再实际应用中慢慢体会,有新的理解再分享给大家。
- 列表
- Go语言的列表通过双向链表的方式实现。能够高效地进行元素的插入和删除操作。双向链表中每个元素都持有其前后元素的引用。
- Go语言的list是一个带头结点的链表。头结点中并不存储数据。
- 列表的初始化样式如下
- var name list.List
- name :=list.new()
- 列表并没有限制其内保存成员的类型,即任意类型的成员都可以存在列表中
- 字典
- 映射关系容器就是map,内部通过散列表的方式实现。
- map的定义格式如下:
- name :=make(map[keyType] valueType])
可以通过for语句对数组,切片和字典进行遍历
for K,v:range name{
}
如果仅仅需要遍历值或者键值,则可以使用Go语言的匿名变量
但需要注意,这个语法当中是传值遍历,对元素的修改不会影响到原容器内容。
函数与接口
- 如果函数参数,相邻的参数类型相同,可以省略类型
- 还支持对返回值进行命名
- 在使用命名返回值的函数中,函数结束前需要显示使用return语句进行返回
- Go语言参数传递都是值传递,为了减少损耗,可以通过返回指针来减少内存复制。
- 匿名函数没有函数名,经常被用作回调函数。
- 可以将匿名函数赋值给函数类型的变量,用于多此调用。
- 声明匿名函数之后,在其后加上调用的参数列表,即可对匿名函数进行调用。
- 闭包函数是有状态的函数。后面再应用里再详细展开吧。
接口声明和嵌套
接口是调用方和实现方约定的一种合作协议,调用者不关心接口的实现方式。样式如下:
type interfaceName interface{
method1(params)(return params)
method2(params)(return params)
method3(params)(return params)
}
- 当接口名的首字母和方法名的首字母皆为大写时,表示该方法是公开的,它可以被包外的代码访问调用。
- 接口间可以组合,通过嵌套将接口嵌套入其他接口来创建新的接口
结构体和方法
结构体的定义
type structName struct
{
value1 valueType1
value2 valueType2
}
- 结构体可以用json格式的键值进行赋值
后面还有接收器和内嵌和组合,但其实并不值得拿出来单独研究,当前看来还没有Go语言并没有class关键字,将struct的应用进行了扩展,起到对象的作用,而闭包函数其实也可以理解为对象。
总结一下迄今为止我理解的Go语言特性:
- Go语言在简化代码量上下足了功夫,通过匿名函数,简单赋值,类型省略等方法让编译器来解决一些约定俗成的问题。
- 在访问范围控制上通过首字母大写来解决,省略了public,private等面向对象语言中的访问修饰符
- 通过struct来实现类似对象的功能。
这一章主要是语言特性,其实看了就是建立个印象,为之后读代码建立点儿知识储备,有编程基础的完全可以不看,后续代码读多了,也就逐渐都掌握了。
下面一节进入Go语言高级特性
本文暂时没有评论,来添加一个吧(●'◡'●)