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之上的高级程序 ...
随机推荐
- Java Base64编码与图片互转
import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import ...
- java中a++与++a区别
java中a++与++a区别 a++与++a的区别,如果单独使用没有任何区别,如果在运算中就有区别了,a++是先运算在赋值,而++a是先赋值在运算!! 先看a++的代码哦 class demo1 { ...
- 在web应用程序中使用MemcachedClient
本文来自:http://www.cnblogs.com/yukaizhao/archive/2008/11/10/memcached_client_usage.html 一. 背景: 在大访问量的we ...
- CF 338 D GCD Table(CRT)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove 给定一个序列,a[1 ..k],问是否存在(i , ...
- 转:Xshell显示找不到匹配的outgoing encryption算法怎么办
原文出处:http://www.xshellcn.com/xsh_column/suanfa-bpp.html 由用户反应在使用xshell和xftp连接debian 7时出现找不到匹配的outgoi ...
- Gridview 多重表头 (一)
今天看到一个人每个月更新博客,结果七年后改行去卖土特产...感慨良多... 虽然我也想去开餐厅~~ 今天需求里有一个多重表头,感觉比较奇特,特意留下记录,以防我的大脑被艾滋海默攻占~~没有女主的命,不 ...
- 未找到具有固定名称“System.Data.SQLite”的 ADO.NET 提供程序的实体框架提供程序
用户代码未处理 System.InvalidOperationException HResult=-2146233079 Message=未找到具有固定名称"System.Data. ...
- thinkPHP入门 一
简介 ThinkPHP是一个快速.简单的基于MVC和面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布,从诞生以来一直秉承简洁实用的设计原则,在保持出色的性能和至简的代码的同时,尤其注重开 ...
- 合理的使用size_t可以提高程序的可移植性和代码的可读性,让你的程序更高效。
最近研读STL源码时,发现里面有很多ptrdiff_t类型的数据,这与size_t的作用类似.以下是一篇关于size_t等平台无关类型的作用,写得很清楚.特将其记录下来. http://blog.cs ...
- Windows 端口和任务 查看 相关命令
netstat -aon|findstr " //查看端口 tasklist|findstr " //根据PID找到对应的程序 taskkill /f /t /im netbox. ...