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之上的高级程序 ...
随机推荐
- 谋哥:研究App排行榜浮出的神器
昨天发的<App排行榜的秘密>到头条网,阅读量到2万,踩的比顶的多几倍.原因是由于我使用360市场的数据来分析,而且这帮喷子根本不看你分析数据背后的意义,反正看到自己不喜欢的比方" ...
- Java - 反射机制(Reflection)
Java - 反射机制(Reflection) > Reflection 是被视为 动态语言的关键,反射机制允许程序在执行期借助于 Reflection API 取得任何类的 ...
- nth-child和nth-of-type的区别
以前一般都用:nth-child,后来知道了:nth-of-type,然后就一般用nth-of-type 它们两有什么区别呢? 首先来看个现象: 假如有这样一个HTML结构 <div class ...
- B - Numbers That Count
Description "Kronecker's Knumbers" is a little company that manufactures plastic di ...
- XML新手入门 创建构造良好的XML(1)
XML新手入门 创建构造良好的XML(1) 2009-03-19 09:24 Kay Whatley IBM Developerworks 我要评论(0) 字号:T | T 本文描述了构建良好的XML ...
- MySQL的基本数据类型与数据类型优化
1.选择优化的数据类型的标准 1)更小的通常更好. 一般情况下,应该尽量使用可以正确存储数据的最小数据类型.更小的数据类型通常更快,因为他们占用更少的磁盘.内存和CPU缓存,并且处理时需要的CPU周期 ...
- 正式学习React(四) 前序篇
预热 redux 函数内部包含了大量柯里化函数以及代码组合思想 柯里化函数(curry) 通俗的来讲,可以用一句话概括柯里化函数:返回函数的函数 // example const funcA = (a ...
- PHP设计模式之装饰器模式
装饰器模式:如果已有对象的部分内容或功能性发生改变,但是不需要修改原始对象的结构或不使用继承,动态的扩展一个对象的功能,则应该使用装饰器模式.简单点说:就是我们不应该去修改已有的类,而是通过创建另外一 ...
- psacct监视用户执行的命令,如cpu时间和内存战胜,实时进程记账
psacct监视用户执行的命令,如cpu时间和内存战胜,实时进程记账
- C语言的本质(27)——C语言与汇编之计算机结构
现代计算机都是基于冯·诺依曼或哈佛体系结构的,不管是嵌入式系统.个人电脑还是服务器.这种两种体系结构的主要特点是:CPU和内存是计算机的两个主要组成部分,内存中保存着数据和指令,CPU从内存中取指令执 ...