Golang-C1-6

作业点评

switch.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

func main() {
	var x interface{}
	switch x.(type) {
	case nil: // ...
	case int: // ...
	case bool: // ...
	case string: // ...
	default: // ...
	}
}

error.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
package main

import (
	"errors"
	"fmt"
)

func main() {
	var e error
	e = errors.New("an error")
	fmt.Println(e.Error())
	var cmd string
	e = fmt.Errorf("bad command:%s", cmd)
	fmt.Println(e)
}

shell.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main

import (
	"os"
	"os/exec"
	"strings"
)

func main() {
	line := "cat shell.go|grep main"
	cmds := strings.Split(line, "|")
	s1 := strings.Fields(cmds[0])
	s2 := strings.Fields(cmds[1])
	cmd1 := exec.Command(s1[0], s1[1:]...)
	cmd1.Stdin = os.Stdin
	out, _ := cmd1.StdoutPipe()
	cmd2 := exec.Command(s2[0], s2[1:]...)
	cmd2.Stdin = out
	cmd2.Stdout = os.Stdout
	cmd1.Start()
	cmd2.Start()
	cmd1.Wait()
	cmd2.Wait()
}

shell1.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
	"io"
	"os"
	"os/exec"
	"strings"
)

func main() {
	line := "cat shell.go|grep main"
	cmds := strings.Split(line, "|")
	s1 := strings.Fields(cmds[0])
	s2 := strings.Fields(cmds[1])
	r, w := io.Pipe()
	cmd1 := exec.Command(s1[0], s1[1:]...)
	cmd1.Stdin = os.Stdin
	cmd1.Stdout = w
	cmd2 := exec.Command(s2[0], s2[1:]...)
	cmd2.Stdin = r
	cmd2.Stdout = os.Stdout
	cmd1.Start()
	cmd2.Start()
	cmd1.Wait()
	w.Close()
	cmd2.Wait()
}

定义方法

总览

  • 对象和方法
  • 接口使用
  • go里面的unix哲学

对象和方法

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
	"fmt"
	"math"
)

type Point struct {
	x, y float64
}

func Distane(p, q Point) float64 {
	return math.Hypot(q.X-p.X, q.Y-p.Y)
}

func main() {
	p := Point{1,2}
	q := Point{4,6}
	fmt.Println(Distane(p, q)) // "5", function call
}

声明方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
	"fmt"
	"math"
)

type Point struct {
	x, y float64
}

func (p * Point) Distane(q Point) float64 {
	return math.Hypot(q.X-p.X, q.Y-p.Y)
}

func main() {
	p := Point{1,2}
	q := Point{4,6}
	fmt.Println(p.Distane(q)) // "5", function call
}

map_struct.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package main

type Student struct {
	Id   int
	Name string
}

func main() {
	m := make(map[string]*Student)
	m["binggan"] = &Student{
		Id:   1,
		Name: "binggan",
	}
	m["binggan"].Id = 2

	m1 := make(map[string]*int)
	n := 1
	m1["a"] = &n
}

method.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
	"fmt"
	"math"
)

type Point struct {
	X, Y float64
}

func Distance(p, q Point) float64 {
	return math.Hypot(q.X-p.X, q.Y-p.Y)
}

func main() {
	p := Point{1, 2}
	q := Point{4, 6}
	fmt.Println(Distance(p, q)) // "5", function call
}

method1.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
	"fmt"
	"math"
)

type Point struct {
	X, Y float64
}

func (p Point) Distance(q Point) float64 {
	return math.Hypot(q.X-p.X, q.Y-p.Y)
}

func main() {
	p := Point{1, 2}
	q := Point{4, 6}
	fmt.Println(p.Distance(q)) // "5", function call
}

export.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

import "fmt"

定义 学生 struct {
	名字 string
	编号 int
}

定义 教室 struct {
	学生们 []学生
}

定义 路径 []

func main() {
	var 学生1 学生
	学生1.名字 = "binggan"
	fmt.Println(学生1)
}

练习

