Go学习笔记(七)

(文章持续更新中...有志同道合的人能够一块儿探讨下。整个系列(1~8)准备重写,不过都是很基础的入门笔记,想学到很深刻的东西则不建议阅读...)bash

接口是双方约定的一种合做协议。每一个接口类型由数个方法组成并发

type 接口类型名 interface{
    方法名1( 参数列表1 ) 返回值列表1
    方法名2( 参数列表2 ) 返回值列表2
    …
}

type Writer interface {
    Write(p []byte) (n int, err error)
}
复制代码
  • 接口的方法与实现接口的类型方法格式一致.实现接口类型中的方法的名称、参数列表、返回参数列表中的任意一项与接口要实现的方法不一致,那么接口的这个方法就不会被实现。
  • 接口中全部方法均被实现.当一个接口中有多个方法时,只有这些方法都被实现了,接口才能被正确编译并使用

Go 语言的源码复用创建在包(package)基础之上.Go 语言的入口 main() 函数所在的包(package)叫 main,main 包想要引用别的代码,必须一样以包的方式进行引用,Go 语言的包与文件夹一一对应,全部与包相关的操做,必须依赖于工做目录(GOPATH)函数

GOPATH 绝对路径提供项目的工做目录ui

goroutine 的概念相似于线程,但 goroutine 由 Go 程序运行时的调度和管理。Go 程序会智能地将 goroutine 中的任务合理地分配给每一个 CPUspa

Go 程序中使用 go 关键字为一个函数建立一个 goroutine。一个函数能够被建立多个 goroutine,一个 goroutine 一定对应一个函数命令行

// 为普通函数建立goroutine 的格式
go 函数名( 参数列表 )
复制代码

若是须要在 goroutine 中返回数, 用通道(channel)把数据从 goroutine 中做为返回值传出线程

package main

import (
    "fmt"
    "time"
)

func running() {
    var times int
    for {
        times++
        fmt.Println("tick", times)
        time.Sleep(time.Second)
    }
}

func main() {
    // 并发执行程序
    go running()
    // 接受命令行输入, 不作任何事情
    var input string
    fmt.Scanln(&input)
}

复制代码

通常状况下,可使用 runtime.NumCPU() 查询 CPU 数量,并使用 runtime.GOMAXPROCS() 函数进行设置指针

runtime.GOMAXPROCS(runtime.NumCPU())
复制代码

并发和并行的概念code

并发:任务在不一样的时间点在处理器进行处理。在同一时间点,任务并不会同时运行 并行:每个任务分配给每个处理器独立完成。在同一时间点,任务必定是同时运行接口

Go语言通道

单纯地将函数并发执行是没有意义的。函数与函数间须要交换数据才能体现并发执行函数的意义

任什么时候候,同时只能有一个 goroutine 访问通道(channel Go语言中一种特殊类型)进行发送和获取数据。(相似队列,先进先出

// 申明通道类型
var 通道变量 chan 通道类型(通道内的数据类型)
复制代码

chan 类型的空值是 nil,声明后须要配合 make 后才能使用

通道是引用类型,须要使用 make 进行建立

通道实例 := make(chan 数据类型)

ch1 := make(chan int)                 // 建立一个整型类型的通道
ch2 := make(chan interface{})         // 建立一个空接口类型的通道, 能够存听任意格式
type Equip struct{ /* 一些字段 */ }
ch2 := make(chan *Equip)             // 建立Equip指针类型的通道, 能够存放*Equip
复制代码

通道建立后,就可使用通道进行发送和接收操做

通道的发送使用特殊的操做符<-

// 数据经过通道发送数据格式
通道变量 <- 值(值的类型必须与ch通道的元素类型一致)

// 建立一个空接口通道
ch := make(chan interface{})
// 将0放入通道中
ch <- 0
// 将hello字符串放入通道中
ch <- "hello"

复制代码

发送将持续阻塞直到数据被接收

把数据往通道中发送时,若是接收方一直都没有接收,那么发送操做将持续阻塞。Go 程序运行时能智能地发现一些永远没法发送成功的语句并作出提示,代码以下:

package main
func main() {
    // 建立一个整型通道
    ch := make(chan int)
    // 尝试将0经过通道发送
    ch <- 0
}
复制代码

通道接收一样使用<-操做符

通道的收发操做在不一样的两个 goroutine 间进行

接收将持续阻塞直到发送方发送数据

通道一次只能接收一个数据元素

阻塞模式接收数据时,将接收变量做为<-操做符的左值,执行该语句时将会阻塞,直到接收到数据并赋值给 data 变量

// 阻塞式接收值
data := <-ch

// 非阻塞式
data, ok := <-ch
data 表示接收到的数据
ok   表示是否接收到数据

非阻塞的通道接收方法可能形成高的 CPU 占用,所以使用很是少

// 忽略从通道返回的数据
<-ch
复制代码

Go 的通道能够在声明时约束其操做方向,如只发送或是只接收。这种被约束方向的通道被称作单向通道

只能发送的通道类型为chan<-,只能接收的通道类型为<-chan

var 通道实例(声明的通道变量) chan<- 元素类型    // 只能发送
var 通道实例(声明的通道变量) <-chan 元素类型    // 只能接收
复制代码

使用 close() 来关闭一个通道.给被关闭通道发送数据将会触发panic

close(ch)
复制代码

互斥锁是一种经常使用的控制共享资源访问的方法,它可以保证同时只有一个 goroutine 能够访问共享资源

Lock()

UnLock()

相关文章
相关标签/搜索