• 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
  • 相关阅读:
    Web 日志分析过程
    nginx系列之九:lua服务
    Linux网络编程之IO模型
    从URL输入到页面展现到底发生什么
    CentOS 日常运维十大技能
    以MySQL为例,详解数据库索引原理(1)
    Elasticsearch的特点以及应用场景
    Ubuntu1804编译安装LNMP
    golang 高级
    Centos7 安装 Redis
  • 原文地址:https://www.cnblogs.com/bubu99/p/12521698.html
Copyright © 2020-2023  润新知