当前位置:首页 > Python教程 > python技巧

go语言4 指针, 结构体, 方法, 接口, python链式调用

1 指针

            //
            指针:指针是一种存储变量内存地址(Memory Address)的变量。
            package main

func main() {
    
            //
            1 定义指针
    
            //
             指向int类型的指针(指向什么类型指针,就是在什么类型前加星号)
    
            //
            var a *int

    
            //
            2 指针的零值     nil 引用类型
    
            //
            fmt.Println(a)     
            //
             <nil>

    
            //
            3 使用指针
    
            //
            var a *int
    
            //
            var b int=100
            ///
            /a指针指向b  (取谁的地址,就是在谁前面加一个&)
            //
            a=&b
    
            //
            fmt.Println(a)
    
            //

            ///
            /4 了解(骚操作)
    
            ///
            /var c =&a
            //
            var c **int=&a
    
            //
            var d ***int =&c
    
            //
            fmt.Println(d)
    
            //

            ///
            /5 解引用(把指针反解成值)  (在指针变量前加*,表示解引用)
            //
            fmt.Println(*a)
    
            //
            fmt.Println(***d)

    
            //
            6 向函数传递指针参数
    
            //
            var a int =100
            ///
            /在函数中把a的值改成101
            //
            fmt.Println(a)
    
            //
            test2(&a)
    
            //
            fmt.Println(a)

    
            //
            7 不要向函数传递数组的指针,而应该使用切片
    
            //
            var a [4]int  = [4]int{1,2,3}
    
            //
            fmt.Println(a)
            ///
            /test3(&a)
            //
            test4(a[:])
    
            //
            fmt.Println(a)

    
            //
            8 go不支持指针运算  (其实支持,用unsafe包,不安全)
    
            //
            var b int=100
    
            //
            var a *int=&b
    
            //
            //
            a++

    
            //
            9 指针数组和数组指针
    
            //
            指针数组---->数组里面放指针
    
            //
            var a int =10
    
            //
            var b int =20
    
            //
            var c int =30
    
            //
            var d [3]*int=[3]*int{&a,&b,&c}
    
            //
            fmt.Println(d)

    
            //
            数组指针----》指向数组的指针
    
            //
            var a [3]int=[3]int{1,3,4}
    
            //
            var b *[3]int=&a
    
            //
            fmt.Println(b)
            
}

            //
            func test2(a *int)  {

            //
            //
            解引用然后,自增1

            //
            //
            *a++

            //
                *a=*a+100

            //
                fmt.Println(*a)

            //
            }


            //
            func test3(a *[3]int)  {

            //
            //
            (*a)[0]=999

            //
            //
            神奇的一幕(go语言处理了一层,如果是数组的指针,直接像操作数组操作就可以了)

            //
                a[0]=999

            //
            //
            a是地址,如果是数组的地址,会显示成 &[999 2 3]

            //
                fmt.Println(a)

            //
            }

            //
            //
            func test4(a []int)  {

            //
                a[0]=999

            //
                fmt.Println(a)

            //
            }
        

 

2 结构体

            //
            结构体,go语言中的面向对象

            //
            结构体是用户定义的类型,表示若干个字段(Field)的集合

            //
            类比面向对象中的类,只有属性,没有方法
            

package main

import 
            "
            fmt
            "
            //
            1 定义一个人类结构体(名字,年龄,性别属性)

            //
             type关键字 结构体名字 struct关键字 {一个一个的字段}

            //
            type Person struct {

            //
                name string

            //
                age int

            //
                sex string

            //
            }


            //
            7 匿名字段(字段没有名字,不允许有多个同类型的字段)

            //
            type Person struct {

            //
                 string

            //
                 int

            //
            //
            int

            //
                 sex string

            //
            //
            sex string

            //
            }


            //
            8 嵌套结构体(结构体套结构体)

            //
            不管是结构体名字还是字段名字,大写字母开头,表示导出字段,表示在外部包可以使用

            //
            面向对象封装(python __)

            //
            type Person struct {

            //
                Name string

            //
                Age int

            //
                Sex string

            //
                hobby Hobby

            //
            }

            //
            type Hobby struct {

            //
                HobbyId int

            //
                HobbyName string

            //
            }
            ///
            / 9 提升字段
            //
            type Person struct {

            //
                Name string

            //
                Age int

            //
                Sex string

            //
                Hobby

            //
            }

            //
            type Hobby struct {

            //
                HobbyId int

            //
                HobbyName string

            //
            }


            //
             10 字段冲突