设定一个路径上的所有点用[]point表示,求出路径的长度

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
	"fmt"
	"math"
)

type Point struct {
	X, Y float64
}

func (p *Point) Distance(q *Point) float64 {
	return math.Hypot(q.X-p.X, q.Y-p.Y)
}

func Distance(path []Point) float64 {

}

func main() {
	path := []Point{{1, 2}, {3, 4}, {5, 6}}
	fmt.Println(Distance(path))
}

type是用来定义类型的

type.go

1
2
3
4
5
6
package main

type Path []Point

func (path Path) Distance() float64 {
}
  • 不同的对象可以有相同的方法名
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main

import (
	"fmt"
	"math"
)

type Point struct {
	X, Y float64
}

func (p *Point) Distance(q *Point) float64 {
	return math.Hypot(q.X-p.X, q.Y-p.Y)
}

func (p Point) GetX() float64 {
	return p.X
}

type Path []Point

func (path Path) Distance() float64 {
	return 0
}

func (path Path) LenPoints() int {
	return len(path)
}

func main() {
	path := Path{{1, 2}, {3, 4}, {5, 6}}
	fmt.Println(path.Distance())
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package main

import (
	"fmt"
	"math"
)

type Point struct {
	X, Y float64
}

func (p *Point) Distance(q *Point) float64 {
	return math.Hypot(q.X-p.X, q.Y-p.Y)
}

func (p Point) GetX() float64 {
	return p.X
}

type Path []Point

/*
func (path Path) Distance() float64 {
	return 0
}

func (path Path) LenPoints() int {
	return len(path)
}
*/

func main() {
	var p Path
	p = make([]Point, 3)
	p[0] = Point{X: 1, Y: 2}
	p[1] = Point{X: 3, Y: 4}
	p[2] = Point{X: 5, Y: 6}
	fmt.Println(p)
	
	// 北京-上海
	m["beijing-shanghai"] = p
	var m map[string]Path
}

练习

定义Path类型,补全Path的Distance方法

time包的使用

time.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
	"fmt"
	"time"
)

func main() {
	var n time.Duration
	n = time.Hour
	n = 3*time.Hour + 30*time.Minute
	fmt.Println(int64(n))
	fmt.Println(n.String())
	fmt.Println(n.Seconds())
	fmt.Println(n.Minutes())

	t := time.Now()
	t1 := t.Add(time.Hour)
	fmt.Println(t1.Sub(t))
}

指针接收者

  • 我们希望改变对象的成员
  • 造价于函数的第一个参数是指针

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

func (p * Point) ScaleBy(factor float64) {
	p.X *= factor
	p.Y *= factor
}

func main() {
	// 直接指针
	p := &Point{1, 2}
	p.ScaleBy(2)
	
	//声明结构体后再用指针指向
	p1 := Point{1, 2}
	p2 := &p1
	p2.ScaleBy(2)
	
	// 使用结构体调用,隐式取地址
	p3 := Point{1, 2}
	p3.ScaleBy(2) // 等价于 (&p3).ScaleBy(2)
}

pointer_method.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

func (p Point) ScaleBy(factor float64) {
	p.X *= factor
	p.Y *= factor
}

func (p *Point) ScaleBy(factor float64) {
	p.X *= factor
	p.Y *= factor
}

func ScaleBy(p Point, factor float64) {
	p.X *= factor
	p.Y *= factor
}

func ScaleBy(p *Point, factor float64) {
	p.X *= factor
	p.Y *= factor
}

func main() {
	// 直接指针
	p := &Point{1, 2}
	p.ScaleBy(2)

	// 声明结构体后再用指针指向
	p1 := Point{1, 2}
	p2 := &p1
	p2.ScaleBy(2)

	// 使用结构体调用,隐式取地址
	p3 := Point{1, 2}
	p3.ScaleBy(2) // 等价于 (&p3).ScaleBy(2)
}

封装

student.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main

type ClassRoom struct {
	students []Student
}

func (c *ClassRoom) add(name string, id int) {
	c.students
}

