Learning Go - 4 Methods and Interfaces 1. 方法 func (v *Vertex) Abs() float64 { // 可以在结构体类型上定义方法,func和方法名中间 return math.Sqrt(v.X*v.X + v.Y*v.Y) } v.Abs() // 这么调用 type MyFloat float64 // 任意类型都可以定义方法,但是要type一下 func (f MyFloat) Abs() float64 {...} // 接收者为指针:避免在每个方法调用中拷贝,更有效率;方法可以修改接收者指向的值,否则修改副本没有用 func (v *Vertex) Scale(f float64) { v.X = v.X * f v.Y = v.Y * f } 2. 接口 type Abser interface { // 一组方法定义的集合 Abs() float64 } var a Abser // a可以赋值:实现这些方法如Abs()的任何值 // 例子 type Person struct { Name string Age int } func (p Person) String() string { //`fmt`包使用接口Stringer中的String()方法来进行输出 return fmt.Sprintf("%v (%v years)", p.Name, p.Age) } func main() { a := Person{"Arthur Dent", 42} fmt.Println(a) // Arthur Dent (42 years), 相当于 重载了cout } 3. 异常 i, err := strconv.Atoi("42") if err != nil { // 非空表示失败 fmt.Printf("couldn't convert number: %v\n", err) } fmt.Println("Converted integer:", i) Exercise - error: 实现Sqrt使其接收到一个负数时,返回一个非nil错误值 type ErrNegativeSqrt float64 func (e ErrNegativeSqrt) Error() string { return "cannot Sqrt negative number:" + fmt.Sprint(float64(e)) } func Sqrt(x float64) (float64, error) { if(x < 0) { return x, ErrNegativeSqrt(x) } z := float64(1) for { y := (z + x/z) / 2.0 fmt.Println(y) if math.Abs(z - y) < 1e-10 { break } z = y } return z, nil } func main() { fmt.Println(Sqrt(2)) fmt.Println(Sqrt(-2)) // fmt包在输出时也会试图匹配 error接口 } 4. io.Reader接口 r := strings.NewReader("Hello, Reader!") // 创建Reader b := make([]byte, 8) // 每次读取8字节 for { n, err := r.Read(b) // Reader接口中的Read方法 fmt.Printf("n = %v err = %v b = %v\n", n, err, b) // 8 nil;6 nil;0 EOF fmt.Printf("b[:n] = %q\n", b[:n]) // %q, 打印字符串 if err == io.EOF { // 遇到数据流结尾时返回 break } } Exercise - rot13Reader: io.Reader包裹另一个io.Reader type rot13Reader struct { r io.Reader } func (rr rot13Reader) Read(s []byte) (n int, e error) { n, e = rr.r.Read(s) for i := 0; i < n; i++ { if((s[i]>='a'&&s[i]<'n') || (s[i]>='A'&&s[i]<'N')) { s[i] += 13 } else { s[i] -= 13 } } return //可以省略 } func main() { s := strings.NewReader("Lbh penpxrq gur pbqr!") r := rot13Reader{s} io.Copy(os.Stdout, &r) } 5. Web Server 包http通过任何实现了http.Handler接口的值来响应HTTP请求, 如其中的ServeHTTP函数 import ( "log" "net/http" "fmt" ) type String string func (s String) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, s) } type Struct struct { // 各种类型都可以实现该接口 Greeting string Punct string Who string } func (s *Struct) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, s.Greeting, s.Punct, s.Who) } func main() { http.Handle("/string", String("I'm a frayed knot.")) http.Handle("/struct", &Struct{"Hello", ":", "Gophers!"}) http.ListenAndServe("localhost:4000", nil) }