type Person struct {
    Name string
    Age int
    Sex string
    Hobby
}
type Hobby struct {
    HobbyId int
    Name string
}
func main() {
    //2 使用结构体(结构体的零值,是属性的零值)不是nil,它不是引用类型,是值类型,故当参数是copy传递
    //var a Person
    //fmt.Println(a)

    //3 定义并初始化
    //var a Person=Person{}
    //var a Person=Person{name:"lqz",age:19,sex:"男"}
    //var a =Person{name:"lqz",age:19,sex:"男"}
    //a :=Person{name:"lqz",age:19,sex:"男"}
    //a :=Person{sex:"男",name:"lqz",age:19}
    //a :=Person{sex:"男",name:"lqz"}
    //按位置初始化(固定位置,并且都传)
    //a :=Person{"lqz",19,"男"}
    //fmt.Println(a)

    //4 使用结构体(通过 . 取值)
    //var a Person=Person{name:"lqz",age:19,sex:"男"}
    //fmt.Println(a.name)
    //a.name="egon"
    //fmt.Println(a)

    //5 匿名结构体(没有名字,没有type关键字,定义在函数内部)
    //什么情况下用?只使用一次,数据整合在一起
    //a:=struct {
    //    name string
    //    age int
    //    sex string
    //}{"lqz",19,"男"}
    //fmt.Println(a.name)

    //6 结构体的指针(因为结构体是值类型)
    //var a *Person=&Person{"lqz",19,"男"}
    //fmt.Println(a)    // &{lqz 19 男}  这是系统优化,为了好看////Go 语言允许我们在访问 字段时,可以使用 emp8.firstName 来代替显式的解引用 (*emp8).firstName//fmt.Println((*a).name)
    //fmt.Println(a.name)

    //7 匿名字段(字段没有名字)(有什么用?用来做字段提升,面向对象中的继承)
    //按位置实例化
    //a:=Person{"lqz",19}
    //按关键字实例化
    //a:=Person{int:19,string:"lqz"}
    //fmt.Println(a)
    //fmt.Println(a.string)
    //fmt.Println(a.int)

    //8 嵌套结构体(结构体套结构体)
    //按位置
    //var a Person  = Person{"lqz",19,"男",Hobby{1,"篮球"}}
    //按关键字
    //var a Person  = Person{hobby:Hobby{HobbyName:"篮球"}}
    //fmt.Println(a)
    //fmt.Println(a.hobby.HobbyName)

    //9 提升字段
    //a:=Person{Hobby:Hobby{1,"篮球"}}
    //fmt.Println(a.HobbyName)
    //fmt.Println(a.HobbyId)
    //fmt.Println(a.Hobby.HobbyId)
    //相当于Person继承了Hobby,
    //a.父类的属性:a.HobbyId
    //super().父类属性:a.Hobby.HobbyId

    //10 字段重复(父类跟子类是属性冲突)
    //a:=Person{Hobby:Hobby{1,"篮球"}}
    //fmt.Println(a.Name) // 用了Person的Name
    //fmt.Println(a.Hobby.Name) // 相当于 super().属性

    //11 导出结构体和字段 (用大写字母开头,表示外部包可以使用)

    //12 结构体相等性(了解一下),值类型,支持比较
    //结构体是值类型。如果它的每一个字段都是可比较的,则该结构体也是可比较的。 如果两个结构体变量的对应字段相等,则这两个变量也是相等的
    //如果结构体包含不可比较的字段(切片,map。。。引用类型),则结构体变量也不可比较

    //13 结构体当参数传递
    a:=Person{Hobby:Hobby{1,"篮球"}}
    fmt.Println(a)
    //test5(a)  // 传递的是值,就不会改变原来的
    test6(&a)
    fmt.Println(a)
}
func test5(a Person){
    a.Name="xxx"
    fmt.Println(a)
}
func test6(a *Person){
    //a.Name="xxx"    // 用这句话也行
    (*a).Name="xxx"
    fmt.Println(a)
}

 

3 方法

            //
             结构体+方法实现面向对象中的类


            //
            方法


            //
            方法其实就是一个函数,在 func 这个关键字和方法名中间加入了一个特殊的接收器类型。接收器可以是结构体类型或者是非结构体类型。接收器是可以在方法的内部访问的


            //
            python中什么是方法,什么是函数?

            //
            函数就是定义的普通函数

            //
            方法是面向对象中的概念,对象绑定方法,类的绑定方法,可以自动传值,

            //
            类中不加任何装饰器定义的函数,是对象的绑定方法,对象来调用,可以自动传值,类也可以来掉,如果类来调用,他就是普通函数,有几个值就传几个值

            //
            类的绑定方法,类来调用,会把类自动传入
            