func (c *ClassRoom) list() {
	c.students
}

var classrooms map[string]*ClassRoom

func main() {
	c := ClassRoom{}
	c.add()

	// select reboot
	// add binggan 1
	// select qinghua
	// add binggan 1
}

可见性

  • 通过首字母大小写来控制可见性
  • 可见性是package级别的
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package golib

var (
	PublicVar string
	privateVar string
)

func privateFunc() {
	fmt.Println("private Func")
}

func PublicFunc() {
	fmt.Println("Public Func")
}

//Add return a + b
func Add(a, b int) int {
	return a + b
}

作业1

  • 用对象的方式封装一个ClassRoom对象
  • 增加一条select指令来选择当前的ClassRoom

接口

为什么需要接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
)

func handle(w http.ResponseWriter, r *httpRequest) {
	fmt.Fprintf(w, "hello\n")
}

func main() {
	f, err := os.Create("a.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()
	fmt.Fprintf(f, "hello\n")
}

声明接口

1
2
3
type Write interface {
	Write(p []byte) (n int, err error)
}

eface.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package main

type Writer interface {
	Write(b []byte) (int, error)
}

//type I interface {
//}

func main() {
	var i interface{}
	var n int
	i = n
	var s string
	i = s
	var p Point
	i = s
}

iface.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
)

// 名字: IInstance
// 方法: Instance() float64

type IInstance interface {
	Instance() float64
}

func handle(w http.ResponseWriter, r *httpRequest) {
	fmt.Fprintf(w, "hello\n")
}

func main() {
	f, err := os.Create("a.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()
	fmt.Fprintf(f, "hello\n")
}

实现接口

  • 实现了接口里面的所有方法就算实现了接口
  • os.File
  • 接口也是实现者

io.Writer接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
package main

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

type ByteCounter int

func (b *ByteCounter) Write(p []byte) (int, error) {
	*b += ByteCounter(len(p))
	return len(p), nil
}

func main() {
	b := new(ByteCounter)
	io.Copy(b, os.Stdin)
	fmt.Println(*b)
}

练习:实现一个统计行数的writer

char_count.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package main

import (
	"bytes"
	"fmt"
	"io"
)

type ByteCounter struct {
	Sum int
}

func (b *ByteCounter) Write(p []byte) (int, error) {
	b.Sum += len(p)
	return len(p), nil
}

type LineCounter struct {
	Sum int
}

func (l *LineCounter) Write(p []byte) (int, error) {
	for _, b := range p {
		if b == '\n' {
			l.Sum++
		}
	}
	return len(p), nil
}

func main() {
	l := new(LineCounter)
	b := new(ByteCounter)

	buf := new(bytes.Buffer)
	buf.WriteString(`
hello gopher
12334
main new
`)

	w := io.MultiWriter(l, b)
	io.Copy(w, buf)
	fmt.Println(l.Sum)
	fmt.Println(b.Sum)
}

接口变量

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
)

func main() {
	var w io.Writer
	w = os.Stdout
	w = new(bytes.Buffer)
	w = nil
	if w == nil {
		fmt.Println("nil")
	}
}

iface.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main

import (
	"fmt"
	"net/http"
)

// 名字: IInstance
// 方法: Instance() float64

type IInstance interface {
	Instance() float64
}

type Path []Point

func (p Path) Instance() float64 {

}

func handle(w http.ResponseWriter, r *httpRequest) {
	fmt.Fprintf(w, "hello\n")
}

func main() {
	var i IInstance
	p := Path{{1, 2}, {3, 4}}
	i = p
	fmt.Println(i)
}

path.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package main

import (
	"fmt"
	"math"
)

type Point struct {
	X, Y float64
}

func (p *Point) Distance2Point(q *Point) float64 {
	return math.Hypot(q.X-p.X, q.Y-p.Y)
}

func (p *Point) Distance() float64 {
	return math.Hypot(p.X, p.Y)
}

type Path []*Point

