1、接口node
1.什么是interfacegolang
在面向对象编程中,能够这么说:“接口定义了对象的行为”, 那么具体的实现行为就取决于对象了。算法
在Go中,接口是一组方法签名。当一个类型为接口中的全部方法提供定义时,它被称为实现该接口。它与oop很是类似。接口指定类型应具备的方法,类型决定如何实现这些方法。编程
2.定义app
Interface类型能够定义一组方法,可是这些不须要实现,而且interface不能包含任何变量负载均衡
type 标识符 interface{ Method1(参数列表) 返回值列表 Method2(参数列表) 返回值列表 ... }
3.接口的实现dom
golang中的接口,不须要显式的实现,只要一个变量,含有接口类型中的全部方法,那么这个变量就实现这个接口。所以,golang中没有implement相似的关键字ide
若是一个变量含有多个interface类型的方法,那么这个变量就实现了多个接口
若是一个变量只含有一个interface的部分方法,那么这个变量没有实现这个函数
package main import "fmt" //定义一个薪资计算的接口,该接口有CalculateSalary方法,并无具体实现,只是一种规范 type SalaryCalculate interface{ CalculateSalary() int } type Manager struct{ basicpay int bonus int } type General struct{ basicpay int } //类型去具体实现接口中的方法 func (this Manager) CalculateSalary() int{ return this.basicpay + this.bonus } func (this General) CalculateSalary() int{ return this.basicpay } func totalExpense(p []SalaryCalculate){ total := 0 for _, v := range p{ //使用者不须要关心底层,只须要调用接口 total += v.CalculateSalary() } fmt.Printf("总开支 %d", total) } func main(){ Manager1 := Manager{10000, 6000} Manager2 := Manager{8000,7500} General1 := General{5000} //值类型实现接口 employees := []SalaryCalculate{Manager1, Manager2, General1} totalExpense(employees) }
4.多态:一种事物的多种形态,均可以按照统一的接口进行操做oop
例如:咱们定义一个车的接口,该接口拥有各类车共同拥有的方法,而该接口能够表明各类车,咱们只须要让具体的车去实现这个接口。
例如:Linux中的一切皆文件的思想,不管是磁盘,内存,仍是...都是文件,咱们只须要定义一个操做文件的接口,而各个具体的东西去实现接口的方法,在调用的时候只须要经过接口进行操做
例如:GO中sort包下Sort方法为咱们提供了排序的原语,咱们只须要去实现接口的方法便可,该包具备很强的扩展性,不须要为每一个类型都定义一个方法,只须要提供一个排序的接口,而对于使用者也是友好的,咱们不须要去记住每一个类型所应该对应的排序方法。
type Interface interface { // Len is the number of elements in the collection. // Len 为集合内元素的总数 Len() int // Less reports whether the element with // index i should sort before the element with index j. // // Less 返回索引为 i 的元素是否应排在索引为 j 的元素以前。 Less(i, j int) bool // Swap swaps the elements with indexes i and j. // Swap 交换索引为 i 和 j 的元素 Swap(i, j int) } package main import ( "sort" "fmt" "math/rand" ) type Student struct{ ID string Name string } type StudentArry []Student func (this StudentArry) Len() int{ return len(this) } func (this StudentArry) Less(i, j int) bool{ return this[i].Name < this[j].Name } func (this StudentArry) Swap(i, j int){ this[i], this[j] = this[j], this[i] } func trans(n StudentArry){ for _, v := range n{ fmt.Println(v) } } func main(){ var stus StudentArry for i := 0; i < 10; i++{ stu := Student{ ID: fmt.Sprintf("154%d", rand.Int()), Name: fmt.Sprintf("stu%d", rand.Intn(100)), } stus = append(stus,stu) } trans(stus) fmt.Printf("\n") sort.Sort(stus) trans(stus) }
5.接口嵌套
package main import "fmt" type Read interface{ Read() } type Write interface{ Write() } type ReadWrite interface{ Read Write } type File struct{ } func (this File) Read(){ fmt.Println("read data") } func (this File) Write(){ fmt.Println("write data") } func Test(v ReadWrite)(){ v.Read() v.Write() } func main(){ var f File Test(f) }
6.空接口,interface{}
空接口没有任何方法,因此全部类型都实现了空接口,也就是任何变量均可以赋值给空接口
var a int var b interface{} b = a
判断一个变量是否实现了指定接口
if sv, ok := v.(Stringer); ok{ fmt.Println("ok") }
7.类型断言,因为接口是通常类型,不知道具体类型,若是要转成具体类型,能够采用如下方法进行转换
var t int var x inteface{} x = t y = x.(int) //转成int
package main import "fmt" type Student struct{ Name string } func CheckType(items ...interface{}){ for _, v := range items{ switch v.(type) { case bool: fmt.Printf("%v params is bool\n", v) case int: fmt.Printf("%v params is int\n", v) case Student: fmt.Printf("%v params is Studen\nt", v) case *Student: fmt.Printf("%v params is *Student\n", v) } } } func main(){ stu := Student{ Name: "bob", } CheckType(false, 1, stu, &stu) }
实现一个通用的链表类
//link.go package main import "fmt" type Node struct{ Data interface{} Next *Node } type Link struct{ Head *Node Tail *Node } func (this *Link) IsEmpty() bool{ return this.Head == nil } func (this *Link) Init(node *Node){ this.Head = node this.Tail = node } func (this *Link) Insert(data interface{}){ node := &Node{ Data: data, } if this.IsEmpty(){ this.Init(node) return } node.Next = this.Head this.Head = node } func (this *Link) Trans(){ cur := this.Head for cur != nil{ fmt.Println(cur.Data) cur = cur.Next } } func (this *Link) Append(data interface{}){ node := &Node{ Data: data, } if this.IsEmpty(){ this.Init(node) return } this.Tail.Next = node this.Tail = node } //main.go package main import "fmt" func main(){ var link Link for i := 0; i < 10; i++{ link.Insert(fmt.Sprintf("stu%d",i)) } for i := 0; i < 10; i++{ link.Append(fmt.Sprintf("stu%d",i)) } link.Trans() }
变量slice和接口slice之间的赋值操做,for range
2、反射
能够在运行时动态获取变量的相关信息
1.两个函数
reflect.TypeOf,获取变量的类型,返回reflect.Type类型
reflect.ValueOf,获取变量的值,返回reflect.Value类型
import ( "fmt" "reflect" ) type Student struct{ Name string Age int Score float32 } func Test(n interface{}){ a := reflect.TypeOf(n) fmt.Println(a) v := reflect.ValueOf(n) fmt.Println(v) fmt.Printf("a type is %T; v type is %T",a, v) } func main(){ var stu Student Test(stu) } /* main.Student { 0 0} a type is *reflect.rtype; v type is reflect.Value */
经过reflect.Value类型咱们能够分析变量的各类属性
其中,reflect.Value.Kind,获取变量的类别,返回一个常量
const ( Invalid Kind = iota Bool Int Int8 Int16 Int32 Int64 Uint Uint8 Uint16 Uint32 Uint64 Uintptr Float32 Float64 Complex64 Complex128 Array Chan Func Interface Map Ptr Slice String Struct UnsafePointer )
type Student struct{ Name string Age int Score float32 } func Test(n interface{}){ a := reflect.TypeOf(n) fmt.Println(a) v := reflect.ValueOf(n) k := v.Kind() fmt.Println(k) } func main(){ var stu Student Test(stu) } /* main.Student struct 能够看出stu这个变量的类型是main包下的Student 而其类别是结构体 */
固然咱们也能够将reflect.Value类型逆转成interface{}类型
reflect.Value.Interface() //转换成interface{}类型
其转换关系为
变量 <------> interface{} <------> reflect.Value
获取变量的值
reflect.ValueOf(x).Float()
reflect.ValueOf(x).Int()
reflect.ValueOf(x).String()
reflect.ValueOf(x).Bool()
经过反射来改变变量的值
type Student struct{ Name string Age int Score float32 } func Test(n interface{}){ v := reflect.ValueOf(n) //注意v是指针类型,因此须要经过Elem()转换,其本质和*v同样 v.Elem().SetInt(99) } func main(){ b := 100 //注意得传指针类型,若是传值类型会panic Test(&b) fmt.Println(b) }
用反射操做结构体
reflect.Value.NumField() 获取结构体中字段的个数
reflect.Value.NumMethod() 获取结构体方法的个数
reflect.Value.Method(n).Call 来调用结构体中的方法
package main import ( "fmt" "reflect" ) type Student struct{ Name string Age int Score float32 } func (this Student) Print(){ fmt.Println(this) } func Test(p interface{}){ val := reflect.ValueOf(p) if val.Kind() != reflect.Struct{ fmt.Println("expect struct") return } fieldNum := val.NumField() methodNum := val.NumMethod() fmt.Println(fieldNum, methodNum) //调用第几个方法 val.Method(0).Call(nil) } func main(){ stu := Student{ Name: "stu100", Age: 18, Score: 99.5, } Test(stu) }
接口实例
实现一个负载均衡调度算法,支持随机、轮训等,思考如何实现如内置sort.Sort()同样,支持第三方扩展的需求
//balance.go /* 定义一个负载均衡算法接口,该接口接收一个包含主机实例的切片,经过算法返回一个主机实例 */ package balance type Balancer interface{ DoBalance([] *Instance) (*Instance, error) } //instance.go /*主机实例*/ package balance import "strconv" type Instance struct{ host string port int } //工厂函数 func NewInstance(host string, port int) *Instance{ return &Instance{ host: host, port: port, } } func (this *Instance) GetHost() string{ return this.host } func (this *Instance) GetPort() int{ return this.port } func (this *Instance) String() string{ return this.host + ":" + strconv.Itoa(this.port) } //random.go /* 咱们写一个包内置的随机算法,经过init函数进行初始化注册,该算法实现了负载均衡算法接口 */ package balance import ( "errors" "math/rand" ) type RandomBalance struct{ } func init(){ RegisterBalance("random", &RandomBalance{}) } func (this *RandomBalance) DoBalance(insts [] *Instance) (inst *Instance,err error){ lens := len(insts) if lens == 0{ err = errors.New("no instance") return } index := rand.Intn(lens) inst = insts[index] return } //mgr.go /* 一个注册中心,拥有注册过的算法(不管是咱们内置的仍是用户扩展的), */ package balance import "fmt" type BalanceMgr struct{ allBalancer map[string]Balancer } var mgr = BalanceMgr{ allBalancer: make(map[string]Balancer), } func (this *BalanceMgr) registerBalance(name string,b Balancer){ this.allBalancer[name] = b } func RegisterBalance(name string,b Balancer){ mgr.registerBalance(name, b) } func DoBalance(name string, insts []*Instance) (inst *Instance, err error){ balancer, ok := mgr.allBalancer[name] if !ok{ err = fmt.Errorf("Not found %s banlancer", name) return } inst, err = balancer.DoBalance(insts) return }
//poll.go /* 看成用户扩展的算法,实现负载均衡算法接口,并在注册中心注册 */ package main import ( "go_dev/day06/t9/balance" "errors" ) type PollBalance struct{ ctn int } func init(){ balance.RegisterBalance("poll", &PollBalance{}) } func (this *PollBalance) DoBalance(insts [] *balance.Instance) (inst *balance.Instance,err error) { lens := len(insts) if lens == 0{ err = errors.New("No instance") return } this.ctn = (this.ctn + 1) % lens inst = insts[this.ctn] return } //main.go package main import ( "time" "fmt" "math/rand" "go_dev/day06/t9/balance" "os" ) func main() { var insts []*balance.Instance for i := 0; i < 16; i++{ host := fmt.Sprintf("192.168.%d.%d",rand.Intn(255),rand.Intn(255)) one := balance.NewInstance(host, 8080 ) insts = append(insts, one) } //能够写到配置文件中 var balanceName = "random" if len(os.Args) > 1{ balanceName = os.Args[1] } for { inst, err := balance.DoBalance(balanceName, insts) if err != nil{ fmt.Println(err) continue } fmt.Println(inst) time.Sleep(time.Second) } }