//指针:指针是一种存储变量内存地址(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) //}
//结构体,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) }
// 结构体+方法实现面向对象中的类 //方法 //方法其实就是一个函数,在 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 语言中没有集合,可以自己定制集合 }
//接口 //接口定义一个对象的行为。接口只指定了对象应该做什么,至于如何实现这个行为(即实现细节),则由对象本身去确定。 //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() { }
# 对象.修改名字(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,能简单做爬虫 激进一些