golang高级部分
一、golang之OOP(orient object programming)
在函数声明时, 在其名字之前放上一个变量, 即是一个方法。 这个附加的参数会将该函数附加到这种类型上, 即相当于为这种类型定义了一个独占的方法。(c++中称成员函数)
二、Goroutine和Channels
在golang中,每一个并发的执行单元叫做一个goroutine;而channel则是它们之间的通信机制,它可以让一个goroutine通过channel给另一个goroutine发送消息;需要注意的是,每个channel都有一个特殊的类型;
ch := make(chan int)
close(ch) //关闭channel
2.1 无buffer channel
ch := make(chan int) or ch := make(chan int , 0)
一个基于无缓存Channels的发送操作将导致发送者goroutine阻塞, 直到另一个goroutine在相同的Channels上执行接收操作, 当发送的值通过Channels成功传输之后, 两个goroutine可以继续执行后面的语句。 反之, 如果接收操作先发生, 那么接收者goroutine也将阻塞, 直
到有另一个goroutine在相同的Channels上执行发送操作。
基于无缓存Channels的发送和接收操作将导致两个goroutine做一次同步操作。 因为这个原因, 无缓存Channels有时候也被称为同步Channels。 当通过一个无缓存Channels发送数据时, 接收者收到数据发生在唤醒发送者goroutine之前;
2.2 单方向的channel
类型 chan<- int 表示一个只发送int的channel, 只能发送不能接收。 相反, 类型 <-chan int 表示一个只接收int的channel, 只能接收不能发送。 ( 箭头 <- 和关键字chan的相对位置表明了channel的方向。 ) 这种限制将在编译期检测。
12 // out 只发 channel
13 // in 只收channel
14 func squares(out chan<- int, in <-chan int) {
15 for v := range in {
16 out <- v * v
17 }
18 close(out)
19 }
2.3 带buffer的channel
ch = make(chan string, 3)
向缓存Channel的发送操作就是向内部缓存队列的尾部插入元素, 接收操作则是从队列的头部删除元素。 如果内部缓存队列是满的, 那么发送操作将阻塞直到因另一个goroutine执行接收操作而释放了新的队列空间。 相反, 如果channel是空的, 接收操作将阻塞直到有另一个
goroutine执行发送操作而向队列插入元素。
获取channel的容量:cap(ch) 获取channel数据的长度:len(ch)
三、select多路复用
package main import (
"fmt"
//"time"
) /*
select {
case <-ch1:
// ...
case <-ch2:
// ...
case <-ch3:
// ...
default:
// ...
}
*/ func main() {
j := make(chan int, 1)
//tick := time.Tick(1 * time.Second)
for down := 10; down > 0; down-- {
fmt.Println("down to here")
select {
case x := <-j:
fmt.Println(x)
case j <- down:
fmt.Println("put to j")
}
}
}
一、并发
一般情况下,我们没法知道分别位于两个goroutine事件x和y的执行顺序,x是在y之前还是之后还是同时发生是没法判断的。 当我们能够没有办法明确地确认一个事件是在另一个事件的前面或者后面发生的话, 就说明x和y这两个事件是并发的。
如何避免竞争?
由于其它的goroutine不能够直接访问变量, 它们只能使用一个channel来发送给指定的goroutine请求来查询更新变量。 这也就是Go的口头禅“不要使用共享数据来通信;使用通信来共享数据”。 一个提供对一个指定的变量通过cahnnel来请求
的goroutine叫做这个变量的监控(monitor)goroutine。
二、互斥
互斥原型实现:
var (
sema = make(chan struct{}, 1)
balance int
) func Add(amount int) {
sema <- struct{}{}
balance = balance + amount
<-sema
} func Get() int {
sema <- struct{}{}
b := balance
<-sema
} import "sync"
var (
mu sync.Mutex
balance int
)
func Add(amount int){
mu.Lock()
balance = balance + amount
mu.Unlock()
} func Get() int {
mu.Lock()
b := balance
mu.Unlock()
}
func Get() int {
mu.Lock()
defer mu.Unlock()
b := balance
return b
}
2.1 读写锁
var rwmu sync.RWMutex ----用于多度少写
rwmu.Rlock() / rwmu.RUnlock() ----读锁定,此时只能进行读操作
rwmu.Lock() / rwmu.Unlock() ----读写锁定
2.2 sync.Once初始化
/*
sync.Once。 概念上来讲,
一次性的初始化需要一个互斥量mutex和一个boolean变量来记录初始化是不是已经完成了;
互斥量用来保护boolean变量和客户端数据结构。 Do这个唯一的方法需要接收初始化函数作为
其参数。
*/
var loadIconsOnce sync.Once
var icons map[string]int
func loadIcons() {
icons["first"] = 1
icons["second"] = 2
icons["thrid"] = 3
} func Icon(name string) int {
loadIconsOnce.Do(loadIcons)
return icons[name]
}
2.3 sync.WaitGroup
先说说WaitGroup的用途:它能够一直等到所有的goroutine执行完成,并且阻塞主线程的执行,直到所有的goroutine执行完成。这里要注意一下,他们的执行结果是没有顺序的,调度器不能保证多个 goroutine 执行次序,且进程退出时不会等待它们结束。
WaitGroup总共有三个方法:Add(delta int),Done(),Wait()。简单的说一下这三个方法的作用。
Add:添加或者减少等待goroutine的数量
Done:相当于Add(-1)
Wait:执行阻塞,直到所有的WaitGroup数量变成0
如:
golang中的同步是通过sync.WaitGroup来实现的.WaitGroup的功能:它实现了一个类似队列的结构,可以一直向队列中添加任务,当任务完成后便从队列中删除,如果队列中的任务没有完全完成,可以通过Wait()函数来出发阻塞,防止程序继续进行,直到所有的队列任务都完成为止.
WaitGroup的特点是Wait()可以用来阻塞直到队列中的所有任务都完成时才解除阻塞,而不需要sleep一个固定的时间来等待.但是其缺点是无法指定固定的goroutine数目.可能通过使用channel解决此问题。
golang高级部分的更多相关文章
- GO语言的进阶之路-Golang高级数据结构定义
GO语言的进阶之路-Golang高级数据结构定义 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们之前学习过Golang的基本数据类型,字符串和byte,以及rune也有所了解, ...
- golang 高级
下面的EmployeeByID函数将根据给定的员工ID返回对应的员工信息结构体的指针.我们可以使用点操作符来访问它里面的成员: func EmployeeByID(id int) *Employee ...
- golang高级用法总结
sync.WaitGroup add() done() wait() 相当于计数器,done会减一,wait会等待所有线程都执行完才执行下面代码 sync.pool 用来封装连接池
- JOIN US | SphereEx 精英集结
新环境.新气象,SphereEx 欢迎志同道合的你加入! 关于 SphereEx 北京思斐软件技术有限公司(sphere-ex.com),是一家致力于构建新型分布式数据基础设施的公司,秉承开源.共享. ...
- [转]Go的50坑:新Golang开发者要注意的陷阱、技巧和常见错误-高级
from : https://levy.at/blog/11 进阶篇 关闭HTTP的响应 level: intermediate 当你使用标准http库发起请求时,你得到一个http的响应变量.如果你 ...
- 1、Golang基础--Go简介、环境搭建、变量、常量与iota、函数与函数高级
1 Go语言介绍 1 golang-->Go--->谷歌公司 2009年 golang:指go语言,指的go的sdk goland:软件,ide:集成开发环境 Java写的 2 Go是静态 ...
- 一键打造vim ide 支持python golang shell等高级特性
1.vim-for-devops github: https://github.com/yxxhero/vim_for_devops 利用vim插件打造支持python.shell.golang的id ...
- golang枚举类型 - iota用法拾遗
在c#.java等高级语言中,经常会用到枚举类型来表示状态等.在golang中并没有枚举类型,如何实现枚举呢?首先从枚举的概念入手. 1.枚举类型定义 从百度百科查询解释如下:http://baike ...
- Golang与C#之switch区别
Golang与C#之switch区别 Go是Google开发的一种编译型,可并行化,并具有垃圾回收功能的编程语言. C#是微软公司发布的一种面向对象的.运行于.NET Framework之上的高级程序 ...
随机推荐
- 第五章 Logistic回归
第五章 Logistic回归 假设现在有一些数据点,我们利用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称作回归. 为了实现Logistic回归分类器,我们可以在每个特征上都乘以一 ...
- 从客户端(Content="<p>666</p>")中检测到有潜在危险的 Request.Form 值。
出现:从客户端(Content="<p>测试</p>")中检测到有潜在危险的 Request.Form 值. 一般是在线编辑器有HTML标签的,我是用的MV ...
- Hadoop: Start-all.sh 后发现JPS后Namenode没有启动
重新格式化Namenode:hadoop namenode -format 然后启动hadoop:start-all.sh 执行下JPS命令就可以看到NameNode了
- c++中各种数据类型所占字节
求各种数据类型所占用的字节数可调用sizeof函数,求各种数据类型的最大值可以调用limits标准库中的numeric_limits<T>::max(),numeric_limits< ...
- SqlLikeAttribute 特性增加 左、右Like实现
SqlLikeAttribute 特性原来只实现了全Like,今天增加左.右Like实现 更新时间:2016-04-30 /// <summary> /// 获取查询条件语句 /// &l ...
- java面对对象 关键字this super
this:this是指向对象本身的一个指针,成员函数内部指向当前类的对象 其实this主要要三种用法: 1.表示对当前对象的引用! 2.表示用类的成员变量,而非函数参数,注意在函数参数和成员变量同名是 ...
- 3D模型制作
agisoft: http://www.agisoft.com/downloads/installer/ http://pan.baidu.com/s/1dDwA3tf http://pan.baid ...
- (原)android的JNI中使用C++的类
android的JNI代码中可以调用C++的类,但是不能直接调用,要加上一个类似于接口的java类,这个类内部调用C++的类.实际上和接口类直接调用C++中的函数差不多,只是稍微复杂了一点. 1. 写 ...
- Joomla JEvents 组件
JEvents http://extensions.joomla.org/extensions/extension/calendars-a-events/events/jevents Getting ...
- undefined reference to `_sbrk', `_write', `_lseek', `_read'
现象: 在用GCC编译嵌入式MCU程序时,由于使用了第三方的库,出现了类似undefined reference to `_sbrk', `_write', `_lseek', `_read'的连接错 ...