Gopl 第六七章 方法与接口

说明

本文为GOPL第六七章学习笔记

方法

方法声明

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
type Point struct{ X, Y float64 }

type ColoredPoint struct {
Point
Color color.RGBA
}

func (p Point) Distance(q Point) float64 {
dX := q.X - p.X
dY := q.Y - p.Y
return math.Sqrt(dX*dX + dY*dY)
}

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

func main() {
red := color.RGBA{255, 0, 0, 255}
blue := color.RGBA{0, 0, 255, 255}
var p = ColoredPoint{Point{1, 1}, red}
var q = ColoredPoint{Point{5, 4}, blue}
fmt.Println(p.Distance(q.Point)) // "5"

//p隐式转换为&p
p.ScaleBy(2)
q.ScaleBy(2)
fmt.Println(p.Distance(q.Point)) // "10"

//方法转函数
dis := Point.Distance
fmt.Println(dis(p.Point,q.Point)) //10
}

接口

温度转化

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
type Celsius float64
type Fahrenheit float64
type celsiusFlag struct {
Celsius
}
type Value interface {
String() string
Set(string) error
}
func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9.0/5.0 + 32.0) }
func FToC(f Fahrenheit) Celsius { return Celsius((f - 32.0) * 5.0 / 9.0) }
func (f *celsiusFlag) Set(s string) error{
var value float64
var unit string
fmt.Sscanf(s,"%f%s",&value,&unit)
switch unit {
case "C","c":
f.Celsius = Celsius(value)
return nil
case "F","f":
f.Celsius = FToC(Fahrenheit(value))
return nil
}
return fmt.Errorf("invalid temperature %q",s)
}
func (c Celsius) String() string {
return fmt.Sprintf("%.2fC",c)
}

func main(){
var c celsiusFlag
c.Set("34.55C")
fmt.Println(c.Celsius)
c.Set("100.43F")
fmt.Println(c.Celsius)
}

http.Handler 接口

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

package main

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

func main() {
db := database{"shoes": 50, "socks": 5}
http.HandleFunc("/list", db.list)
http.HandleFunc("/price", db.price)
log.Fatal(http.ListenAndServe("localhost:8000", nil))
}

type dollars float32

func (d dollars) String() string { return fmt.Sprintf("$%.2f", d) }

type database map[string]dollars

func (db database) list(w http.ResponseWriter, req *http.Request) {
for item, price := range db {
fmt.Fprintf(w, "%s: %s\n", item, price)
}
}

func (db database) price(w http.ResponseWriter, req *http.Request) {
item := req.URL.Query().Get("item")
//localhost:8000/price?item=shoes -> $50.00
if price, ok := db[item]; ok {
fmt.Fprintf(w, "%s\n", price)
} else {
w.WriteHeader(http.StatusNotFound) // 404
fmt.Fprintf(w, "no such item: %q\n", item)
}
}