Go 面向对象

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
    }
}
Link.go
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()
}
main.go

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)
}
val.Elem().SetInt()

 用反射操作结构体

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)
}
balance.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,
    }
}

//定义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)
}
instance.go
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
}
mgr.go
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
}
random.go
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
}
roundrobin.go

------入口

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)
    }
}
main.go
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
}
hash.go
原文地址:https://www.cnblogs.com/bubu99/p/12521698.html