Go语言基础语法(一)

Python011

Go语言基础语法(一),第1张

本文介绍一些Go语言的基础语法。

先来看一个简单的go语言代码:

go语言的注释方法:

代码执行结果:

下面来进一步介绍go的基础语法。

go语言中格式化输出可以使用 fmt 和 log 这两个标准库,

常用方法:

示例代码:

执行结果:

更多格式化方法可以访问https://studygolang.com/pkgdoc中的fmt包。

log包实现了简单的日志服务,也提供了一些格式化输出的方法。

执行结果:

下面来介绍一下go的数据类型

下表列出了go语言的数据类型:

int、float、bool、string、数组和struct属于值类型,这些类型的变量直接指向存在内存中的值;slice、map、chan、pointer等是引用类型,存储的是一个地址,这个地址存储最终的值。

常量是在程序编译时就确定下来的值,程序运行时无法改变。

执行结果:

执行结果:

Go 语言的运算符主要包括算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符以及指针相关运算符。

算术运算符:

关系运算符:

逻辑运算符:

位运算符:

赋值运算符:

指针相关运算符:

下面介绍一下go语言中的if语句和switch语句。另外还有一种控制语句叫select语句,通常与通道联用,这里不做介绍。

if语法格式如下:

if ... else :

else if:

示例代码:

语法格式:

另外,添加 fallthrough 会强制执行后面的 case 语句,不管下一条case语句是否为true。

示例代码:

执行结果:

下面介绍几种循环语句:

执行结果:

执行结果:

也可以通过标记退出循环:

--THE END--

想进大厂,但不知道该如何入手,不妨从先过八股文的题量开始,比如先过个50题,然后一边面,一边学,进大厂就只不过是时间问题了,加油打工人!

本篇一共10题,大概花20分钟阅读。

1.golang的switch语句有什么特点?

switch关键字是通过对比key和case后面的value来选择需要执行的语句,与其他语言比如php和java不同的是,golang的switch默认不会去执行下一个case的语句,除非你显示的添加了一行fallthough关键字。

2.golang的select当有多个goroutine准备就绪,它是如何选择的?

select语句是用来处理与channel IO相关的逻辑,当有多个channel准备就绪的时候,其是伪随机选择一个goroutine来接收,然后执行相关的语句块。

Note: select关键字常用于和goroutine超时相关的逻辑设计。

3.golang什么时候会panic?

这里总结了8种,应付面试官应该是够了

4.子协程出现panic能在父协程使用recover()捕获吗?

不能,只能在子协程内部使用recover()捕获panic,协程只能捕获自己的panic。

5.什么样的panic不可恢复

6.defer函数的执行顺序是怎么样的?

7.unsafe.Pointer和uintptr是用来干什么的呢?

在golang中,为了安全性,是不允许指针像C++那样进行类型转换以及计算的,但是有些场景又必须要这么做怎么办呢?于是出现了unsafe.Pointer用于指针类型转换,比如*int64可以转换为*int64,出现了uintptr用于指针运算。

对于unsafe.Point有以下几点性质:

uintptr官方的定义是

其是用来做指针运算的

Note:

第三行的目的是为了获取age属性,age属性在stuct中处于第二列,首先是把student转换成unsafe.Point,获取指向student的指针,然后再转换成uintptr进行指针运算,然后通过unsafe.offset获取student.age相对于student的偏移量加上student的起始地址就能获得student.age的起始地址,然后转换成*int类型,就可以读取age属性了。

8.常用unsafe.Point和uintptr做什么呢,这么做有什么好处呢?

unsafe.Point常用于操作结构体的私有变量,以及类型转换。

好处就是golang中只有unsafe.Point能做到这个事,其他方法都做不到,反射的底层也是用unsafe.Point做的。

9.unsafe.Point和unintptr有什么坑呢?

千万要小心,不要为uintptr起一个中间变量 ,例如这样:

这是因为当发生gc的时候,可能会修改变量的内存地址,同时也会修改指向该变量的指针指向新的地址。但是uintptr是一个整数,其不是一个指针,因此在gc修改变量的时候,可不会修改它的值,他还指向原来的地址,然后转化成unsafe.Point进行操作,当然会报错。

10. string转byte的零拷贝技术

string在golang中的的存储结构为:

我们可以定义一个一样的结构体,然后用unsafe.Point把其转化成我们定义结构体,这样就可以把其私有属性,映射成共有属性了。

这个结构体golang已经帮我们定义好了,如下:

同理,slice的存储结构可以映射成,如下结构体,golang也已经帮我们定义好了

接来下就是具体的代码:

其实就是修改了一下byte切片data所指向的地址空间以及len就行了。

参考资料:

https://zhuanlan.zhihu.com/p/240856451 unsafe.Point

上一节中,我们为每个连接都创建了一个goroutine来读取其中的消息,现在我们将这个读取消息的方法实现一下。

我们在application目录下新建controllers目录,并在其中创建一个MessageController.go文件。

首先我们新建一个MessageController的结构体,内容如下

这个结构体包括两个内容,一个是我们将连接放在数组之后,返回的索引,另一个是连接本身.

这个是具体的方法。

我们首先设置了一下读消息的大小、超时时间以及超时后需要的操作。

超时时间如果设置为0,那么就是永不超时。之前在这里直接写0,被告知需要传一个time.Time类型的数据。最终谷歌后才得到了这个值time.Time{}为"0001-01-01 00:00:00 +0000 UTC"。

我们将用户手法消息的内容定义为一个结构体,然后将用户的订阅信息的json通过json.unmarshal转换成这个结构体。

之后的switch操作与我们在Swoole中的操作基本雷同,在查询到login之后,调用service中 的login方法来进行注册。

下一节中我们再介绍具体的注册逻辑。