兄弟连Go语言培训清华尹成带你实战GO案例(63)Go 原子计数器

合集下载

go bool类型 原子操作

go bool类型 原子操作

go bool类型原子操作Go语言中的bool类型原子操作是指对bool类型的数据进行原子级的读写操作,保证在多线程并发的情况下数据的一致性和正确性。

本文将详细介绍Go语言中bool类型原子操作的相关知识。

一、什么是原子操作原子操作是指在执行过程中不会被中断的操作,要么执行完毕,要么没有执行。

在并发编程中,原子操作是保证数据一致性的重要手段。

在Go语言中,通过sync/atomic包提供了一些原子操作的函数,用于对基本数据类型进行原子级操作。

二、bool类型的原子操作在Go语言中,我们可以使用atomic包中的函数对bool类型的数据进行原子操作。

具体而言,可以使用以下函数:1. func LoadUint32(addr *uint32) (val uint32)该函数用于原子地读取一个uint32类型的值,并返回读取的结果。

2. func StoreUint32(addr *uint32, val uint32)该函数用于原子地写入一个uint32类型的值。

3. func CompareAndSwapUint32(addr *uint32, old, new uint32) (swapped bool)该函数用于比较并交换一个uint32类型的值。

如果addr指向的值等于old,则将addr指向的值替换为new,并返回true;否则,不替换,返回false。

4. func SwapUint32(addr *uint32, new uint32) (old uint32)该函数用于原子地将addr指向的值替换为new,并返回原始值old。

5. func AddUint32(addr *uint32, delta uint32) (new uint32)该函数用于原子地将addr指向的值增加delta,并返回增加后的值。

三、使用示例下面通过一个示例来演示如何使用bool类型的原子操作。

```gopackage mainimport ("fmt""sync/atomic""time")func main() {var flag uint32// 启动10个并发协程for i := 0; i < 10; i++ {go func() {// 原子地将flag的值置为1atomic.StoreUint32(&flag, 1)}()}// 等待所有协程执行完毕time.Sleep(time.Second)// 原子地读取flag的值result := atomic.LoadUint32(&flag)fmt.Println("flag的值为:", result)}```在上述代码中,我们首先定义了一个uint32类型的变量flag,然后启动了10个并发协程,每个协程都会将flag的值置为1。

兄弟连区块链教程Go语言异常panic和恢复recover

兄弟连区块链教程Go语言异常panic和恢复recover

2018年时已过半,在今年的区块链热潮中,国内各家科技巨头均已粉墨登场,开始在这个新兴领域里抢占高地。

但在具体布局细节上,几大巨头又各有不同,从中亦可窥见它们各自对区块链的重视程度和期许方向。

兄弟连Go语言全栈与区块链技术培训课程是由清华、微软和谷歌名师历时半年时间研发出的独一无二的体系化课程。

课程涵盖9大学习阶段,及多个企业级项目实战和来自世界顶尖区块链比赛作品,并由以微软区块链最具价值专家尹成为代表的清华系区块链团队亲临授课,综合提升学员的职场竞争力。

Go语言不支持传统的try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。

因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。

在Go语言中,使用多值返回来返回错误。

不要用异常代替错误,更不要用来控制流程。

在极个别的情况下,才使用Go中引入的Exception处理:defer, panic, recover。

panic:1、内建函数2、假如函数F中书写了panic语句,会终止其后要执行的代码,在panic所在函数F内如果存在要执行的defer函数列表,按照defer的逆序执行3、返回函数F的调用者G,在G中,调用函数F语句之后的代码不会执行,假如函数G中存在要执行的defer函数列表,按照defer的逆序执行,这里的defer 有点类似try-catch-finally 中的finally4、直到goroutine整个退出,并报告错误recover:1、内建函数2、用来控制一个goroutine的panicking行为,捕获panic,从而影响应用的行为3、一般的调用建议a). 在defer函数中,通过recever来终止一个gojroutine的panicking过程,从而恢复正常代码的执行b). 可以获取通过panic传递的error简单来讲:go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理。

兄弟连区块链培训Go语言基础教程—指针

兄弟连区块链培训Go语言基础教程—指针

