Golang学习笔记_方法

 
Category: GoLang

写在前面

练习, Stringer

Go 语言之旅;

package main

import "fmt"

type IPAddr [4]byte

// TODO: 给 IPAddr 添加一个 "String() string" 方法
func (ip IPAddr) String() string {
	return fmt.Sprintf("%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3])
}

func main() {
	hosts := map[string]IPAddr{
		"loopback":  {127, 0, 0, 1},
		"googleDNS": {8, 8, 8, 8},
	}
	for name, ip := range hosts {
		fmt.Printf("%v: %v\n", name, ip)
	}
}

平方根程序的错误处理:

package main

import (
	"fmt"
	"math"
)

type ErrNegativeSqrt float64

func (e ErrNegativeSqrt) Error() string {
	return fmt.Sprintf("cannot Sqrt negative number: %v", float64(e)) // must cast, otherwise dead loop
}

func Sqrt(x float64) (float64, error) {
	if x < 0 { //error
		return x, ErrNegativeSqrt(x)
	}
	z := 1.0
	for {
		if math.Abs(z*z-x) < 1e-13 {
			return z, nil //right ans
		}
		z -= (z*z - x) / 2 / z
	}
}

func main() {
	fmt.Println(Sqrt(2))
	fmt.Println(Sqrt(-2))
}

reader: Go 语言之旅;

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{})
}

rot-reader

package main

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

type rot13Reader struct {
	r io.Reader
}

func (obj rot13Reader) Read(b []byte) (int, error) {
	ans := 0
	for {
		n, err := obj.r.Read(b)
		for i := ans; i < ans+n; i++ {
			if b[i] < 'n' { // 投机取巧了, 没考虑大写字母
				b[i] += 13
			} else {
				b[i] -= 13
			}
		}
		ans += n
		if err == io.EOF {
			return ans, err
		}
	}
}

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

图像, Go 语言之旅;

type Image.

  type Image interface {
      // ColorModel returns the Image's color model.
      ColorModel() color.Model
      // Bounds returns the domain for which At can return non-zero color.
      // The bounds do not necessarily contain the point (0, 0).
      Bounds() Rectangle
      // At returns the color of the pixel at (x, y).
      // At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
      // At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
      At(x, y int) color.Color
  }
package main

import (
	"image"
	"image/color"

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

type Image struct{}

func (i Image) ColorModel() color.Model {
	return color.RGBAModel
}

func (i Image) Bounds() image.Rectangle {
	return image.Rect(0, 0, 200, 200)
}
func (i Image) At(x, y int) color.Color {
	return color.RGBA{uint8(x), uint8(y), 255, 255}
}

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

等价二叉查找树: Go 语言之旅;

package main

import (
	"fmt"

	"golang.org/x/tour/tree"
)

/*
type Tree struct {
    Left  *Tree
    Value int
    Right *Tree
}*/
var flg int = -127

// Walk 步进 tree t 将所有的值从 tree 发送到 channel ch。
func Walk(t *tree.Tree, ch chan int) {
	if t == nil {
		return
	}
	// inorder
	Walk(t.Left, ch)
	ch <- t.Value
	Walk(t.Right, ch)
}

// Same 检测树 t1 和 t2 是否含有相同的值。
func Same(t1, t2 *tree.Tree) bool {
	c1 := make(chan int)
	c2 := make(chan int)
	go Walk(t1, c1)
	go Walk(t2, c2)
	for i := 0; i < 10; i++ {
		a, b := <-c1, <-c2
		//fmt.Println(a, b)
		if a != b {
			return false
		}
	}
	return true
}

func main() {
	ans1 := Same(tree.New(1), tree.New(1))
	ans2 := Same(tree.New(1), tree.New(2))
	fmt.Println(ans1, ans2)
}

Go 语言之旅;爬虫

package main

import (
	"fmt"
	"sync"
)

type Fetcher interface {
	// Fetch 返回 URL 的 body 内容,并且将在这个页面上找到的 URL 放到一个 slice 中。
	Fetch(url string) (body string, urls []string, err error)
}

type urlRecord struct {
	v   map[string]int
	mux sync.Mutex
	wg  sync.WaitGroup
}

var m = urlRecord{v: make(map[string]int)}

// Crawl 使用 fetcher 从某个 URL 开始递归的爬取页面,直到达到最大深度。
func Crawl(url string, depth int, fetcher Fetcher) {
	// TODO: 并行的抓取 URL。
	// TODO: 不重复抓取页面。
	// 下面并没有实现上面两种情况:

	defer m.wg.Done()

	if depth <= 0 {
		return
	}

	m.mux.Lock()
	m.v[url]++
	m.mux.Unlock()

	body, urls, err := fetcher.Fetch(url)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Printf("found: %s %q\n", url, body)
	for _, u := range urls {
		m.mux.Lock()
		if _, ok := m.v[u]; !ok {
			m.wg.Add(1)
			go Crawl(u, depth-1, fetcher)
		}
		m.mux.Unlock()
	}

	return
}

func main() {
	m.wg.Add(1)
	Crawl("https://golang.org/", 4, fetcher)
	m.wg.Wait()
}

// fakeFetcher 是返回若干结果的 Fetcher。
type fakeFetcher map[string]*fakeResult

type fakeResult struct {
	body string
	urls []string
}

func (f fakeFetcher) Fetch(url string) (string, []string, error) {
	if res, ok := f[url]; ok {
		return res.body, res.urls, nil
	}
	return "", nil, fmt.Errorf("not found: %s", url)
}

// fetcher 是填充后的 fakeFetcher。
var fetcher = fakeFetcher{
	"https://golang.org/": &fakeResult{
		"The Go Programming Language",
		[]string{
			"https://golang.org/pkg/",
			"https://golang.org/cmd/",
		},
	},
	"https://golang.org/pkg/": &fakeResult{
		"Packages",
		[]string{
			"https://golang.org/",
			"https://golang.org/cmd/",
			"https://golang.org/pkg/fmt/",
			"https://golang.org/pkg/os/",
		},
	},
	"https://golang.org/pkg/fmt/": &fakeResult{
		"Package fmt",
		[]string{
			"https://golang.org/",
			"https://golang.org/pkg/",
		},
	},
	"https://golang.org/pkg/os/": &fakeResult{
		"Package os",
		[]string{
			"https://golang.org/",
			"https://golang.org/pkg/",
		},
	},
}