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之上的高级程序 ...
随机推荐
- HBase--DependentColumnFilter(参考例过滤器 )详解
DependentColumnFilter是一种允许用户指定一个参考列或引用列来过滤其他列的过滤器,过滤的原则是基于参考列的时间戳来进行筛选 . 官方说明: 大意:此过滤器提供两个参数--列族和列限定 ...
- 熬之滴水穿石:Spring--精简的J2EE(5)
47--Spring的MVC 在Spring的框架中也存在MVC这样的模式,在Spring下有2个这样的控制器一个叫Controller, ...
- SQL With(递归 CTE 查询)
本文来自:http://www.cnblogs.com/smailxiaobai/archive/2012/01/16/2323291.html 指定临时命名的结果集,这些结果集称为公用表表达式 (C ...
- Zjnu Stadium(hdu3047带权并查集)
题意:一个300列的无限行的循环场地,a b d代表a,b顺时针相距d的距离,现在给你一些距离,判断是否有冲突,如果有冲突计算冲突的次数 思路:带权并查集 a,b的距离等于b到根节点的距离 - a到根 ...
- 【贪心】【POJ3154】墓地雕塑(Graveyard, NEERC 2006, LA 3708)需要稍稍加工的(先贪心,再确保能这样贪(可行性&&如果可行必定最优&&非证明最优性)的题)(K)
例题4 墓地雕塑(Graveyard, NEERC 2006, LA 3708) 在一个周长为10000的圆上等距分布着n个雕塑.现在又有m个新雕塑加入(位置可以随意放),希望所有n+m个雕塑在圆周 ...
- 初次使用Oracle
这是我第一次写博客,主要是记录下自己这半个多月以来的学习笔记,以备以后可以随时查看. 首先就是安装Oracle的问题的,我系统是Win7 64位的,出现各种问题郁闷得不行,最终安装个Oracle102 ...
- .NET MySQL的参数化查询
MySqlConnection conn = new MySqlConnection(SqlConnnectString); MySqlCommand cmd = new MySqlCommand(& ...
- 76 bytes for faster jQuery
转载自http://james.padolsey.com/javascript/76-bytes-for-faster-jquery/ 作者JAMES PADOLSEY 在我们平时使用JQuery,调 ...
- css基础之 联网使用bootstrap
在<head></head>中添加 <meta charset="utf-8"> <meta http-equiv="X-UA- ...
- 2015.4.16-SQL-内连接与外连接
1.内连接 如图: 关键字 inner join 2.外连接 分为左外连接 和右外连接,即如果是左外连接,即使左面没有值,也会显示为null, 右外连接也如此 关键字 left join ; righ ...