func (p Path) Distance() float64 {
	var sum float64
	for i := 0; i < len(p)-1; i++ {
		sum += p[i].Distance2Point(p[i+1])
	}
	return sum
}

type IDistance interface {
	Distance() float64
}

func print(p IDistance) {
	fmt.Println(p.Distance())
}

func main() {
	var path Path
	path = make([]*Point, 3)
	p1 := &Point{X: 1, Y: 2}
	p2 := &Point{X: 3, Y: 4}
	p3 := &Point{X: 5, Y: 6}
	path[0] = p1
	path[1] = p2
	path[2] = p3

	var i IDistance
	i = p1
	fmt.Println(i.Distance())
	i = p2
	fmt.Println(i.Distance())
	i = path
	fmt.Println(i.Distance())
	print(path)
	print(p1)
}

writer接口

iassert.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
	"bytes"
	"io"
	"os"
)

func main() {
	var w io.Writer
	w = os.Stdout
	f, ok := w.(*os.File)
	if !ok {
		c, ok := w.(*bytes.Buffer)
		if !ok {

		}
	}
	_ = f
	_ = c
}

iowriter.go

1
2
3
type Writer interface {
	Write(p []byte) (n int, err error)
}

ivar.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
)

func main() {
	var w io.Writer
	w = os.Stdout
	w = new(bytes.Buffer)
	w = nil
	if w == nil {
		fmt.Println("nil")
	}
}

crypto.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package main

import (
	"bytes"
	"io"
	"os"
)

type XorWriter struct {
	w io.Writer
	x byte
}

func (x *XorWriter) Write(p []byte) (int, error) {
	p1 := make([]byte, len(p))
	copy(p1, p)
	for i, b := range p1 {
		p1[i] = b ^ x.x
	}
	return x.w.Write(p1)
}

func NewXorWriter(w io.Writer, x byte) *XorWriter {
	return &XorWriter{
		w: w,
		x: x,
	}
}

type XorReader struct {
	r io.Reader
	x byte
}

func (x *XorReader) Read(p []byte) (int, error) {
	return x.r.Read(p)
}

func NewXorReader(r io.Reader, x byte) *XorReader {
	return &XorReader{
		r: r,
		x: x,
	}
}

func main() {
	buf := new(bytes.Buffer)
	x := NewXorWriter(buf, 'a')
	io.WriteString(x, "hello")
	//fmt.Println(buf.Bytes())

	x1 := NewXorReader(buf, 'a')
	io.Copy(os.Stdout, x1)
}

接口2

常见接口

sort.Interface

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package main

import (
	"fmt"
	"os"
	"sort"
	"text/tabwriter"
	"time"
)

type Track struct {
	Title string
	Artist string
	Album string
	Year int
	Length time.Duration
}

var tracks = []*Track{
	{"Go", "Delilah", "From the Roots up", "2012", length("3m38s")},
	{"Go2", "Delilah2", "From the Roots up2", "2013", length("3m39s")},
	{"Go3", "Delilah3", "From the Roots up3", "2014", length("3m40s")},
	{"Go4", "Delilah4", "From the Roots up4", "2015", length("3m41s")},
}

func length(s string) time.Duration {
	d, err := time.ParseDuration(s)
	if err != nil {
		panic(s)
	}
	return d
}

func printTracks(tracks []*Track) {
	const format = "%v\t%v\t%v\t%v\t%v\t\n"
	tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0)
	fmt.Fprintf(tw, format, "Title", "Artist", "Album", "Year", "Length")
	fmt.Fprintf(tw, format, "-----", "-----", "-----", "-----", "-----")
	for _, t := range tracks {
		fmt.Fprintf(tw, format, t.Title, t.Artist, t.Album, t.Year, t.Length)
	}
	tw.Flush() // calculate column widths adn print table
}

type byArtist []*Track

func (x byArtist) len() int { return len(x) }
func (x byArtist) less(i, j int) bool { return x[i].Artist < x[j].Artist }
func (x byArtist) swap(i, j int) { x[i], x[j] = x[j], x[i] }