兄弟连区块链培训Go语言基础教程—指针综合市场上各类型区块链培训周期来看,目前培训周期大体可分为短期和半年期。

而区块链作为一门新兴前沿且综合性强的学科技术,对于小白用户或是有基本了解的用户来说,仅凭数天的简单镀金就想在领域内有所建树,几乎是完全不可能实现的。

兄弟连教育建议,用户在考虑培训周期时要切实结合自身目前所掌握的区块链知识的多少、培训的目的是简单的认知提升还是借此高薪就业等等。

兄弟连Go全栈与区块链课程设置为5个半月共计22周的学习时长,由浅入深进行讲解,助力于小白用户向区块链工程师的转型。

⽀支持指针类型*T,指针的指针**T,以及包含包名前缀的*<package>.T。

•默认值nil,没有NULL 常量。

•操作符"&" 取变量地址,"*" 透过指针访问⺫⽬目标对象。

•不⽀支持指针运算,不⽀支持"->" 运算符,直接⽤用"." 访问⺫⽬目标成员。

func main() {type data struct{ a int }var d = data{1234}var p *datap = &dfmt.Printf("%p, %v\n", p, p.a) // 直接⽤用指针访问⺫⽬目标对象成员,⽆无须转换。

}输出:0x2101ef018, 1234不能对指针做加减法等运算。

x := 1234p := &xp++ // Error: invalid operation: p += 1 (mismatched types *int and int)可以在unsafe.Pointer 和任意类型指针间进⾏行转换。