package main

import 
            "
            fmt
            "
            //
            1 定义方法

            //
            定义一个结构体

            //
            type Person1 struct {

            //
                name string

            //
                age int

            //
                sex string

            //
            }
            ///
            /给结构体绑定方法
            //
            func (p Person1)PrintName()  {

            //
                fmt.Println(p.name)

            //
            }

            //

            ///
            /绑定一个修改名字的方法
            //
            func (p Person1)ChangeName(name string)  {

            //
                p.name=name

            //
                fmt.Println("--------",p)

            //
            }

            //

            ///
            /指针类型接收器,修改age的方法
            //
            func (p *Person1)ChangeAge(age int)  {

            //
                p.age=age

            //
            //
            (*p).age=age   
            //
            正常操作

            //
                fmt.Println("--------",p)

            //
            }

            //
            //

            ///
            /普通函数
            //
            func PrintName(p Person1)  {

            //
                fmt.Println(p.name)

            //
            }



            //
            5 匿名字段的方法(重点)

            //
            type Hobby1 struct {

            //
                id int

            //
                hobbyName string

            //
            }

            //
            type Person1 struct {

            //
                name string

            //
                age int

            //
                sex string

            //
                Hobby1  
            //
            匿名字段

            //
            }
            ///
            /给Hobby1,绑定一个打印名字的方法
            //
            func (h Hobby1)printName()()  {

            //
                fmt.Println(h.hobbyName)

            //
            }

            //

            ///
            /给Person1绑定一个方法(相当于重写了父类方法)
            //
            func (p Person1)printName()()  {

            //
            //
            即打印hobby的名字,又打印人的名字

            //
            //
            fmt.Println(p.hobbyName)

            //
            //
            fmt.Println(p.Hobby1.hobbyName)

            //
            //
            直接调用Hobby1的方法(调用父类方法,相当于 super().方法名)

            //
                p.Hobby1.printName()

            //
                fmt.Println(p.name)

            //
            }
            ///
            /6 在方法中使用值接收器 与 在函数中使用值参数
            //
            type Person1 struct {

            //
                name string

            //
                age int

            //
                sex string

            //
            }
            ///
            /方法中使用值接收器
            //
            func (p Person1)printName()  {

            //
                fmt.Println(p.name)

            //
            }
            ///
            /在函数中使用值参数
            //
            func printName(p Person1)  {

            //
                fmt.Println(p.name)

            //
            }



            //
            7 在方法中使用指针接收器 与 在函数中使用指针参数

            //
            type Person1 struct {

            //
                name string

            //
                age int

            //
                sex string

            //
            }
            ///
            /在方法中使用指针接收器
            //
            func (p *Person1)printName()  {

            //
                fmt.Println(p.name)

            //
            }
            ///
            /在函数中使用指针参数
            //
            func printName(p *Person1)  {

            //
                fmt.Println(p.name)

            //
            }



            //
            8 在非结构体上的方法

            //
             不可以,只能采取下面的自定义类型,曲线救国

            //
            func (i int)add()  {

            //
                i=i+i

            //
            }


            //
            自己定义的类型,可以绑定方法
type myInt int//给自己定义的类型绑定方法
func (i *myInt)add()  {
    (*i)++
    fmt.Println(*i)
}

