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.