func main() {x := 0x12345678p := unsafe.Pointer(&x) // *int -> Pointern := (*[4]byte)(p) // Pointer -> *[4]bytefor i := 0; i < len(n); i++ {fmt.Printf("%X ", n[i])}}输出:78 56 34 12返回局部变量指针是安全的,编译器会根据需要将其分配在GC Heap 上。

兄弟连区块链培训教程Go语言高级查询

兄弟连区块链培训教程Go语言高级查询

兄弟连Go语言区块链培训教程高级查询很多人喜欢Go语言,其实是因为Go语言有其独特的语言属性在支撑着其在编程语言界的发展,今天兄弟连Go语言+区块链培训老师给大家介绍一下关于Go语言中高级查询,下面我们一起来看一下吧。

高级查询isnull:判断某个字段是否为nullfunc (this *OperatorsController) GetIsNull() {user := er{}var users []*erorm := orm.NewOrm()//创建ormqs := orm.QueryTable(user)//创建句柄n, err := qs.Filter("name__isnull", false).All(&users)if err != nil {this.Ctx.WriteString("查询失败!")return}fmt.Println("n = ", n)for _, u := range users {fmt.Println("u = ", u)}this.Ctx.WriteString("查询成功!")}in:和sql中得in含义相同,通常和Filter结合使用func (this *OperatorsController) GetIn() {user := er{}var users []*er//创建ormorm := orm.NewOrm()//创建句柄qs := orm.QueryTable(user)//SELECT * FROM USER WHERE id IN(2, 5, 6);/*buffer := []int{ 13, 14, 15, 16}n, err := qs.Filter("id__in", buffer).All(&users)*/n, err := qs.Filter("id__in", 13, 14, 15, 16).All(&users)if err != nil {this.Ctx.WriteString("查询失败!")return}fmt.Println("n = ", n)for _, u := range users {fmt.Println("u = ", u)}this.Ctx.WriteString("查询成功!")}istartswith:判断某个字段是否以指定内容开始func (this *OperatorsController) GetStartswith() {user := er{}var users []*er//创建ormorm := orm.NewOrm()//创建句柄qs := orm.QueryTable(user)//SELECT * FROM USER WHERE NAME LIKE '杜%'n, err := qs.Filter("name__startswith", "B").All(&users) if err != nil {this.Ctx.WriteString("查询失败!")return}fmt.Println("n = ", n)for _, u := range users {fmt.Println("u = ", u)}this.Ctx.WriteString("查询成功!")}gt:大于,通常和Filter结合使用func (this *OperatorsController) GetGt() {user := er{}var users []*er//创建ormorm := orm.NewOrm()//创建句柄qs := orm.QueryTable(user)//SELECT * FROM USER WHERE id > 2;n, err := qs.Filter("id__gt", 14).All(&users)if err != nil {this.Ctx.WriteString("查询失败!")return}fmt.Println("n = ", n)for _, u := range users {fmt.Println("u = ", u)}this.Ctx.WriteString("查询成功!")}contains:判断某个字段是否包含指定字段func (this *OperatorsController) GetContains() {user := er{}//创建用户指针切片,用于存储查询结果var users []*er//创建ormorm := orm.NewOrm()//创建句柄qs := orm.QueryTable(user)//SELECT * FROM USER WHERE NAME LIKE '%紫%';n, err := qs.Filter("name__contains", "o").All(&users) if err != nil {this.Ctx.WriteString("查询失败!")return}fmt.Println("n = ", n)for _, u := range users {fmt.Println("u = ", u)}this.Ctx.WriteString("查询成功!")}exact:对某个条件取反func (this *OperatorsController) GetExact() {user := er{}//创建ormorm := orm.NewOrm()//创建句柄qs := orm.QueryTable("user")//SELECT * FROM USER WHERE id = 7;//在user表中查询id等于12的用户err := qs.Filter("id__exact", 12).One(&user)if err != nil {this.Ctx.WriteString("查询失败!")return}fmt.Println("user = ", user)this.Ctx.WriteString("查询成功!") }。

兄弟连Go语言培训清华尹成带你实战GO案例(15)Go SHA1 散列

兄弟连Go语言培训清华尹成带你实战GO案例(15)Go SHA1 散列

兄弟连Go语言培训清华尹成带你实战GO案例(15)Go SHA1 散列Go SHA1 散列SHA1散列经常用来计算二进制或者大文本数据的短标识值。

git版本控制系统用SHA1来标识受版本控制的文件和目录。

这里介绍Go中如何计算SHA1散列值。

Go在crypto/* 包里面实现了几个常用的散列函数。

package mainimport "crypto/sha1"import "fmt"func main() {s := "sha1 this string"// 生成一个hash的模式是`sha1.New()`,`sha1.Write(bytes)`// 然后是`sha1.Sum([]byte{})`,下面我们开始一个新的hash// 示例h := sha1.New()// 写入要hash的字节,如果你的参数是字符串,使用`[]byte(s)`// 把它强制转换为字节数组h.Write([]byte(s))// 这里计算最终的hash值,Sum的参数是用来追加而外的字节到要// 计算的hash字节里面,一般来讲,如果上面已经把需要hash的// 字节都写入了,这里就设为nil就可以了bs := h.Sum(nil)// SHA1散列值经常以16进制的方式输出,例如git commit就是// 这样,所以可以使用`%x`来将散列结果格式化为16进制的字符串fmt.Println(s)fmt.Printf("%x\n", bs)}运行结果sha1 this stringcf23df2207d99a74fbe169e3eba035e633b65d941 / 1。

兄弟连区块链技术Go语言教程实现clock

兄弟连区块链技术Go语言教程实现clock

兄弟连区块链技术Go语言教程实现clock所有的新技术都经历了一些成长的痛苦,区块链技术也一样。

但是,尽管它还处于发展的早期阶段,但它具有改进许多行业、许多应用和系统的巨大潜力。

Go语言具有其关键特性。

Go语言之所以如此强大,是因为它在服务端的开发中总能抓住程序员的痛痒需求,用最直接、简单、高效、稳定的方式来解决并实现问题。

1 package main23 import (4 "bufio"5 "image"6 "image/color"7 "image/png"8 "math"9 "os"10 "time"11 )1213 const clock_size = 20014 const radius = clock_size / 31516 var colour color.RGBA1718 func circle(clock *image.RGBA) {19 for angle := float64(0); angle < 360; angle++ {20 radian_angle := math.Pi * 2 * angle / 36021 x := radius*math.Sin(radian_angle) + clock_size/222 y := radius*math.Cos(radian_angle) + clock_size/223 clock.Set(int(x), int(y), colour)24 }25 }26 func hand(clock *image.RGBA, angle float64, length float64) {27 radian_angle := math.Pi * 2 * angle28 x_inc := math.Sin(radian_angle)29 y_inc := -math.Cos(radian_angle)30 for i := float64(0); i < length; i++ {31 x := i*x_inc + clock_size/232 y := i*y_inc + clock_size/233 clock.Set(int(x), int(y), colour)34 }35 }36 func main() {37 clock := image.NewRGBA(image.Rect(0,0,clock_size, clock_size))38 colour.A = 25539 circle(clock)40 colour.R, colour.G, colour.B = 255,0,041 time := time.Now()42 hand(clock, (float64(time.Hour())+float64(time.Minute())/60)/12, radius*0.5) // hour hand43 colour.R, colour.G, colour.B = 0,255,044 hand(clock, (float64(time.Minute())+float64(time.Second())/60)/60, radius*0.6) // minute hand45 colour.R, colour.G, colour.B = 0,0,25546 hand(clock, float64(time.Second())/60, radius*0.8) // Second hand47 out := bufio.NewWriter(os.Stdout)48 defer out.Flush()49 png.Encode(out, clock)50 }执行时,将结果重定向到.png文件中就会生成png文件。

兄弟连区块链教程Go语言基础连接MySQL数据库操作

兄弟连区块链教程Go语言基础连接MySQL数据库操作

兄弟连区块链教程Go语言基础连接MySQL数据库操作2018年时已过半,在今年的区块链热潮中,国内各家科技巨头均已粉墨登场,开始在这个新兴领域里抢占高地。

但在具体布局细节上,几大巨头又各有不同,从中亦可窥见它们各自对区块链的重视程度和期许方向。

兄弟连Go语言全栈与区块链技术培训课程是由清华、微软和谷歌名师历时半年时间研发出的独一无二的体系化课程。

课程涵盖9大学习阶段,及多个企业级项目实战和来自世界顶尖区块链比赛作品,并由以微软区块链最具价值专家尹成为代表的清华系区块链团队亲临授课,综合提升学员的职场竞争力。

(1)导入数据库驱动import (_"/doc/33994403.html,/Go-SQL-Driver/MySQL")这里使用_ 的意思是引入后面的包名而不直接使用这个包中定义的函数,变量等资源。

若出现无法导入的情况,我们可以使用以下方式解决(以window系统为例)windows+R 打开cmd,输入go get /doc/33994403.html,/vmihailenco/redis , 回车之后会自动下载项目到GOPATH中的src目录下,然后刷新IDE。

(2)数据库连接使用sql.Open 用来打开一个注册过的数据库驱动,这里有几种连接方式,如下所示,一般我们选用第二种方式user@unix(/path/to/socket)/dbname?charset=utf8user:password@tcp(localhost:3306)/dbname?charset=utf8user:password@/dbnameuser:password@tcp([de:ad:be:ef::ca:fe]:80)/dbname(3)增删改查操作package mainimport ("database/sql""fmt"_"/doc/33994403.html,/Go-SQL-Driver/MySQL")var(DBHostsIp = "localhost:3306"DBUserName = "root"DBPassWord = "123456"DBName = "localmysql")func main(){//连接至数据库db,err := sql.Open("mysql", DBUserName+":"+DBPassWord+"@tcp("+DBHostsIp+")/"+DBN ame)CheckErr(err)insert(db)//关闭数据库连接db.Close()}//插入demofunc insert(db *sql.DB) {//准备插入操作stmt,err := db.Prepare("INSERT user (user_name,user_age,user_sex) values (?,?,?)")CheckErr(err)//执行插入操作res,err := stmt.Exec("limao",26,2)CheckErr(err)//返回最近的自增主键idid,err := /doc/33994403.html,stInsertId() fmt.Println("LastInsertId: ",id)}//查询demofunc query(db *sql.DB) {//rows:返回查询操作的结果集rows,err := db.Query("SELECT * FROM user")CheckErr(err)//第一步:接收在数据库表查询到的字段名,返回的是一个string 数组切片columns, _ := rows.Columns() // columns: [user_id user_name user_age user_sex]//根据string数组切片的长度构造scanArgs、values两个数组,scanArgs的每个值指向values相应值的地址scanArgs := make([]interface{}, len(columns))values := make([]interface{}, len(columns))for i := range values {scanArgs[i] = &values[i]}for rows.Next() {//将查询到的字段名的地址复制到scanArgs数组中err = rows.Scan(scanArgs...)CheckErr(err)//将行数据保存到record字典record := make(map[string]string)for i, col := range values {if col != nil {//字段名= 字段信息record[columns[i]] = string(col.([]byte))}}fmt.Println(record)}}//更新demofunc update(db *sql.DB) {//准备更新操作stmt1,err := db.Prepare("UPDATE user SET user_age=?,user_sex=? WHERE user_id=?") CheckErr(err) //执行更新操作res1, err := stmt1.Exec(21, 2, 1)CheckErr(err)//查询更新多少条信息num, err := res1.RowsAffected()CheckErr(err)fmt.Println(num)}//删除demofunc remove(db *sql.DB) {//准备删除操作stmt, err := db.Prepare(`DELETE FROM user WHERE user_id=?`)CheckErr(err)//执行删除操作res, err := stmt.Exec(1)CheckErr(err)//查询删除多少条信息num, err := res.RowsAffected()CheckErr(err)fmt.Println(num)}//检查错误信息func CheckErr(err error) {if err != nil {panic(err)}}总结:db.Prepare()函数用来返回准备要执行的sql操作,然后返回准备完毕的执行状态。

兄弟连教育Go语言教程(10)表达式 - 控制流

兄弟连教育Go语言教程(10)表达式 - 控制流

兄弟连教育Go语言教程(10)表达式- 控制流1. IF很特别的写法:•可省略条件表达式括号。

•⽀支持初始化语句,可定义代码块局部变量。

•代码块左⼤大括号必须在条件表达式尾部。

x := 0// if x > 10 // Error: missing condition in if statement// {// }if n := "abc"; x > 0 { // 初始化语句未必就是定义变量,⽐比如println("init") 也是可以的。

println(n[2])} else if x < 0 { // 注意else if 和else 左⼤大括号位置。

println(n[1])} else {println(n[0])}不⽀支持三元操作符"a > b ? a : b"。

2. For⽀支持三种循环⽅方式,包括类while 语法。

s := "abc"for i, n := 0, len(s); i < n; i++ { // 常⻅见的for 循环,⽀支持初始化语句。

println(s[i])}n := len(s)for n > 0 { // 替代while (n > 0) {}println(s[n]) // 替代for (; n > 0;) {}n--}for { // 替代while (true) {}println(s) // 替代for (;;) {}}不要期望编译器能理解你的想法,在初始化语句中计算出全部结果是个好主意。

func length(s string) int {println("call length.")return len(s)}func main() {s := "abcd"for i, n := 0, length(s); i < n; i++ { // 避免多次调⽤用length 函数。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

兄弟连Go语言培训清华尹成带你实战GO案例(63)Go 原子计数器
Go 原子计数器
Go里面的管理协程状态的主要机制就是通道通讯。

这些我们上面的例子介绍过。

这里还有一些管理状态的
机制,下面我们看看多协程原子访问计数器的例子,这个功能是由sync/atomic包提供的函数来实现的。

package main
import "fmt"
import "time"
import "sync/atomic"
import "runtime"
func main() {
// 我们使用一个无符号整型来代表一个永远为正整数的counter
var ops uint64 = 0
// 为了模拟并行更新,我们使用50个协程来每隔1毫秒来
// 增加一下counter值,注意这里的50协程里面的for循环,
// 也就是说如果主协程不退出,这些协程将永远运行下去
// 所以这个程序每次输出的值有可能不一样
for i := 0; i < 50; i++ {
go func() {
for {
// 为了能够保证counter值增加的原子性,我们使用
// atomic包中的AddUint64方法,将counter的地址和
// 需要增加的值传递给函数即可
atomic.AddUint64(&ops, 1)
// 允许其他的协程来处理
runtime.Gosched()
}
}()
}
//等待1秒中,让协程有时间运行一段时间
time.Sleep(time.Second)
// 为了能够在counter仍被其他协程更新值的同时安全访问counter值,
// 我们获取一个当前counter值的拷贝,这里就是opsFinal,需要把
// ops的地址传递给函数`LoadUint64`
opsFinal := atomic.LoadUint64(&ops)
}
我们多运行几次,结果如下: ops: 7499289
ops: 7700843
ops: 7342417。

相关文档
最新文档