go学习总结(九)

1.实现Reader类型

package main

import "golang.org/x/tour/reader"

type MyReader struct{}


// TODO: 给 MyReader 添加一个 Read([]byte) (int, error) 方法
func (r MyReader) Read(b []byte) (int, error){
	b[0] = 'A'
	return 1,nil
}

func main() {
	reader.Validate(MyReader{})
}

2.rot13Reader

package main

import (
    "io"
    "os"
    "strings"
	"fmt"
)

type rot13Reader struct {  
    r io.Reader
}

func rot13(out byte) byte{  //字母转换
    switch{
        case out >= 'A' && out <= 'M' || out >= 'a' && out <= 'm':
            out += 13
        case out >= 'N' && out <= 'Z' || out >= 'n' && out <= 'z':
            out -= 13
    }        
    return out
}    
    
func (fz rot13Reader) Read(b []byte) (int,error){  //重写Read方法
    n, e := fz.r.Read(b)
           for i := 0; i < n; i++ {
        b[i] = rot13(b[i])    
        }            
    return n,e
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	fmt.Println(s)
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

3.Image

package main

import "golang.org/x/tour/pic"

type Image struct{}//新建一个Image结构体

func (i Image) ColorModel() color.Model{	//实现Image包中颜色模式的方法
	return color.RGBAModel
}
func (i Image) Bounds() image.Rectangle{	//实现Image包中图片边界的方法
	return image.Rect(0,0,200,200)
}
func (i Image) At(x,y int) color.Color{	//实现Image包中生成图像某个点的方法
	return color.RGBA{uint8(x),uint8(255),uint8(255)}	
}

func main() {
	m := Image{}
	pic.ShowImage(m)
}

4.goroutine


package main

import (
	"fmt"
	"time"
)

func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

func main() {
	go say("world")//启动一个新的go程并执行
	go say("hello")//启动一个新的go程并执行
    say("amy")
}

5.信道

信道是带有类型的管道,你可以通过它用信道操作符 <- 来发送或者接收值。
ch <- v    // 将 v 发送至信道 ch。
v := <-ch  // 从 ch 接收值并赋予 v。
(“箭头”就是数据流的方向。)
和映射与切片一样,信道在使用前必须创建:
ch := make(chan int)
package main

import "fmt"

func sum(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum // 将和送入 c
}

func main() {
	s := []int{7, 2, 8, -9, 4, 0}
	c := make(chan int)

	go sum(s[:len(s)/2], c)
	fmt.Println(1,c)
	p:=&c
	fmt.Println(2,p)
	fmt.Println(3,*p)
	x:= <-c
	fmt.Println(4,x)
	go sum(s[len(s)/2:], c)
	fmt.Println(5,c)
	y:= <-c
	fmt.Println(6,y)
	go sum(s[1:3],c)
	i,j,k :=<-c, <-c, <-c
	fmt.Println(7,i,j,k)
}
执行结果如下:
1 0x430080
2 0x40c138
3 0x430080
4 17
5 0x430080
6 -5
fatal error: all goroutines are asleep - deadlock!
为什么会报deadlock呢?因为在第七步输出时,前面两个c的输入值已经被x,y取走了,所以此时想再将c的值传给i,j已经做不到了。即c的输入值被取过一次此时已经空了,而i,j还在等待输入,故发生死锁。改为如下则OK。
package main

import "fmt"

func sum(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum // 将和送入 c
}

func main() {
	s := []int{7, 2, 8, -9, 4, 0}
	c := make(chan int)

	go sum(s[:len(s)/2], c)
	fmt.Println(1,c)
	p:=&c
	fmt.Println(2,p)
	fmt.Println(3,*p)
	//x:= <-c
	//fmt.Println(4,x)
	go sum(s[len(s)/2:], c)
	fmt.Println(5,c)
	//y:= <-c
	//fmt.Println(6,y)
	go sum(s[1:3],c)
	i,j,k :=<-c, <-c, <-c
	fmt.Println(7,i,j,k)
}



1 0x430080
2 0x40c138
3 0x430080
5 0x430080
7 10 17 -5

6.带缓冲信道

信道可以是 带缓冲的。将缓冲长度作为第二个参数提供给 make 来初始化一个带缓冲的信道:
ch := make(chan int, 100)
仅当信道的缓冲区填满后,向其发送数据时才会阻塞。当缓冲区为空时,接受方会阻塞。 
package main

import "fmt"

func main() {
	ch := make(chan int, 1)
	ch <- 1
	fmt.Println(<-ch)
}


package main

import "fmt"

func main() {
	ch := make(chan int, 1)//当信道长度是1时,发送两个数据则会导致死锁
	ch <- 1
	ch <- 2
	fmt.Println(<-ch)
}


package main

import "fmt"

func main() {
	ch := make(chan int, 3)
	ch <- 1
	ch <- 2
	fmt.Println(<-ch)
	fmt.Println(<-ch)
}

7.

发布了131 篇原创文章 · 获赞 13 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/haiziccc/article/details/104156210