嵌套方法

//毕达哥拉斯定理
package main

import (
	"fmt"
	"math"
)

type Point struct {
	x, y float64
}

func (p *Point) Abs() float64 {
	return math.Sqrt(p.x*p.x + p.y*p.y)
}

type NamedPoint struct {
	Point
	name string
}

func main() {
	n := &NamedPoint{Point{3, 4}, "Pythagoras"}
    fmt.Println(n.Abs()) // 打印5
    fmt.Println(n.name)
}

output

5
Pythagoras

对于接口,类型(比如结构体)实现接口方法集中的方法,每一个方法的实现说明了此方法是如何作用于该类型的:即实现接口,同时方法集也构成了该类型的接口。
下面是求矩形面积的一个实例:

//计算矩形面积,没用接口
package main

import "fmt"

type Square struct{
    side float64
}

type Rectangle struct{
    length float64
    width float64
}

func (sq *Square)Area()float64{
    return sq.side*sq.side
}

func (r *Rectangle)Area()float64{
    return r.length*r.width
}

func main(){
    a := &Rectangle{2,3}
    b := &Square{5}
    fmt.Println(a.Area(),b.Area())
}
//output:6 25

下面是用接口的代码:

package main

import "fmt"

type Shaper interface{
    Area()float64
}

type Square struct{
    side float64
}

type Rectangle struct{
    length float64
    width float64
}

func (sq *Square)Area()float64{
    return sq.side*sq.side
}

func (r *Rectangle)Area()float64{
    return r.length*r.width
}

func main(){
    a := &Rectangle{2,3}
    b := &Square{5}
    shape :=  []Shaper{a,b}//定义shape接口,将a,b以数组的形式放进去
    fmt.Println(shape[0].Area(),shape[1].Area())//可用for-range读取每一个  计算值
}
//output:6 25

当然也可以用这样的方式来使用接口:

func main(){
    a := &Rectangle{2,3}
    var shape Shaper
    shape = a
    fmt.Println(shape.Area())
}

接口嵌套接口

type ReadWrite interface {
    Read(b Buffer) bool
    Write(b Buffer) bool
}

type Lock interface {
    Lock()
    Unlock()
}

type File interface {
    ReadWrite
    Lock
    Close()
}

检测接口变量的类型
继续用上面求矩形面积的代码

    a := &Rectangle{2,3}
    var shape Shaper
    shape = a //这里是Rectangle方法的接口
    if v,ok := shape.(*Rectangle);ok{
        fmt.Printf("The type of shape is %T\n",v)
    }else{
        fmt.Println("Shape does not have a variable type of Rectangle")
    }
//output:The type of shape is *main.Rectangle

用type-switch判断接口类型

switch t := areaIntf.(type) {
case *Square:
	fmt.Printf("Type Square %T with value %v\n", t, t)
case *Circle:
	fmt.Printf("Type Circle %T with value %v\n", t, t)
case nil:
	fmt.Printf("nil value: nothing to check?\n")
default:
	fmt.Printf("Unexpected type %T\n", t)
}

实用的空接口
可以将任何类型写进去,这里我以写入结构体为例:

package main

import "fmt"

type Person struct{
    name string
    age int
}

type Any interface{}

func main(){
    var inter Any
    per1 := new(Person)
    per1.name="Mr_zwX"
    per1.age=18
    inter=per1
    fmt.Println(inter)
}
//output:&{Mr_zwX 18}

复制数据切片到空接口切片(必须是显性复制的过程)

var dataSlice []myType = FuncReturnSlice()
var interfaceSlice []interface{} = make([]interface{}, len(dataSlice))
for i, d := range dataSlice {
    interfaceSlice[i] = d
}

通过反射修改值

package main

import (
	"fmt"
	"reflect"
)

func main() {
    var x float64=1.2345
    v := reflect.ValueOf(x)
    fmt.Println("Value:",v)//Value: 1.2345
    fmt.Println("Settability:",v.CanSet())//Settability: false
    v=reflect.ValueOf(&x)
    fmt.Println("Type:",v.Type())//Type: *float64
    fmt.Println("Settability:",v.CanSet())//Settability: false

    v=v.Elem()
    fmt.Println("Settability:",v.CanSet()) // Settability: true  
    v.SetFloat(2.3333)  
    fmt.Println(v)//2.3333
}