func main() {
	sort.Sort(byArtist(tracks))
	printTracks(tracks)
}

sort.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package main

import (
	"fmt"
	"os"
	"sort"
	"text/tabwriter"
	"time"
)

type Track struct {
	Title  string
	Artist string
	Album  string
	Year   int
	Length time.Duration
}

var tracks = []*Track{
	{"Go", "Delilah", "From the Roots Up", 2012, length("3m38s")},
	{"Go", "Moby", "Moby", 1992, length("3m37s")},
	{"Go Ahead", "Alicia Keys", "As I Am", 2007, length("4m36s")},
	{"Ready 2 Go", "Martin Solveig", "Smash", 2011, length("4m24s")},
}

func length(s string) time.Duration {
	d, err := time.ParseDuration(s)
	if err != nil {
		panic(s)
	}
	return d
}

func printTracks(tracks []*Track) {
	const format = "%v\t%v\t%v\t%v\t%v\t\n"
	tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0)
	fmt.Fprintf(tw, format, "Title", "Artist", "Album", "Year", "Length")
	fmt.Fprintf(tw, format, "-----", "------", "-----", "----", "------")
	for _, t := range tracks {
		fmt.Fprintf(tw, format, t.Title, t.Artist, t.Album, t.Year, t.Length)
	}
	tw.Flush() // calculate column widths and print table
}

type byArtist []*Track

func (x byArtist) Len() int           { return len(x) }
func (x byArtist) Less(i, j int) bool { return x[i].Year < x[j].Year }
func (x byArtist) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }

func main() {
	sort.Sort(byArtist(tracks))
	printTracks(tracks)
}

练习

编写一个按照长度排序的实现byLength

http.Handler

godoc.org/net/http

http.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main

import (
	"fmt"
	"log"
	"net/http"
	"time"
)

type Monitor struct {
	counter int
}

func (m *Monitor) Run() {
	for {
		time.Sleep(time.Second)
		m.counter++
	}
}

func (m *Monitor) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "count:%d\n", m.counter)
}

func handle(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "hello world\n")
}

func main() {
	var m Monitor
	http.HandleFunc("/", handle)
	http.Handle("/monitor", &m)
	go m.Run()
	log.Fatal(http.ListenAndServe(":19090", nil))
}

error接口

godoc.org/errors

io.Writer和io.Reader

unix的文件抽象

io包里面的接口处理

godoc.org/io

tee命令

  • io.TeeWriter

接口断言

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package main

import (
	"bytes"
	"io"
	"os"
)

func main() {
	var w io.Writer
	w = os.Stdout
	f := w.(*os.File)
	c := w.(*bytes.Buffer)
}

switch接口判断

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
package main

func main() {
	var x interface{}
	switch x.(type) {
	case nil: // ...
	case int: // ...
	case bool: // ...
	case string: // ...
	default: // ...
	}
}

空接口

  • 空接口可以接受任何类型

tar包

遍历文件树

  • filepath.Walk

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package main

import (
	"fmt"
	"os"
	"path/filepath"
)

func main() {
	filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
		fmt.Println(path)
		return nil
	})
}

walk.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package main

import (
	"fmt"
	"os"
	"path/filepath"
)

func main() {
	filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			fmt.Println(path)
		}
		return nil
	})
}

练习:du命令

du.go

1
2
3
4
5
package main

func main() {

}

tar命令

uncompress.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package main

import (
	"compress/gzip"
	"io"
	"log"
	"os"
)

func main() {
	r, err := gzip.NewReader(os.Stdin)
	if err != nil {
		log.Fatal(err)
	}
	io.Copy(os.Stdout, r)
}

示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package main

import (
	"archive/tar"
	"io"
	"os"
	"path/filepath"
)

