重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
1、new 的主要特性
创新互联公司专业为企业提供吉县网站建设、吉县做网站、吉县网站设计、吉县网站制作等企业网站建设、网页设计与制作、吉县企业网站模板建站服务,10多年吉县做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。
首先 new 是内建函数,定义也很简单:
func new(Type) *Type
内建函数 new 用来分配内存,第一个参数是一个类型,不是一个值,返回值是一个指向新分配类型零值的指针
实现一个类似 new 的功能:
func newInt() *int {
var i int
return i
}
someInt := newInt()
函数的功能跟 someInt := new(int) 一模一样。定义 new 开头的函数时,出于约定也应该返回类型的指针。
2、make 的主要特性
make 也是内建函数,定义比 new 多了一个参数,返回值也不同:
func make(Type, size IntegerType) Type
内建函数 make 用来为 slice,map 或 chan 类型分配内存和初始化一个对象(注意:只能用在这三种类型上),跟 new 类似,第一个参数也是一个类型而不是一个值,跟 new 不同的是,make 返回类型的引用而不是指针,而返回值也依赖于具体传入的类型,具体说明如下:
Slice: 第二个参数 size 指定了长度,容量和长度相同。
可以传入第三个参数来指定不同的容量值,但必须不能比长度值小。
比如 make([]int, 0, 10)
Map: 根据 size 大小来初始化分配内存,不过分配后的 map 长度为 0,如果 size 被忽略了,那么会在初始化分配内存时分配一个小尺寸的内存
Channel: 管道缓冲区依据缓冲区容量被初始化。如果容量为 0 或者忽略容量,管道没有缓冲区。
3、总结
new 的作用是初始化一个指向类型的指针(*T),make 的作用是为 slice,map 或 chan 初始化并返回引用(T)。
本文介绍一些Go语言的基础语法。
先来看一个简单的go语言代码:
go语言的注释方法:
代码执行结果:
下面来进一步介绍go的基础语法。
go语言中格式化输出可以使用 fmt 和 log 这两个标准库,
常用方法:
示例代码:
执行结果:
更多格式化方法可以访问中的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--
Hello,大家好,又见面了!上一遍我们将 channel 相关基础以及使用场景。这一篇,还需要再次进阶理解channel 阻塞问题。以下创建一个chan类型为int,cap 为3。
channel 内部其实是一个环形buf数据结构 ,是一种滑动窗口机制,当make完后,就分配在 Heap 上。
上面,向 chan 发送一条“hello”数据:
如果 G1 发送数据超过指定cap时,会出现什么情况?
看下面实例:
以上会出现什么,chan 缓冲区允许大小为1,如果再往chan仍数据,满了就会被阻塞,那么是如何实现阻塞的呢?当 chan 满时,会进入 gopark,此时 G1 进入一个 waiting 状态,然后会创建一个 sudog 对象,其实就sendq队列,把 200放进去。等 buf 不满的时候,再唤醒放入buf里面。
通过如下源码,你会更加清晰:
上面,从 chan 获取数据:
Go 语言核心思想:“Do not communicate by sharing memory; instead, share memory by communicating.” 你可以看看这本书名叫:Effective Go
如果接收者,接收一个空对象,也会发生什么情况?
代码示例 :
也会报错如下:
上面,从 chan 取出数据,可是没有数据了。此时,它会把 接收者 G2 阻塞掉,也是和G1发送者一样,也会执行 gopark 将状态改为 waiting,不一样的点就是。
正常情况下,接收者G2作为取出数据是去 buf 读取数据的,但现在,buf 为空了,此时,接收者G2会将sudog导出来,因为现在G2已经被阻塞了嘛,会把G2给G,然后将 t := -ch 中变量 t 是在栈上的地址,放进去 elem ,也就是说,只存它的地址指针在sudog里面。
最后, ch - 200 当G1往 chan 添加200这个数据,正常情况是将数据添加到buf里面,然后唤醒 G2 是吧,而现在是将 G1 的添加200数据直接干到刚才G2阻塞的t这里变量里面。
你会认为,这样真的可以吗?想一想,G2 本来就是已经阻塞了,然后我们直接这么干肯定没有什么毛病,而且效率提高了,不需要再次放入buf再取出,这个过程也是需要时间。不然,不得往chan添加数据需要加锁、拷贝、解锁一序列操作,那肯定就慢了,我想Go语言是为了高效及内存使用率的考虑这样设计的。(注意,一般都是在runtime里面完成,不然会出现象安全问题。)
总结 :
chan 类型的特点:chan 如果为空,receiver 接收数据的时候就会阻塞等待,直到 chan 被关闭或者有新的数据到来。有这种个机制,就可以实现 wait/notify 的设计模式。
相关面试题: