golang之指针
package main import "fmt" type myInt int //匿名函数 //值的接收 //指针的接收 //*myint表示myInt的指针类型 // *i表示指针i,指向i的值 func (i *myInt) add(another int) myInt { *i = *i + myInt(another) return *i } //i1与i是两个变量,传递值 func main() { i1 := myInt(1) i2 := i1.add(2) fmt.Println(i1,i2) }
值方法,指针方法遵循了如下规则:
接受者变量代表的值实际上是源值的复制品。如果这个值不是指针类型,在值方法中就没有途径去改变源值。
而指针值与其复制品指向的是同一个值,所以在指针方法中就存在了改变源值的途径。
如果接受者类型是引用类型或者它的别名类型,即使是值方法,也可以改变源值
-------------
对于某个非指针的数据类型,与它关联的方法的集合中只包含它的值方法。而对于它的指针类型,其方法集合中只包含它的值方法也包含指针方法。
在非指针数据类型的值上,也是能够调用其指针方法的。
这是因为GO在内部做了自动转换。
例如add方法是指针方法,那么表达式i1.add(2)会被自动转换为(&i1).add(2)
第二条规则对于编写接口类型的实现类型来说很重要。
Golang之排序算法
冒泡排序
package main //冒泡排序 import "fmt" func bsort(a []int) { for i := 0; i < len(a); i++ { for j := 1; j < len(a)-i; j++ { if a[j] < a[j-1] { a[j], a[j-1] = a[j-1], a[j] } } } } func main() { b := [...]int{8, 7, 5, 4, 3, 10, 15} bsort(b[:]) fmt.Println(b) }
选择排序
package main import "fmt" //冒泡排序 func ssort(a []int) { for i := 0; i < len(a); i++ { var min int = i for j := i + 1; j < len(a); j++ { if a[min] > a[j] { min = j } } a[i], a[min] = a[min], a[i] } } func main() { b := [...]int{8, 7, 5, 4, 3, 10, 15} ssort(b[:]) fmt.Println(b) }
插入排序
package main import "fmt" //冒泡排序 func isort(a []int) { for i := 1; i < len(a); i++ { for j := i; j > 0; j-- { if a[j] > a[j-1] { break } a[j], a[j-1] = a[j-1], a[j] } } } func main() { b := [...]int{8, 7, 5, 4, 3, 10, 15} isort(b[:]) fmt.Println(b) }
快速排序
package main import "fmt" //快速排序 func qsort(a []int, left, right int) { if left >= right { return } val := a[left] k := left //确定val所在的位置 for i := left + 1; i <= right; i++ { if a[i] < val { a[k] = a[i] a[i] = a[k+1] k++ } } a[k] = val qsort(a, left, k-1) qsort(a, k+1, right) } func main() { b := [...]int{8, 7, 5, 4, 3, 10} qsort(b[:], 0, len(b)-1) fmt.Println(b) }
Golang之struct
1.用来定义复杂数据结构
2.struct里面可以包含多个字段(属性)
3.struct类型可以定义方法,注意和函数的区分。
4.struct类型是值类型
5.struct类型可以嵌套
6.Go语言没有class类型,只有struct类型
package main import "fmt" //声明结构体 type Student struct { Name string Age int Score int } func main() { //struct字段访问,使用“点”访问 var stu Student stu.Name = "yuchao" stu.Age = 18 stu.Score = 99 fmt.Printf("name=%s age=%d scrore=%d", stu.Name, stu.Age, stu.Score) }
定义struct的三种形式:
package main import "fmt" //声明结构体 //字段名和函数名一样,首字母大写,在包外可以访问 type Student struct { Name string Age int Score float32 } func main() { //struct字段访问,使用“点”访问 var stu Student //var stu *Student = new(Student) //var stu *Student = &Student{ } stu.Name = "yuchao" stu.Age = 18 stu.Score = 99 //fmt.Println(stu) //默认结构 {yuchao 18 99.1} //fmt.Printf("name=%s age=%d scrore=%d", stu.Name, stu.Age, stu.Score) var stu1 *Student = &Student{ Age: 20, Name: "chao", } var stu3 = Student{ Age: 20, Name: "hua", } fmt.Println(stu1) fmt.Println(stu3.Name) fmt.Printf("Name:%p ", &stu.Name) fmt.Printf("age:%p ", &stu.Age) fmt.Printf("score:%p ", &stu.Score) }
var stu Student var stu *Student = new(Student) var stu *Student = &Student{ }
struct的内存布局,struct中的所有字段在内存是连续的,布局如下:
Golang之面向对象和指针
package main import "fmt" type Integer int //为内置的int类型增加了新方法less,面向对象写法 func (a Integer) Less(b Integer) bool { return a < b } func Integer_Less(a Integer, b Integer) bool { return a < b } //Go的面向对象,如果需要修改对象,必须用指针,这不是Go约束,还是自然约束 func (a *Integer) Add(b Integer) { *a += b } //Integer类型是一个int,为int起一个别名Integer, // 并且增加一系列方法Add,Add2,又编程了一个新的类型,这个类型还完全拥有int的功能 //传递值而不是指针 func (a Integer) Add2(b Integer) { a += b fmt.Println(a) fmt.Println(b) } func main() { var a Integer = 1 if a.Less(2) { fmt.Println(a, "Less 2") } if Integer_Less(a, 2) { fmt.Println(a, "Less 2") } //为Integer又加了Add方法,Add()方法需要修改对象的值,需要指针引用 //a.Add(2) //fmt.Println("a=", a) //实现成员方法传入的如果不是指针,而是值,也就是Integer,而非*Iteger,,这时a=1 a.Add2(2) fmt.Println("a=", a) //Go语言和C语言一样,类型都是基于值传递,想要修改变量的值,只能传递指针 } /* Go语言中没有隐藏的this指针 方法施加的目标(“对象”)显示传递,没有被隐藏 方法施加的目标(“对象”)不需要非得是指针,也不用非得叫this */
//值语义和引用语义 //b=a //b.Modify() //如果b的修改,不影响a的值,那么此类型就是值类型 //如果会影响a的值,那么此类型就是引用类型 //Go语言大多类型都是值语义 //基本类型:byte、int、bool、float32、float64、string等 //复合类型:数组(array)、结构体(struct)和指针(point) //数组被完整的复制,就是值语义 func main() { var a=[3]int{1,2,3} var b=a //表示b=a赋值语句,是数组内容的完整复制 b[1]++ fmt.Println(a,b) } //引用方法,需要使用指针 func main() { var a = [3]int{1, 2, 3} var b = &a //这句赋值,是数组内容的引用,变量b类型是*[3]int类型 b[1]++ fmt.Print(a, *b) }
Golang之Struct(二叉树定义)
package main import "fmt" //二叉树结构体 //如果每个节点有两个指针,分别用来指向左子树和右子树,我们把这样的结构叫做二叉树 type Student struct { Name string Age int Score float32 left *Student right *Student } func trans(root *Student) { if root == nil { return } //fmt.Println(root) //前序遍历 trans(root.left) //fmt.Println(root) //中序遍历 trans(root.right) fmt.Println(root) //后序遍历 } func main() { var root *Student = new(Student) root.Name = "stu01" root.Age = 18 root.Score = 100 var left1 *Student = new(Student) left1.Name = "stu02" left1.Age = 18 left1.Score = 100 root.left = left1 var right1 *Student = new(Student) right1.Name = "Stu04" right1.Age = 18 right1.Score = 100 root.right = right1 var left2 *Student = new(Student) left2.Name = "Stu03" left2.Age = 18 left2.Score = 100 left1.left = left2 trans(root) }
Golang之方法(自定义类型,struct)
方法的使用,请看本天师的代码
//Golang的方法定义 //Golang中的方法是作用在特定类型的变量上,因此自定义类型,都可以有方法,不仅仅是struct //定义:func (recevier type) methodName(参数列表)(返回值列表){} //方法和函数的区别 /* 1,函数调用:function(variable,参数列表) 2, 方法,variable.function(参数列表) 方法的控制,通过大小写空格控制 */
package main //Golang的方法定义 //Golang中的方法是作用在特定类型的变量上,因此自定义类型,都可以有方法,不仅仅是struct //定义:func (recevier type) methodName(参数列表)(返回值列表){} import "fmt" type integer int func (p integer) print() { fmt.Println("p is:", p) } //这里传递的是副本,想改变p的值,需要传递指针 func (p *integer) set(b integer) { *p = b } type Student struct { Name string Age int Score int sex int } //这里需要接受指针 *Student(接收者),否则修改不了值 func (p *Student) init(name string, age int, score int) { p.Name = name p.Age = age p.Score = score fmt.Println(p) } func (p Student) get() Student { return p } func main() { var stu Student //修改地址的写法(&stu).init //但是go可以自动知道,接受者是指针,这里stu就传递地址 stu.init("stu", 18, 99) stu1 := stu.get() fmt.Println(stu1) //type integer方法 var a integer a = 100 a.print() a.set(1000) a.print() }
Golang之继承,多重继承(struct)
package main import "fmt" /* 继承 一个结构体嵌到另一个结构体,称作组合 匿名和组合的区别 如果一个struct嵌套了另一个匿名结构体,那么这个结构可以直接访问匿名结构体的方法,从而实现继承 如果一个struct嵌套了另一个【有名】的结构体,那么这个模式叫做组合 如果一个struct嵌套了多个匿名结构体,那么这个结构可以直接访问多个匿名结构体的方法,从而实现多重继承 */ type Car struct { weight int name string } func (p *Car) Run() { fmt.Println("running") } type Bike struct { Car lunzi int } type Train struct { Car } func (p *Train) String() string { str := fmt.Sprintf("name=[%s] weight=[%d]", p.name, p.weight) return str } func main() { var a Bike a.weight = 100 a.name = "bike" a.lunzi = 2 fmt.Println(a) a.Run() var b Train b.weight = 100 b.name = "train" b.Run() fmt.Printf("%s", &b) }
练习2
package main import ( "fmt" "time" ) type Car struct { Name string Age int } func (c *Car) Set(name string, age int) { c.Name = name c.Age = age } type Car2 struct { Name string } //Go有匿名字段特性 type Train struct { Car Car2 createTime time.Time //count int 正常写法,Go的特性可以写成 int } //给Train加方法,t指定接受变量的名字,变量可以叫this,t,p func (t *Train) Set(age int) { t.int = age } func main() { var train Train train.int = 300 //这里用的匿名字段写法,给Age赋值 //(&train).Set(1000) train.Car.Set("huas", 100 ) train.Car.Name = "test" //这里Name必须得指定结构体 fmt.Println(train) }
Golang之接口(interface)
Golang最重要的接口,,,,
package main import ( "fmt" ) //interface类型默认是指针 /* 接口的实现 Golang中的接口,不需要显示的实现。只需要一个变量,含有接口类型中的所有方法,那么这个变量就实现这个接口 因为Golang中没有implement类似的关键字 如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个接口 如果一个变量只含有了1个interface的部分方法,那么这个变量没有实现这个接口.. 一种事物的多种形态,都可以按照统一的接口进行操作 */ //接口嵌套 type ReadWrite interface { Read(b Buffer) bool Write(b Buffer) bool } type Lock interface { Lock() Unlock() } //嵌套,继承了前面四个方法,File就有6个方法 type File interface { ReadWrite Lock Close() } //类型断言,由于接口是一般类型,不知道具体类型,如果要转成具体类型可以采用以下方法进行转换 var t int var x interface{} x=t y,ok=x.(int) //定义People结构体 type People struct { name string age int } //定义Test接口 type Test interface { //接口有2个方法 Print() Sleep() } //定义struct type Student struct { name string age int score int } //定义Print()方法 func (p Student) Print() { fmt.Println("name:", p.name) fmt.Println("age:", p.age) fmt.Println("score", p.score) } //Sleep方法 func (p Student) Sleep() { fmt.Println("student sleep") } func (people People) Print() { fmt.Println("name:", people.name) fmt.Println("age:", people.age) } func (p People) Sleep() { fmt.Println("People Sleep") } func main() { var t Test //接口是个地址 fmt.Println(t) var stu Student = Student{ name: "stu1", age: 20, score: 200, } t = stu t.Print() t.Sleep() fmt.Println("t:", t) }
//接口,空接口
package main import "fmt" type Carer interface { GetName() string Run() } func main() { var a interface{} //空接口 var b int //具体类型 //空接口可以保持任何类型的变量 a = b // b给a赋值,空接口可以容纳任何类型 b=a //这是错的 fmt.Printf("type of a:%T ", a) // %T打印类型 }
//接口的实现(车,宝马车)
package main import "fmt" type Carer interface { GetName() string Run() DiDi() } type BMW struct { Name string } //得实现接口所有的方法,才算实现了该接口 func (p *BMW) GetName() string { return p.Name } //因此还得实现RUN() //指针类型*BMW,也可以写值类型 (p BMW) func (p *BMW) Run() { fmt.Printf("%s is running ", p.Name) } //还得实现DiDi() func (p *BMW) DiDi() { fmt.Printf("%s is didi ", p.Name) } func main() { var car Carer fmt.Println(car) //var bmw BMW //bmw.Name = "BMW" //写法2 bmw := &BMW{ Name: "BMW", } car = bmw car.Run() }
//Golang中的接口,不需要显示的实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现了这个接口。
//因此Golang中没有implement类似的关键字
//如果一个变量含有了多个interface类型的方法,那么这个变量就实现了多个接口
package main import "fmt" type Carer interface { GetName() string Run() DiDi() } type Test interface { Hello() } //宝马车 type BMW struct { Name string } //因此还得实现RUN() //得实现接口所有的方法,才算实现了该接口 func (p *BMW) GetName() string { return p.Name } //实现接口的Run() func (p *BMW) Run() { fmt.Printf("%s is running ", p.Name) } //还得实现DiDi() func (p *BMW) DiDi() { fmt.Printf("%s is didi ", p.Name) } func (p *BMW) Hello() { fmt.Printf("hello,i'm %s ", p.Name) } //比亚迪 type BYD struct { Name string } func (p *BYD) GetName() string { return p.Name } func (p *BYD) Run() { fmt.Printf("%s is running ", p.Name) } func (p *BYD) DiDi() { fmt.Printf("%s is didi ", p.Name) } func main() { var car Carer var test Test fmt.Println(car) //var bmw BMW //bmw.Name = "BMW" //写法2 bmw := &BMW{ Name: "BMW", } car = bmw car.Run() test = bmw test.Hello() byd := &BYD{ Name: "BYD", } car = byd car.Run() }
Golang之指针(point)再探索
package main import "fmt" /* 声明指针 *T 是指向类型T的值的指针变量的类型 */ func main() { //b := 255 //var a *int = &b // a是int指针,指向b的内存地址 //fmt.Printf("Type of is:%T ", a) //fmt.Println("address of b is", a) // //a := 22 //var b *int //b 这个变量是int类型的指针变量,变量的值,也只能是int型指针 //if b == nil { // // 指针的零值是nil // fmt.Println("b is", b) // b = &a // fmt.Println("b after initialization is", b) //} //b := 255 //a := &b //fmt.Println("address of b is", a)//打印b的内存地址 //fmt.Println("value of b is", *a)//打印b的值,可以通过*a指针 //b := 255 //a := &b //fmt.Println("address of b is:", a) //b的内存地址 //fmt.Println("value of b is:", *a) //*a++ //通过a的指针加一 //fmt.Println("new value of b is:", b) //a := 58 //fmt.Println("value of a befor func call is:", a) //b := &a //change(b) //指针变量b,改变a的值,a=55, //fmt.Println("value of a after call is:", a) /* 不要将指向数组的指针,作为参数传递给函数,改用切片 */ //a := [3]int{89, 90, 91} //modify(&a) //传递数组a的地址,给modify //fmt.Println(a) a := [3]int{89, 90, 91} modify(a[:]) //传入一个a的切片 fmt.Println(a) } //函数传递指针,改变参数的内存地址。 //func change(val *int) { // *val = 55 //修改数组的值 //传递指向数组的指针,作为参数,并且对其修改 //func modify(arr *[3]int) { // (*arr)[0] = 90 // //arr[0]=90 //也可以这么写,这是上面的简写形式(*a)[X]可以写成a[X] //} //切片方式修改函数 //这个方法是修改函数最常用的,最好的方法。。。。。。。。。。。。 func modify(sls []int) { sls[0] = 91 } //Go不支持如同C的指针运算
Golang之interface(多态,类型断言)
多态用法
package main //一种事物的多种形态,都可以按照统一的接口进行操作 //多态 import ( "fmt" "math/rand" "sort" ) type Student struct { Name string Id string Age int sortType int } type Book struct { Name string Author string } //切片默认传地址 type StudentArray []Student func (p StudentArray) Len() int { return len(p) } func (p StudentArray) Less(i, j int) bool { return p[i].Name < p[j].Name } func (p StudentArray) Swap(i, j int) { p[i], p[j] = p[j], p[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) } }
接口嵌套
package main import "fmt" //接口嵌套 一个接口可以嵌套在另外的接口 type Reader interface { Read() } type Writer interface { Write() } type ReadWriter interface { Reader Writer } type File struct { } func (f *File) Read() { fmt.Println("read data") } func (f *File) Write() { fmt.Print("write data") } func Test(rw ReadWriter) { rw.Read() rw.Write() } func main() { var f File Test(&f) }
类型断言
package main import "fmt" type Student struct { Name string Sex string } //类型断言 //一个判断传入参数类型的函数 func just(items ...interface{}) { for index, v := range items { switch v.(type) { case bool: fmt.Printf("%d params is bool,value is %v ", index, v) case int, int64, int32: fmt.Printf("%d params is int,value is %v ", index, v) case float32, float64: fmt.Printf("%d params is float,value is %v ", index, v) case string: fmt.Printf("%d params is string,value is %v ", index, v) case Student: fmt.Printf("%d params student,value is %v ", index, v) case *Student: fmt.Printf("%d params *student,value is %v ", index, v) } } } func main() { var b Student = Student{ Name: "stu01", Sex: "female", } just(28, 8.2, "this is a test", b, &b) }
Golang之实现(链表)
链表算法
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 } } 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 } }
package main import "fmt" func main() { var link Link for i := 0; i < 10; i++ { //link.InsertHead(i) link.InsertTail(fmt.Sprintf("str %d",i)) } link.Trans() }
Golang之反射(重点!!)
1、反射:可以在运行时动态获取变量的相关信息
Import(“reflect”)
两个函数:
reflect.TypeOf()//获取变量的类型,返回reflect.Type类型
reflect.ValueOf()//获取变量的值,返回reflect.Value类型
reflect.Value.Kind()//获取变量的类别,返回一个常量
reflect.Value.Interface()//转换成interface{}类型
可逆状态
示例用法
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 ", stu, stu) } } func testInt(b interface{}) { val := reflect.ValueOf(b) c := val.Int() fmt.Printf("get value interface{} %d ", c) } func main() { var a Student = Student{ Name: "stu01", Age: 18, Score: 92, } test(a) testInt(1234) }
package main import ( "fmt" "reflect" ) func main(){ var x float64=3.4 fmt.Println("type:",reflect.TypeOf(x)) v:=reflect.ValueOf(x) fmt.Println("value:",v) fmt.Println("type:",v.Type()) fmt.Println("kind:",v.Kind()) fmt.Println("value:",v.Float()) fmt.Println(v.Interface()) fmt.Printf("value is %5.2e ",v.Interface()) y:=v.Interface().(float64) fmt.Println(y) }
获取变量的值
reflect.ValueOf(x).Float()
reflect.ValueOf(x).Int()
reflect.ValueOf(x).String()
reflect.ValueOf(x).Bool()
反射之elem()修改指针的方法
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 ", stu, stu) } } func testInt(b interface{}) { val := reflect.ValueOf(b) val.Elem().SetInt(100) //val.Elem().Setint()相当于指针操作 c := val.Elem().Int() fmt.Printf("get value interface{}%d ", c) fmt.Printf("string val:%d ", val.Elem().Int()) } func main() { var a Student = Student{ Name: "stu01", Age: 18, Score: 92, } test(a) var b int = 1 b = 200 testInt(&b) fmt.Println(b) }
用反射操作结构体
reflect.Value.NumField()获取结构体中字段的个数
reflect.Value.Method(n).Call来条用结构体中的方法
反射取得结构体方法个数,字段数
package main //通过反射动态修改变量的值 import ( "fmt" "reflect" ) type Student struct { Name string Age int Score float32 Sex string } 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{}) { val := reflect.ValueOf(a) kd := val.Kind() if kd != reflect.Struct { fmt.Println("expect struct") return } num := val.NumField() fmt.Printf("struct has %d fields ", num) numOfMethod := val.NumMethod() fmt.Printf("struct has %d methods ", numOfMethod) } func main() { var a Student a = Student{ Name: "stu01", Age: 18, Score: 92.8, } TestStruct(a) fmt.Println(a) }
反射练习
package main //通过反射动态修改变量的值 import ( "fmt" "reflect" ) type NotKnownType struct { s1 string s2 string s3 string } //定义一个String方法 func (n NotKnownType) String() string { return n.s1 + "-" + n.s2 + "-" + n.s3 } var secret interface{} = NotKnownType{"Ada", "Go", "Oberon"} func main() { value := reflect.ValueOf(secret) //<main.NotKnownType Value> typ := reflect.TypeOf(secret) //main.NotKnownType fmt.Println(typ) knd := value.Kind() //struct fmt.Println(knd) for i := 0; i < value.NumField(); i++ { fmt.Printf("Field %d:%v ", i, value.Field(i)) } results := value.Method(0).Call(nil) fmt.Println(results)//[Ada-Go-Oberon] }
通过反射修改结构体
package main import ( "fmt" "reflect" ) type T struct { A int B string } func main() { t := T{23, "skidoo"} s := reflect.ValueOf(&t).Elem() typeOfT := s.Type() for i := 0; i < s.NumField(); i++ { f := s.Field(i) fmt.Printf("%d:%s %s=%v ", i, typeOfT.Field(i).Name, f.Type(), f.Interface()) } s.Field(0).SetInt(77) s.Field(1).SetString("Sunset Strip") fmt.Println("t is now", t) }
Golang之实现一个负载均衡算法(随机,轮询)
代码记录
程序结构目录
--------程序包
package balance type Balancer interface { DoBalance([]*Instance, ...string) (*Instance, error) }
package balance import ( "strconv" ) type Instance struct { host string port int } func NewInstance(host string, port int) *Instance { return &Instance{ host: host, port: port, } } //定义Instance结构体的方法GetHost() func (p *Instance) GetHost() string { return p.host } //定义方法GetPort() func (p *Instance) GetPort() int { return p.port } func (p *Instance) String() string { return p.host + ":" + strconv.Itoa(p.port) }
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 balancer ", name) inst, err = balancer.DoBalance(insts) return }
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 }
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 }
------入口
package main import ( "fmt" "go_dev/day7/example/example1/balance" "math/rand" "os" "time" ) 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("do balance err:", err) fmt.Fprintf(os.Stdout, "do balance err ") continue } fmt.Println(inst) time.Sleep(time.Second) } }
package main import ( "fmt" "go_dev/day7/example/example1/balance" "hash/crc32" "math/rand" ) type HashBalance struct { Name string Age int } 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 { 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 }