func untar(base string, r io.Reader) error {
	tr := tar.NewReader(r)
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			return nil
		}
	}
	if err != nil {
		return err
	}
	fullpath := filepath.Join(base, hdr.Name)
	info := hdr.FileInfo()
	// as dir
	if info.IsDir() {
		os.MkdirAll(fullpath, 0755)
		continue
	}
	dir := filepath.Dir(fullpath)
	os.MkdirAll(dir, 0755)
	//as file
	f, err := os.Create(filepath)
	if err != nil {
		return err
	}
	_, err = io.Copy(f, tr)
	if err != nil {
		f.Close()
		return err
	}
	f.Chmod(info.Mode())
	f.Close()
}

func main() {
	untar(".", os.Stdin)
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
	"archive/tar"
	"fmt"
	"io"
	"io/ioutil"
	"os"
)

func main() {
	tr := tar.NewReader(os.Stdin)
	for {
		hdr, err := tr.Next()
		if err := nil {
			return
		}
		fmt.Println(hdr.Name)
		io.Copy(ioutil.Discard, tr)
	}
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package main

import (
	"archive/tar"
	"compress/gzip"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"os"
)

func main() {
	uncompress, err := gzip.NewReader(os.Stdin)
	if err := nil {
		log.Fatal(err)
	}
	tr := tar.NewReader(uncompress)
	for {
		hdr, err := tr.Next()
		if err := nil {
			return
		}
		fmt.Println(hdr.Name)
		io.Copy(ioutil.Discard, tr)
	}
}

tar.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package main

import (
	"archive/tar"
	"io"
	"os"
	"path/filepath"
)

func untar(base string, r io.Reader) error {
	tr := tar.NewReader(r)
	for {
		hdr, err := tr.Next()
		if err == io.EOF {
			return nil
		}
		if err != nil {
			return err
		}
		fullpath := filepath.Join(base, hdr.Name)
		info := hdr.FileInfo()
		// as dir
		if info.IsDir() {
			os.MkdirAll(fullpath, 0755)
			continue
		}
		dir := filepath.Dir(fullpath)
		os.MkdirAll(dir, 0755)

		// as file
		f, err := os.Create(fullpath)
		if err != nil {
			return err
		}
		_, err = io.Copy(f, tr)
		if err != nil {
			f.Close()
			return err
		}
		f.Chmod(info.Mode())
		f.Close()
	}
}

func main() {
	untar(".", os.Stdin)
}

tar1.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import (
	"archive/tar"
	"compress/gzip"
	"fmt"
	"io"
	"io/ioutil"
	"log"
)

func main() {
	uncrypto, err := rsa.NewReader(conn)
	uncompress, err := gzip.NewReader(uncrypto)
	if err != nil {
		log.Fatal(err)
	}
	tr := tar.NewReader(uncompress)
	for {
		hdr, err := tr.Next()
		if err != nil {
			return
		}
		fmt.Println(hdr.Name)
		io.Copy(ioutil.Discard, tr)
	}

}

总结

装饰器对象

  • tar的解压缩和解打包

reader.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import (
	"compress/gzip"
	"fmt"
	"io"
	"log"
	"os"
)

type MyReader struct {
	r   io.Reader
	cnt int
}

func NewMyReader(r io.Reader) *MyReader {
	return &MyReader{
		r: r,
	}
}

func (r *MyReader) Read(b []byte) (int, error) {
	n, err := r.r.Read(b)
	r.cnt += n
	return n, err
}

func main() {
	uncompress, err := gzip.NewReader(os.Stdin)
	if err != nil {
		log.Fatal(err)
	}
	//r := NewMyReader(uncompress)
	io.Copy(os.Stdout, uncompress)
	fmt.Println("size", r.cnt)
}

homework

以对象的方式组织学生管理系统

要求:

  • 新增ClassRoom对象,一个ClassRoom包含多个学生
  • 多个ClassRoom之间可以有同样名字的学生
  • 新增select指令,用来选择ClassRoom
  • 不用实现ClassRoom的增删改查功能
  • 为了简化ClassRoom的管理,如果select的ClassRoom不存在则自动创建

完成tar命令的创建功能

要求:

  • 实现基本的创建tar包
  • 在实现tar包的基础上实现压缩功能,创建tar.gz文件