1 指针
package main
//指针:指针是一种存储 变量内存地址的 变量
//1 取一个变量的地址:& 取地址符号
//2 如果在类型前面加*,表示指向这个类型的指针
//3 在指针变量前加*,表示解引用(反解),通过地址拿到值
func main() {
//1 指针的定义
//var b int=156
////把b的内存地址赋值给a这个指针
//var a *int=&b
////var c *string =&b //int类型指针是不能赋值给字符串类型的指针
////a:=&b
//fmt.Println(a)
//2 指针的零值(nil)
//var b *int
//fmt.Println(b)
//3 指针的解引用(拿到地址指向的值)
//var b=156
//a:=&b
//
//fmt.Println(a)
////指针a指向的值:解引用(反解)
//fmt.Println(*a)
//4 向函数传递指针参数
//var b =156
//fmt.Println(b)
//test(&b)
//fmt.Println(b)
//5 不要向函数传递数组的指针,而应该使用切片
//var a [4]int=[4]int{3,4,5}
// ////写一个函数,传入数组,该掉原来的数组
// //fmt.Println(a)
// //test(&a)
// ////fmt.Println(a)
// ////向函数传递切片
// //test1(a[:])
// //fmt.Println(a)
//6 Go 不支持指针运算
//var b [3]int=[3]int{1,2,3}
//a:=&b
//不允许指针运算
//fmt.Println(*(a++))
//7 指向指针的指针
//var b int=156
//var a *int=&b
//var c **int
//c=&a
//var d ***int
//d=&c
//fmt.Println(d)
//fmt.Println(*d)
//fmt.Println(**d)
//fmt.Println(***d)
//6 数组指针和指针数组
// 数组指针:指向数组导入指针
//var a [3]int=[3]int{1,2,3}
//var b *[3]int=&a
//fmt.Println(b)
// 指针数组:数组里面放指针
//var x,y,z=12,13,14
//var b [3]*int = [3]*int{&x,&y,&z}
//fmt.Println(b)
}
//func test1(x []int) {
// x[0]=100
// fmt.Println(x)
//}
//func test(x *[4]int) {
// //x[0]=100 //支持指针直接操作(内部处理的),自动反解,自动解引用
// (*x)[1]=100 //正统写法
// fmt.Println(x) //x是个指向数组的指针,地址 打印出:&[3 100 5]
// fmt.Println(*x)
//}
//func test(b *int) {
// //解引用,然后操作 b是一个指针
// *b+=10
// fmt.Println(*b)
//}
2 结构体
package main
//结构体取代类(go语言中的结构体,类似于面向对象语言中的类)
// go中的面向对象:继承,封装,多态
//结构体:是一系列属性的集合 python中的类:一系列属性和方法的集合
//1 定义一个结构体
/*
type 结构体名字 struct {
属性 类型
属性 类型
}
*/
//大小写表示公有和私有
type Person struct {
name string
age int
sex int
}
// 匿名字段(字段没有名字)
type Person2 struct {
string //姓名
int //年龄
}
//结构体嵌套
//type Hobby struct {
// id int
// name string
//}
//type Person3 struct {
// name string
// age int
// sex int
// hobby Hobby
//}
//字段提升
type Hobby struct {
id int
hobbyName string
}
type Person3 struct {
name string
age int
sex int
Hobby
}
func main() {
//2 结构体使用
//var p Person=Person{} //相当于实例化得到一个对象
////p:=Person{} //相当于实例化得到一个对象
//fmt.Println(p)
//fmt.Println(p.name)
//3 结构体的零值 //值类型,零值是属性的零值
//var p Person
//p.name="lqz"
//fmt.Println(p)
//4 定义并初始化(传入属性)
//4.1 按位置传(顺序不能变,有几个值就要传几个值)
//var p Person=Person{"lqz",18,1}
//4.2 按关键字传(位置可以乱,可以少传)
//var p Person=Person{sex:1,age:18}
//fmt.Println(p)
//fmt.Println(p.name)
//5 创建匿名结构体(没有名字也没有type关键字,定义再函数内部)
//只使用一次,把一堆属性放到一个变量中
// a:=struct {
// name string
// age int
// sex int
// }{age:18}
// //var name="lqz"
// //var age=19
// //var sex=1
// //name="lqz"
// fmt.Println(a.age)
//6结构体的指针
//var p Person=Person{sex:1,age:18}
//var p1 *Person=&Person{sex:1,age:18}
//var p1 *Person
//fmt.Println(p1)
//7 匿名字段(字段没有名字)(做变量提升,提升字段:面向对象中的继承)
//7.1 按位置
//var p Person2=Person2{"lqz",18}
//7.2 按关键字(类型就是关键字)
//var p Person2=Person2{int:18,string:"lqz"}
//fmt.Println(p)
//8 嵌套结构体(结构体中套结构体)
//8.1按位置
//var p Person3=Person3{"lqz",18,1,Hobby{1,"篮球"}}
//8.2 按关键字
//var p Person3=Person3{name:"lqz",hobby:Hobby{}}
////把hobby id设置成2,name设置成篮球
//p.hobby.name="篮球"
//p.hobby.id=2
//fmt.Println(p)
//9 提升字段(只把不重复的字段提升)
//9.1按位置
//var p Person3=Person3{"lqz",18,1,Hobby{1,"篮球"}}
//9.2 按关键字(面向对象的继承)
//var p Person3=Person3{name:"lqz",Hobby:Hobby{}}
//p.hobbyName="篮球"
//p.id=2
//p.Hobby.id=3
//fmt.Println(p)
//go中通过匿名字段和结构体嵌套实现面向对象的继承
//10 导出结构体(大小写)和字段(大小写)
//11 结构体想等性:
//结构体是值类型。
//如果它的每一个字段都是可比较的,则该结构体也是可比较的。 如果两个结构体变量的对应字段相等,则这两个变量也是相等的
//如果结构体包含不可比较的字段,则结构体变量也不可比较。
}
3 方法
package main
import "fmt"
//方法: python:什么是方法(绑定给对象,类,自动传值),什么是函数?
//方法是绑定给结构体的:结构体只有属性+方法---》类
//func 这个关键字和 方法名中间 加入了一个特殊的接收器类型
//func (t Type) methodName(parameter list) {
//}
//1 定义方法
//定义一个结构体
type Person4 struct {
name string
age int
sex int
}
//给结构体绑定方法(printName)
func (p Person4)printName() {
fmt.Println(p.name)
}
//普通函数
func printName(p Person4) {
fmt.Println(p.name)
}
//3 指针接收器与值接收器
func (p Person4)changeName(name string) {
p.name=name
fmt.Println(p)
}
//指针类型接收器的修改年龄
func (p *Person4)changeAge(age int) {
//(*p).age=age //正统的想法
p.age=age //go支持的
fmt.Println(p)
}
func main() {
//2 使用方法
//p:=Person4{"lqz",18,1}
////自动传值
//p.printName()
////为什么我们已经有函数了还需要方法呢?
//printName(p)
//3 值接收器和指针接收器
//值接收器,不会修改原来的,指针接收器才会修改原来的
//p:=Person4{"lqz",18,1}
//(&p).changeName("egon")
//(&p).changeAge(100)
//fmt.Println(p)
// 不管是值类型接收器还是指针类型接收器,都可以用值和指针来调用
//4 那么什么时候使用指针接收器,什么时候使用值接收器
//指针接收器也可以被使用在如下场景:当拷贝一个结构体的代价过于昂贵时
//5 匿名字段的方法
}
package main
import "fmt"
//匿名字段的方法
type Hobby1 struct {
id int
hobbyName string
}
type Person5 struct {
name string
age int
sex int
Hobby1 //匿名字段
}
//Hobby1的绑定方法
func (h Hobby1)printName() {
fmt.Println(h.hobbyName)
}
//Person5的绑定方法
func (p Person5)printName() {
fmt.Println(p.name)
}
func main() {
//5 匿名字段的方法,匿名字段的方法也提升
//p:=Person5{}
////方法也提升
//p.hobbyName="篮球"
////p.printName() //继承,子类没有printName,就会调用父类的printName方法
//p.printName()
////就要调用父类的printName(面向对象中的super)
//p.Hobby1.printName()
//6 在方法中使用值接收器 与 在函数中使用值参数
//指针和值都可以来调用, 只能传值
//7 在方法中使用指针接收器 与 在函数中使用指针参数
// 指针和值都可以来调用 只能传递指针
//8 在非结构体上的方法(向给int类型绑定个add方法可以吗?)
//var i int =10
//i.add()
var i Myint=10
i.add()
i.add()
i.add()
i.add()
fmt.Println(i)
}
//给传统数据类型重命名,然后绑定方法
type Myint int //把int类型重命名为Myint
func (i *Myint)add() {
(*i)=(*i)+1
}
4 接口
package main
import "fmt"
// 接口:接口定义一个对象的行为,一系列方法的集合
//abc规范了子类应该有哪些行为,用abc模块来规范子类的行为
//django中:父类 写了一个方法,没有代码,只有个raise ,子类继承,但是没有重写该方法,一调用就报错
//1 定义一个鸭子接口(run方法 speak方法)
type DuckInterface interface {
run()
speak()
}
//写一个唐老鸭结构体,实现该接口
type TDuck struct {
name string
age int
wife string
}
//实现接口(只要结构体绑定了接口中的所有方法,就叫做:结构体实现了该接口)
func (t TDuck)run() {
fmt.Println("我是唐老鸭,我的名字叫",t.name,"我会人走路")
}
func (t TDuck)speak() {
fmt.Println("我是唐老鸭,我的名字叫",t.name,"我说人话")
}
//写一个肉鸭结构体,实现该接口
type RDuck struct {
name string
age int
}
//实现接口(只要结构体绑定了接口中的所有方法,就叫做:结构体实现了该接口)
func (t RDuck)run() {
fmt.Println("我是肉鸭,我的名字叫",t.name,"我会人走路")
}
func (t RDuck)speak() {
fmt.Println("我是肉鸭,我的名字叫",t.name,"我说人话")
}
func main() {
//var t TDuck=TDuck{"嘤嘤怪",18,"刘亦菲"}
//var r RDuck=RDuck{"建哥",18}
////唐老鸭的run方法
//t.run()
////肉鸭的run方法
//r.run()
//定义一个鸭子接口类型(因为肉鸭和唐老鸭都实现了鸭子接口,所有可以把这俩对象赋值给鸭子接口)
var i1 DuckInterface
i1=TDuck{"嘤嘤怪",18,"刘亦菲"}
var i2 DuckInterface
i2=RDuck{"建哥",18}
//唐老鸭的run方法
i1.run()
//肉鸭的run方法
i2.run()
}
//func run(i DuckInterface) {
// i.run()
//}
////a 可以是字典,字符串,列表
//len(a) a.__len__()
////len(str)