Go 语言编程实例(四)

互斥体

在前面的例子中,我们看到了如何使用原子操作来管理简单的计数器状态。对于更复杂的状态,可以使用 互斥体 来安全地访问多个 goroutine 中的数据。

在这个例子中,状态(state)是一个映射。示例中的互斥将同步访问状态。我们将跟踪执行的读写操作数量。

这里启动 100 个 goroutine 来对状态执行重复读取,每个 goroutine 中每 ms 读取一次。对于每个读取,我们选择一个键来访问。Lock() 互斥体以确保对状态的独占访问,读取所选键的值, Unlock() 互斥体,并增加 readOps 计数。

我们还将启动 10 个 goroutine 来模拟写入,使用与读取相同的锁模式。

让 10 个 goroutine 在状态和互斥体上工作一秒钟。采集和报告最终操作计数。手机和报告最终操作计数。用最后的锁状态,显示它是如何结束了。

package main

import (
    "sync"
    "math/rand"
    "sync/atomic"
    "time"
    "fmt"
)

func main(){
    var state = make(map[int]int)

    var mutex = &sync.Mutex{}

    var readOps  uint64 = 0
    var writeOps uint64 = 0

    for r := 0 ; r < 100 ; r ++{
        go func() {
            total := 0
            for{
                key:= rand.Intn(5)
                mutex.Lock()
                total += state[key]
                mutex.Unlock()
                atomic.AddUint64(&readOps , 1)

                time.Sleep(time.Millisecond)
            }
        }()
    }

    for w:= 0 ; w < 10 ; w ++{
        go func() {
            for{
                key := rand.Intn(5)
                val := rand.Intn(100)
                mutex.Lock()
                state[key] = val
                mutex.Unlock()
                atomic.AddUint64(&writeOps,1)
                time.Sleep(time.Millisecond)
            }
        }()
    }

    time.Sleep(time.Second)

    readOpsFinal := atomic.LoadUint64(&readOps)
    fmt.Println("readops:",readOpsFinal)

    writeOpsFinal := atomic.LoadUint64(&writeOps)
    fmt.Println("writeops",writeOpsFinal)

    mutex.Lock()
    fmt.Println("state",state)
    mutex.Unlock()
}

Go排序实例

Go语言的 sort 包实现了内置和用户定义类型的排序。排序方法特定于内置类型,排序是一个就地排序,不会生成新的切片。

这里举例了一个 int 一个 string 类型的例子。

package main

import (
    "sort"
    "fmt"
)

func main(){
    // example for string
    strs := []string{"c","a","b"}
    sort.Strings(strs)

    fmt.Println("Strings:",strs)

    //example of sorting
    ints := []int{7,2,4}
    sort.Ints(ints)
    fmt.Println("Ints: ",ints)

    //使用 sort 检查是相关 slice 是否已经被排好序
    s := sort.IntsAreSorted(ints)
    fmt.Println("sorted: ",s)
    
}

Go自定义函数

有时候,我们希望通过使用自然排序意外的其他方式对集合进行排序。例如,假设我们想通过字符串长度进行排序,下面是Go语言中自定义排序的类型。

为了使用Go语言中的自定义函数进行排序,我们需要一个相应的类型。这里创建了一个 ByLength 类型,它只是内置 []string 类型的别名。

需要实现 sort.Interface - Len , Less , Swap 在这个类型上,所以可以使用 sort 包中的一般 Sort 函数。 Len 和 Swap 通常在类型之间是相似的, Less 保存实际的自定义排序逻辑。在这个例子中,要按照字符串长度的增加顺序排序,因此在这里使用 len(s[i]) 和 len(s[j])。

所有这些都到位后,现在可以通过将原始 fruits 切片转换为 ByLength 来实现自定义排序,然后对该类型切片使用 sort.Sort() 方法。

package main

import (
    "sort"
    "fmt"
)

//定义类型
type ByLength []string

//重写下面几个接口函数
func (s ByLength) Len()int{
    return len(s)
}

func (s ByLength) Swap(i,j int){
    s[i],s[j] = s[j],s[i]
}

func (s ByLength) Less(i,j int) bool {
    return len(s[i]) < len(s[j])
}


//正常调用方法
func main(){
    fruits := []string{"peach","banana","kiwi"}
    sort.Sort(ByLength(fruits))
    fmt.Println(fruits)
}

Go panic 错误处理实例

Panic 通常意味着失去出乎意料的错了。大多数情况下,使用他来正常运行时不应该出现的错误,或者不准备妥善处理。

在程序中可使用 Panic 来检查意外的错误。

如果一个函数返回一个我们不知道如何(或想要)处理的错误值,那么 Panic 的常见用法就是终止。这里有一个例子,如果在创建一个新文件时需要意外的错误。

运行此程序将导致程序出错,打印错误消息和 goroutine 跟踪,并退出非零状态。

package main

import "os"

func main(){

    panic("a problem")

    _,err := os.Create("./test.log")
    if err != nil{
        panic(err)
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容

  • 第一章五个程序 都很好!但是初学编程/没有其他语言基础的不容易看懂。 记一遍不熟悉的东西: who = strin...
    暗黑破坏球嘿哈阅读 1,424评论 0 10
  • Go入门 Go介绍 部落图鉴之Go:爹好还这么努力? 环境配置 安装 下载源码编译安装 下载相应平台的安装包安装 ...
    齐天大圣李圣杰阅读 4,580评论 0 26
  • 出处---Go编程语言 欢迎来到 Go 编程语言指南。本指南涵盖了该语言的大部分重要特性 Go 语言的交互式简介,...
    Tuberose阅读 18,412评论 1 46
  • 幼儿园时,我盼望升小学。“到了小学我就可以俯视幼儿园同学了!”多么幼稚的我啊!所以我对小学也多了一份期待。 可是也...
    三鹿之汪疯阅读 258评论 0 0
  • 人们经常会说某人比较靠谱,某人办事不靠谱。那么靠谱是什么? 我的理解是:凡事要有责任,勇于担当,及时坦诚交流,善始...
    李昌红阅读 709评论 0 1