zoukankan      html  css  js  c++  java
  • go的指针,结构体,方法,以及接口

    1 指针

    //指针:指针是一种存储变量内存地址(Memory Address)的变量。
    package main
    
    func main() {
    	//1 定义指针
    	// 指向int类型的指针(指向什么类型指针,就是在什么类型前加星号)
    	//var a *int
    
    	//2 指针的零值
    	//fmt.Println(a)
    
    	//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不支持指针运算
    	//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,它不是引用类型,是值类型
    	//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)
    	////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)
    
    
    }
    
    
    // 链式调用
    

    4 接口入门

    //接口
    //接口定义一个对象的行为。接口只指定了对象应该做什么,至于如何实现这个行为(即实现细节),则由对象本身去确定。
    
    //django框架频率组件 Base--》根据ip过滤的,自己写频率组件,必须继承base,如果没有实现Base中的所有方法,就报错
    //abc模块,强制要求子类必须重写某些方法
    package main
    
    
    //1 定义接口(接口是一系列行为的集合:一系列方法的集合)
    
    type Duck interface {
    	run()
    	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,nane):
        self.name=name
        return self
    	def chang_age(self,age):
        self.age=age
        return self
    
  • 相关阅读:
    SSH、SCP和SFTP 解析(转)
    SQL Server数据库partition by 与ROW_NUMBER()函数使用详解 (转载)
    Git版本控制与工作流详解(转)
    IQueryable,IEnumberable,.AsEnumerable() 和 .AsQueryable() (转载)
    ASP.NET 中Http处理流程与 HttpModule,HttpHandler学习之初步认知
    xml Node 是否存在
    MVC-前台调用后台action 传递upload file 参数问题
    ResXResourceWriter 与ResourceWriter
    "= ="与 equals 的区别 摘录
    jpg文件格式分析
  • 原文地址:https://www.cnblogs.com/yafeng666/p/12824691.html
Copyright © 2011-2022 走看看