func main() {
    // 1 方法的定义和使用
    //p:=Person1{"lqz",19,"男"}
    //p.PrintName()

    //PrintName(p)  // 需要手动来传,跟结构体没有必然联系

    //2 为什么我们已经有函数了还需要方法呢

    //3 值接收器和指针接收器
    //p:=Person1{"lqz",19,"男"}
    //p.ChangeName("egon")  // 值接收器,改新的,不会影响原来的,不会影响当前的p对象
    //fmt.Println(p)
    //调用指针类型接收器的方法
    //p.ChangeAge(100)  //指针类型接收器,会影响原来的,会影响当前的p对象
    //fmt.Println(p)

    //4 那么什么时候使用指针接收器,什么时候使用值接收器?
    //用指针接收器的情况
    //1 方法内部的改变,影响调用者
    //2 当拷贝一个结构体的代价过于昂贵时 ,就用指针接收器
    //其他情况,值接收器和指针接收器都可以

    //5 匿名字段的方法(重点)
    //p:=Person1{"lqz",19,"男",Hobby1{1,"篮球"}}////匿名字段,属性可以提升
    ////匿名字段,方法也提升
    ////p.printName()  // 也提升了  子类对象调用父类中的方法,子类中没有,就是调用父类的--》 对象.方法名
    ////p.Hobby1.printName() // 正常操作 直接指名道姓的调用父类中的方法---》 super().方法名//
////子类中重写了父类的方法(嵌套结构体中有重名的方法)//p.printName()

    //6  在方法中使用值接收器 与 在函数中使用值参数
    //p:=Person1{"lqz",19,"男"}
    //p.printName()
    //printName(p)
    //神奇的一幕
    //p 是指向结构体的指针
    //p:=&Person1{"lqz",19,"男"}
    //p.printName()////printName(p)//printName(*p) //解引用

    //7  在方法中使用指针接收器 与 在函数中使用指针参数
    //p:=&Person1{"lqz",19,"男"}
    ////p.printName()
    ////printName(p)
    //相应的
    //p:=Person1{"lqz",19,"男"}
    //p.printName()////printName(p)//printName(&p)

    //不论值类型接收器还是指针类型接收器,都可以使用值来调,也可以使用指针来调

    //8 在非结构体上的方法
    //i:=10
    //i.add()var i myInt =10
    fmt.Println(i)
    i.add()
    i.add()
    i.add()
    i.add()
    i.add()
    fmt.Println(i)
    
// go 语言中没有集合,可以自己定制集合
}

 

4 接口入门

            //
            接口

            //
            接口定义一个对象的行为。接口只指定了对象应该做什么,至于如何实现这个行为(即实现细节),则由对象本身去确定。


            //
            django框架频率组件 Base--》根据ip过滤的,自己写频率组件,必须继承base,如果没有实现Base中的所有方法,就报错

            //
            abc模块,强制要求子类必须重写某些方法
            package main



            //
            1 定义接口(接口是一系列行为的集合:一系列方法的集合)
            
type Duck 
            interface
             {
    run()    
            //
             省略func    
                speak()
}

            //
            只要结构体绑定了接口中的所有方法,这个结构体就叫实现了Duck接口
type TDuck struct {
    name string
    age int
    wife string
}
//实现Duck接口(绑定接口中的所有方法)func (t TDuck)run()  {

}
func (t TDuck)speak()  {

}

 

补充

1 链式调用

            #
             对象.修改名字(lqz).修改年龄(10)
            
#
             一门语言如何实现链式调用
            class
             Person:
    
            def
             chang_name(self,name):
        self.name = name
        return self
    def chang_age(self, age):
        self.age = age
        return self

 

总结:

            //
            指针 结构体  方法


            //
            1 指针:(地址)
    -什么类型的指针,就是在类型前加 *
    -取什么变量的地址,就是在变量前加 &
    -通过指针得到值(解引用),在变量前加*
    
    -当参数传递,修改会影响原来的值
    -一般情况下,引用不需要再去地址了,取地址一般取值类型的地址
//2 结构体
    -面向对象当中的类,只有属性 ,没有方法(一系列属性的集合)
        type Person struct{ 一堆属性}
    -使用结构体:a:=Person{} 按位置,按关键字传参
    -取值: . 取值
    -结构体是值类型,默认是是属性的默认值
    -匿名结构体
    -匿名字段
    -结构体嵌套(变量提升)
    -结构体比较(如果结构体中有引用类型,不支持比较)
//3 方法(特殊的函数)
    -func关键字和函数名之间有个特殊类型接收器
        -func (a 结构体名字)方法名(参数)(返回值){}
    -绑定给结构体,结构体通过 . 方式来调用
    -值接收器和指针接收器(值接收器不会修改原来的,指针接收器会修改原来的)
    -不论值还是指针,都可以直接调用方法(值接收器类型,指针接收器类型)
    -匿名字段的方法(方法提升,类似于面向对象中的继承,多继承)
    -非结构体上绑定方法(自己定义的属性)
    


//go的指针,结构体,匿名结构体,匿名字段,信道,缓冲信道,方法,函数,接口,goroutine,闭包函数,匿名函数对xx有一定了解,能简单的在liunx上部署项目,熟悉bs4,requests,了解scrapy,能简单做爬虫
激进一些

 

原文:https://www.cnblogs.com/ludingchao/p/12774002.html


【说明】本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!

相关教程推荐

其他课程推荐