接口
1. 定义: Interface类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量。
type example interface{
Method1(参数列表) 返回值列表
Method2(参数列表) 返回值列表
}
2.interface类型默认是一个指针
type example interface{
Method1(参数列表) 返回值列表
Method2(参数列表) 返回值列表
…
}
var a example
a.Method1()
3. 接口实现
- a. Golang中的接口,不需要显示的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口。因此,golang中没有implement类似的关键字
- b. 如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个接口。
- c. 如果一个变量只含有了1个interface的方部分方法,那么这个变量没有实现这个接口。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package main import "fmt" type Car interface { GetName() string Run() DiDi() } type Test interface { Hello() } type BMW struct { Name string } func (p *BMW) GetName() string { return p.Name } func (p *BMW) Run() { fmt.Printf("%s is running\n", p.Name) } func (p *BMW) DiDi() { fmt.Printf("%s is didi\n", p.Name) } func (p *BMW) Hello() { fmt.Printf("%s is hello\n", p.Name) } type BYD struct { Name string } func (p *BYD) GetName() string { return p.Name } func (p *BYD) Run() { fmt.Printf("%s is running\n", p.Name) } func (p *BYD) DiDi() { fmt.Printf("%s is didi\n", p.Name) } func main() { var car Car var test Test fmt.Println(car) // var bwm = BMW{} // bwm.Name = "宝马" bwm := &BMW{ Name: "宝马", } car = bwm car.Run() test = bwm test.Hello() byd := &BMW{ Name: "比亚迪", } car = byd car.Run() // var a interface{} // var b int // var c float32 // a = b // a = c // fmt.Printf("type of a %T\n", a) }
4.多态:一种事物的多种形态,都可以按照统一的接口进行操作
sort排序
package main
import (
"fmt"
"math/rand"
"sort"
)
type Student struct {
Name string
Id string
Age int
}
type Book struct {
Name string
Author string
}
type StudentArray []Student
func (self StudentArray) Len() int {
return len(self)
}
func (self StudentArray) Less(i, j int) bool {
return self[i].Name > self[j].Name
}
func (self StudentArray) Swap(i, j int) {
self[i], self[j] = self[j], self[i]
}
func main() {
var stus StudentArray
for i := 0; i < 10; i++ {
stu := Student{
Name: fmt.Sprintf("stu%d", rand.Intn(100)),
Id: fmt.Sprintf("110%d", rand.Int()),
Age: rand.Intn(100),
}
stus = append(stus, stu)
}
for _, v := range stus {
fmt.Println(v)
}
fmt.Println()
sort.Sort(stus)
for _, v := range stus {
fmt.Println(v)
}
}
5. 接口嵌套:一个接口可以嵌套在另外的接口,如下所示:
type ReadWrite interface {
Read(b Buffer) bool
Write(b Buffer) bool
}
type Lock interface {
Lock()
Unlock()
}
type File interface {
ReadWrite
Lock
Close()
}
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package main import "fmt" type Reader interface { Read() } type Writer interface { Write() } type ReadWriter interface { Reader Writer } type File struct { } func (self *File) Read() { fmt.Println("read data") } func (self *File) Write() { fmt.Println("write data") } func Test(rw ReadWriter) { rw.Read() rw.Write() } func main() { var f *File var b interface{} b = f // Test(f) v, ok := b.(ReadWriter) fmt.Println(v, ok) }
6. 类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型,可以采用以下方法进行转换:
var t int
var x interface{}
x = t
y, ok = x.(int) //转成int,带检查
7. 练习,写一个函数判断传入参数的类型
package main
import (
"fmt"
)
type Studnet struct {
Name string
Sex string
}
func Test(a interface{}) {
// b, ok := a.(int)
b, ok := a.(Studnet)
if ok == false {
fmt.Println("convert failed")
return
}
// b += 3
fmt.Println(b)
}
func just(items ...interface{}) {
for index, v := range items {
switch v.(type) {
case bool:
fmt.Printf("%d params is bool, value is %v\n", index, v)
case int, int32, int64:
fmt.Printf("%d params is int, value is %v\n", index, v)
case float32, float64:
fmt.Printf("%d params is float, value is %v\n", index, v)
case string:
fmt.Printf("%d params is string, value is %v\n", index, v)
case Studnet:
fmt.Printf("%d params is student, value is %v\n", index, v)
case *Studnet:
fmt.Printf("%d params is *student, value is %v\n", index, v)
}
}
}
func main() {
var a interface{}
var b int
Test(b)
a = b
c := a.(int)
fmt.Printf("%d %T\n", a, a)
fmt.Printf("%d %T\n", c, c)
var d Studnet = Studnet{
Name: "stu1",
Sex: "female",
}
Test(d)
just(28, 8.2, "this is a test", d, &d)
}
8. 类型断言,采用type switch方式
9. 空接口.interface{}
空接口没有任何方法,所以所有类型都实现了空接口。
var a int
var b interface{}
b = a
10.判断一个变量是否实现了指定接口
type Stringer interface {
String() string
}
var v MyStruct
if sv, ok := v.(Stringer); ok {
fmt.Printf(“v implements String(): %s\n”, sv.String());
}
11. 实现一个通用的链表类
link.go
package main
import (
"fmt"
)
type LinkNode struct {
data interface{}
next *LinkNode
}
type Link struct {
head *LinkNode
tail *LinkNode
}
func (p *Link) InsertHead(data interface{}) {
node := &LinkNode{
data: data,
next: nil,
}
if p.tail == nil && p.head == nil {
p.tail = node
p.head = node
return
}
node.next = p.head
p.head = node
}
func (p *Link) InsertTail(data interface{}) {
node := &LinkNode{
data: data,
next: nil,
}
if p.tail == nil && p.head == nil {
p.tail = node
p.head = node
return
}
p.tail.next = node
p.tail = node
}
func (p *Link) Trans() {
q := p.head
for q != nil {
fmt.Println(q.data)
q = q.next
}
}
main.go
package main
func main() {
var initLink Link
for i := 0; i < 10; i++ {
// initLink.InsertHead(i)
initLink.InsertTail(i)
}
initLink.Trans()
}
12. interface{},接口中一个方法也没有,所以任何类型都实现了空接口,也就是任何变量都可以赋值给空接口。
var a int
var b interface{}
b = a
13. 变量slice和接口slice之间赋值操作,for range
var a []int
var b []interface{}
b = a
14. 实现一个负载均衡调度算法,支持随机、轮训等算法
- balance
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package balance type Balancer interface { DoBalance([]*Instance, ...string) (*Instance, error) }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 (p *Instance) GetHost() string { return p.host } func (p *Instance) GetPort() int { return p.port } func (p *Instance) String() string { return p.host + ":" + strconv.Itoa(p.port) }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package balance import "fmt" type BalanceMgr struct { allBalancer map[string]Balancer } var mgr = BalanceMgr{ allBalancer: make(map[string]Balancer), } func (p *BalanceMgr) RegisterBalancer(name string, b Balancer) { p.allBalancer[name] = b } func RegisterBalancer(name string, b Balancer) { mgr.RegisterBalancer(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 balancer", name) return } fmt.Printf("use %s balance\n", name) inst, err = balancer.DoBalance(insts) return }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package balance import ( "errors" "math/rand" ) func init() { RegisterBalancer("random", &RandomBalance{}) } type RandomBalance struct { } func (p *RandomBalance) DoBalance(insts []*Instance, key ...string) (inst *Instance, err error) { if len(insts) == 0 { err = errors.New("No instance") return } lens := len(insts) index := rand.Intn(lens) inst = insts[index] return }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package balance import ( "errors" ) func init() { RegisterBalancer("roundrobin", &RoundRobinBalance{}) } type RoundRobinBalance struct { curIndex int } func (p *RoundRobinBalance) DoBalance(insts []*Instance, key ...string) (inst *Instance, err error) { if len(insts) == 0 { err = errors.New("No instance") return } lens := len(insts) if p.curIndex >= lens { p.curIndex = 0 } inst = insts[p.curIndex] p.curIndex = (p.curIndex + 1) % lens return }
- main
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package main import ( "fmt" "go_dev/day7/example/example1/balance" "hash/crc32" "math/rand" ) type HashBalance struct { } func init() { balance.RegisterBalancer("hash", &HashBalance{}) } func (p *HashBalance) DoBalance(insts []*balance.Instance, key ...string) (inst *balance.Instance, err error) { var defkey string = fmt.Sprintf("%d", rand.Int()) if len(key) > 0 { // err := fmt.Errorf("hash balance must pass the hash key") defkey = key[0] } lens := len(insts) if lens == 0 { err = fmt.Errorf("No backend instance") return } crcTable := crc32.MakeTable(crc32.IEEE) hashVal := crc32.Checksum([]byte(defkey), crcTable) index := int(hashVal) % lens inst = insts[index] return }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package main import ( "fmt" "go_dev/day7/example/example1/balance" "math/rand" "os" "time" ) func main() { // 定义一个空切片 // insts := main([]*balance.Instance) 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] } // var balancer balance.Balancer // var conf = "random" // if len(os.Args) > 1 { // conf = os.Args[1] // } // if conf == "random" { // balancer = &balance.RandomBalance{} // 随机 // fmt.Println("use random balancer") // } else if conf == "roundrobin" { // balancer = &balance.RoundRobinBalance{} // 轮询 // fmt.Println("use roundrobin balancer") // } // balancer := &balance.RandomBalance{} // 随机 // balancer := &balance.RoundRobinBalance{} // 轮询 for { inst, err := balance.DoBalance(balanceName, insts) if err != nil { // fmt.Println("do balance err:", err) fmt.Fprintf(os.Stdout, "do balance error\n") continue } fmt.Println(inst) time.Sleep(time.Second) } } // 运行 // go run go_dev/day7/example/example1/main random // go run go_dev/day7/example/example1/main roundrobin // go run go_dev/day7/example/example1/main hash // 编译 // go build go_dev/day7/example/example1/main
反射
1. 反射:可以在运行时动态获取变量的相关信息
Import (“reflect”)
两个函数:
- a. reflect.TypeOf,获取变量的类型,返回reflect.Type类型
- b. reflect.ValueOf,获取变量的值,返回reflect.Value类型
- c. reflect.Value.Kind,获取变量的类别,返回一个常量
- d. reflect.Value.Interface(),转换成interface{}类型
2. reflect.Value.Kind()方法返回的常量
3. 获取变量的值:
reflect.ValueOf(x).Float()
reflect.ValueOf(x).Int()
reflect.ValueOf(x).String()
reflect.ValueOf(x).Bool()
4. 通过反射的来改变变量的值
reflect.Value.SetXX相关方法,比如:
reflect.Value.SetFloat(),设置浮点数
reflect.Value.SetInt(),设置整数
reflect.Value.SetString(),设置字符串
5. 用反射操作结构体
a. reflect.Value.NumField()获取结构体中字段的个数
b. reflect.Value.Method(n).Call来调用结构体中的方法
6.案例
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package main import ( "fmt" "reflect" ) type Student struct { Name string Age int Score float32 } func test(b interface{}) { t := reflect.TypeOf(b) fmt.Println(t) v := reflect.ValueOf(b) k := v.Kind() fmt.Println(k) iv := v.Interface() stu, ok := iv.(Student) if ok { fmt.Printf("%v %T\n", stu, stu) } } func testInt(b interface{}) { val := reflect.ValueOf(b) val.Elem().SetInt(100) c := val.Elem().Int() fmt.Printf("get value interface{} %d\n", c) fmt.Printf("string value: %d\n", val.Elem().Int()) } func main() { var a Student = Student{ Name: "stu1", Age: 18, Score: 92, } test(a) var b int = 1 testInt(&b) fmt.Println(b) }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
package main import ( "encoding/json" "fmt" "reflect" ) type Student struct { Name string `json:"student_name"` Age int Score float32 Sex string } func (s Student) Print() { fmt.Println("---start----") fmt.Println(s) fmt.Println("---end----") } func (s Student) Set(name string, age int, score float32, sex string) { s.Name = name s.Age = age s.Score = score s.Sex = sex } func TestStruct(a interface{}) { tye := reflect.TypeOf(a) val := reflect.ValueOf(a) kd := val.Kind() if kd != reflect.Ptr && val.Elem().Kind() == reflect.Struct { fmt.Println("expect struct") return } num := val.Elem().NumField() val.Elem().Field(0).SetString("stu1000") for i := 0; i < num; i++ { fmt.Printf("%d %v\n", i, val.Elem().Field(i).Kind()) } fmt.Printf("struct has %d fields\n", num) tag := tye.Elem().Field(0).Tag.Get("json") fmt.Printf("tag=%s\n", tag) numOfMethod := val.Elem().NumMethod() fmt.Printf("struct has %d methods\n", numOfMethod) var params []reflect.Value val.Elem().Method(0).Call(params) } func main() { var a Student = Student{ Name: "stu01", Age: 18, Score: 92.8, } result, _ := json.Marshal(a) fmt.Println("json result:", string(result)) TestStruct(&a) fmt.Println(a) }