并发
很多goroutine映射到一个线程。多对1的关系。
chan是go里的一等公民。我们可以往chan里放不同类型的数据。也可以从一个声明的chan里取数据。
demo 从8:00开始
- pipeline:一個library
- pipeline:一個library
Go语言编程范式:面向接口、函数式编程、并发编程。
各个编程语言的使用场景.
外部排序pipeline
节点的组装,
传统语言与Go语言 对比
go run [file] go build [file] [bin]
进一步学习
go tool tour
http://docscn.studygolang.com/doc/
期待我的 go 语言实战课
go 语言三大特色
面向接口- Reader/ Writer 接口的使用
函数式编程
并发编程
课程回顾
原始数据
网络的扩展
网络的扩展
单机版外部排序 pipeline
Reader Source 节点-支持分块
Mergen-搭建归并节点组
pipeline 的搭建及运行——CPU 及线程数量的观测
func ReadSource(reader io.Reader) <-chan int {
out := make(chan int)
go func() {
buffer := make([]byte, 8)
for {
n, err := reader.Read(buffer)
if n > 0 {
v := int(binary.BigEndian.Uint64(buffer))
out <- v
}
if err != nil {
break
}
}
close(out)
}()
return out
}
func WriteSink(writer io.Writer, in <-chan int) {
for v := range in {
buffer := make([]byte, 8)
binary.BigEndian.PutUint64(buffer, uint64(v))
writer.Write(buffer)
}
}
func RandomSource(count int) <-chan int{
out := make(chan int)
go func() {
for i := 0; i < count; i++ {
out <- rand.Int()
}
close(out)
}()
return out
}func main() {
const filename = "large.in"
const n = 100000000
file, err := os.Create(filename)
if err != nil {
panic(err)
}
defer file.Close()
p := pipeline.RandomSource(n)
writer := bufio.NewWriter(file)
pipeline.WriteSink(writer, p)
writer.Flush()
file, err = os.Open(filename)
if err != nil {
panic(err)
}
defer file.Close()
p = pipeline.ReadSource(bufio.NewReader(file))
count := 0
for v := range p {
fmt.Println(v)
count++
if count >= 100 {
break
}
}
}
package pipeline
import (
"encoding/binary"
"io"
"sort"
)
func ArraySource(a ...int) <-chan int {
out := make(chan int)
go func() {
for _, v := range a{
out <- v
}
close(out)
}()
return out
}
func InMemSort(in <-chan int) <-chan int {
out := make(chan int)
go func() {
// Read into memory
var a []int
for v := range in {
a = append(a, v)
}
// Sort
sort.Ints(a)
// Output
for _, v := range a {
out <- v
}
close(out)
}()
return out
}
func Merge(in1, in2 <-chan int) <-chan int {
out := make(chan int)
go func() {
v1, ok1 := <-in1
v2, ok2 := <-in2
for ok1 || ok2 {
if !ok2 || (ok1 && v1 <= v2) {
out <- v1
v1, ok1 = <-in1
} else {
out <- v2
v2, ok2 = <-in2
}
}
close(out)
}()
return out
}package main
import (
"ccmouse/gointro/pipeline"
"fmt"
)
func main() {
p := pipeline.Merge(
pipeline.InMemSort(
pipeline.ArraySource(3, 2, 6, 7, 4)),
pipeline.InMemSort(
pipeline.ArraySource(7, 4, 0, 3, 2, 13, 8)))
for v := range p {
fmt.Println(v)
}
}
一些节点
数组数据源节点- channel 的关闭及检测
内部排序节点
归并节点
外部排序 Pipeline
节点的组装
节点多输入和多输出
Pipeline
外部排序归并节点
外部排序切分
将数据分为左右两半,分别归并排序,再把两个有序数据归并
如何归并:
[1, 3, 6, 7], [1, 2, 3, 5] → 1
[3, 6, 7],[1, 2, 3, 5] → 1
[3, 6, 7], [2, 3, 5] → 2
[3,6,7],[3, 5] → 3
……
package main
import (
"fmt"
"sort"
)
func main() {
// create a slice of int
a := []int{3, 6, 2, 1, 9, 10,8}
sort.Ints(a)
for _, v := range a {
fmt.Println(v)
}
}
package main
import (
"fmt"
)
func main() {
ch := make(chan string)
for i:=0; i < 5000; i++ {
// go starts a goroutine
go printHelloWorld(i, ch)
}
for {
msg := <- ch
fmt.Println(msg)
}
}
func printHelloWorld(i int, ch chan string) {
for {
ch <- fmt.Sprintf("Hello world from go routine %d!\n", i)
}
}
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
fmt.Fprintf(writer, "<h1>Hello World %s!<h1>", request.FormValue("name"))
})
http.ListenAndServe(":8888", nil)
}
Hello World
普通 Hello World
Hello World Server - 读取 url 中的参数
并发 Hello World - 初识 goroutine 与 channel
一个简单的排序