[13 Go语言基础-指针,结构体,方法]

[12 Go语言基础-指针,结构体,方法]

1 指针

package main

import "fmt"

// 指针:指针是一种存储变量内存地址的变量
/*
& 放在变量前,表示取该变量的地址
* 放在指针变量前,表示解引用(把变量的地址,反解成具体的值)
* 放在类型前,表示指向这个类型的指针(变量定义的时候使用)
 */
func main() {
	// 1 指针的使用
	//b:=156
	//fmt.Println(b)
	//a:=&b  // 取变量b的地址,赋值给a
	//fmt.Println(a)
	//fmt.Println(*a)
	////fmt.Println(*b)  // 不对
	//

	//var a *int  // 指针类型---》指向int类型的指针
	//a=&b

	// 2 小案例
	//b:=156
	//var a *int=&b
	//fmt.Println(b)
	//fmt.Println(a)
	//// a也是个变量,取a的地址
	////c:=&a   // c的类型是?
	//var c **int=&a   // c的类型是?
	//fmt.Println(c)
	//var d ***int = &c
	//fmt.Println(d)
	//// 解引用
	//fmt.Println(*d)
	//fmt.Println(**d)
	//fmt.Println(***d)

	// 3 指针的0值
	//var a *string
	//fmt.Println(a)  // <nil> ,引用类型

	// 4 向函数传递指针参数,引用类型,会影响原来的
	//var a int=156
	//var b *int =&a
	//test(b)
	//fmt.Println(b)
	//fmt.Println(a)

	//5 不要向函数传递数组的指针,而应该使用切片
	//var a =[3]int{3,2,1}
	//var a =&[3]int{3,2,1}
	//var a *[3]int=&[3]int{3,2,1}
	//var a =&[3]int{3,2,1}
	//fmt.Println(a) // 理论上打印出地址,但是go给你做成了&[3 2 1]
	//test2(a)
	//var a =[4]int{3,2,1}
	//test3(a[:])
	//fmt.Println(a)
	// 如果传递数组的指针,函数的参数每次都要改变,要重写函数,如果传切片,就不需要改了


	//6 Go 不支持指针运算
	//b := [...]int{109, 110, 111}
	//p := &b
	////p++
	//fmt.Println((*p)[2])

	// 7 指针数组和数组指针
	//数组指针指的是:指向数组的指针var a *[3]int =&[3]int{3,2,1}
	//var x *[3]int =&[3]int{3,2,1}
	//fmt.Println(x)
	////指针数组:数组里放了一堆指针
	//a:=10
	//b:=10
	//c:=10
	//var d [3]*int=[3]*int{&a,&b,&c}
	//fmt.Println(d)






}
func test(b *int)  {
	fmt.Println(b)
	fmt.Println(*b)
	// 改值
	*b=*b+100
	fmt.Println(*b)
}

func test2(a *[3]int)  {
	fmt.Println(a)
	//(*a)[0]=999
	a[0]=999  // go语言给处理了,正常来讲需要解引用(成数组),再取值,但是支持不用解引用,直接取
	fmt.Println(*a)
}

func test3(a []int)  {
	fmt.Println(a)
	a[0]=999
	fmt.Println(a)

}

2 结构体

package main

// 结构体:go中的面向对象
// 结构体是用户定义的类型,表示若干个字段(Field)的集合。
//有时应该把数据整合在一起,而不是让这些数据没有联系。这种情况下可以使用结构体

// 定义结构体
/*
 type关键字  结构体名字 struct关键字{
	字段一 字段类型
	字段二 字段类型
}

*/
//type Person struct {
//	name   string
//	age    uint8
//	gender string
//}
//// 定义一个animal结构体
//type Animal struct {
//	string   // 动物的名字   字段没有名字
//	uint8    //动物的年龄
//	gender string
//}

// 结构体嵌套
//type Hobby struct {
//	name string
//	HobbyId  int
//
//}
//type Person struct {
//	name   string
//	age    uint8
//	gender string
//	//hobby Hobby
//	Hobby
//}

func main() {
	//1 使用结构体
	//var p Person  // 只定义,没有赋初值
	//fmt.Println(p)

	//2 字段取值,赋值
	//fmt.Println(p.name)
	//p.gender="男"
	//p.age=19
	//p.name="lqz"
	//fmt.Println(p.name)

	// 3 定义同时初始化
	//var p Person = Person{"lqz",18,"男"}  // 按位置初始化
	//var p Person = Person{"lqz",18,}  // 报错

	//var p Person = Person{name:"lqz",age:19,gender:"男"}  // 按关键字初始化
	//var p Person = Person{age:19,gender:"男"}  // 按关键字初始化
	//var p = Person{gender: "男", age: 18} // 按关键字初始化,可以少传,可以打乱顺序
	//fmt.Println(p)

	//4 结构体是值类型,当参数传递,修改不会影响原来的
	//var p = Person{gender: "男", age: 18}
	//test4(p)
	//fmt.Println(p)

	// 5 匿名结构体(没有名字,没有type关键字)
	//a:=struct {
	//	name string
	//	age int
	//}{"lqz",19}
	//a := struct {
	//	name string
	//	age  int
	//}{name: "lqz"}
	//fmt.Println(a)
	// 匿名结构体有什么用?如果不使用匿名结构体,需要每一个变量都去使用,如果使用了,把多个变量放到匿名结构体中,拿到匿名结构体,就相当于拿到了很多变量



	// 6 结构体指针
	//var p =Person{"lqz",19,"男"}
	//var p1 *Person=&p
	//var p1 *Person= &Person{"lqz",19,"男"}
	//fmt.Println(p1)
	//test6(p1)
	//fmt.Println(p1)

	// 7 匿名字段  (字段提升)
	// 匿名字段,类型名就是字段名,字段名不能重复
	//var animal Animal=Animal{"狗子",2} // 按位置
	//var animal Animal=Animal{string:"狗子",uint8:2} // 按关键字
	//fmt.Println(animal.string)
	//animal.string="猫子"
	//fmt.Println(animal)

	// 8 嵌套结构体
	//var p =Person{name:"lqz",hobby:Hobby{"篮球",1} }
	////var p Person
	//fmt.Println(p)
	//fmt.Println(p.hobby.HobbyId)

	// 9 结构体嵌套加匿名字段(字段提升)类似于面向对象的继承
	//var p =Person{name:"lqz",Hobby:Hobby{"篮球",1} }
	//fmt.Println(p.Hobby.HobbyName)
	//// 字段提升
	//fmt.Println(p.HobbyId)
	//fmt.Println(p.HobbyName)

	// 如果Hobby结构体中有name字段,Person中也有name字段
	//var p =Person{name:"lqz",Hobby:Hobby{"篮球",1} }
	//fmt.Println(p.name)
	//fmt.Println(p.Hobby.name)

	// 10 结构体导出和字段导出
	//var p package1.Person=package1.Person{Name: "lqz"}
	//fmt.Println(p)
	//fmt.Println(p.Name)
	//fmt.Println()

	// 11 结构体相等性
	//如果结构体包含不可比较的字段,则结构体变量也不可比较
	//var p =package1.Person{Name: "lqz"}
	//var p1 =package1.Person{Name: "lqz"}
	//fmt.Println(p==p1)


}

//func test4(p Person) {
//	fmt.Println(p.name)
//	p.name = "egon"
//	fmt.Println(p)
//}

//func test5() (struct {
//	name string
//	age  int
//}) {
//	a := struct {
//		name string
//		age  int
//	}{"lqz", 19}
//	return a
//}

//func test6(p *Person)  {
//	fmt.Println((*p).name)
//	(*p).name="egon"
//
//}

3 方法

package main

import "fmt"

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

// 定义一个结构体
type Person struct {
	name string
	age int
	Hobby
}
// 定义一个方法,绑定给Person结构体
func (self Person) printName()  {   // 值类型接收器
	fmt.Println(self.name)
}
func (self Person)ChangeName(name string)  {  // 指针类型接收器
	//(*self).name=name
	self.name=name
	fmt.Println(self)
}
func (self *Person)ChangeName2(name string)  {  // 指针类型接收器
	//(*self).name=name
	self.name=name
	fmt.Println(self)
}

type Hobby struct {
	name string
	id int
}

//func (self Hobby)printHobbyName()  {
func (self Hobby)printName()  {
	fmt.Println(self.name)

}



// 非结构体上的方法
//func (self uint)add()  {
//	self++
//}

// 类型重命名
type MyInt int
func (self *MyInt)add()  {
	(*self)++
}
func main() {

	//var p =Person{"lqz",19}
	//p.PrintName()
	//var p1 =Person{"egon",19}
	//p1.PrintName()
	//p1.ChangeName("刘亦菲")
	//fmt.Println(p1)
	//var p1 =&Person{"egon",19}
	//p1.PrintName()
	//p1.ChangeName("刘亦菲")
	//fmt.Println(p1)

	// 什么时候使用指针接收器,什么时候使用值接收器

	// 不管是值类型接收器,还是指针类型接收器,都可以使用值来调用,指针也可以调用
	// 如果要修改掉原来的值,必须用指针类型接收器

	// 有了函数,为什么要方法
	//var p1 =Person{"egon",19}
	////ChangeName(p1,"刘亦菲")
	////p1.ChangeName("李亦非")
	////fmt.Println(p1)
	//
	//ChangeName2(&p1,"刘亦菲")
	//p1.ChangeName2("李亦非")
	//fmt.Println(p1)

	//在方法中使用值接收器 与 在函数中使用值参数
	//在方法中使用指针接收器 与 在函数中使用指针参数
	// 不管是值类型接收器,还是指针类型接收器,都可以使用值来调用,指针也可以调用
	// 如果是普通函数,是什么类型参数,就必须传什么类型参数





	// 方法提升
	//var p Person
	////p.printHobbyName()
	//p.Hobby.printName()

	// 非结构体上的方法
	//var i MyInt=10
	//fmt.Println(i)
	//i.add()
	//i.add()
	//i.add()
	//i.add()
	//fmt.Println(i)



}

// 定义了一个函数
func ChangeName(self Person,name string)  {
	self.name=name
	fmt.Println(self)
}

func ChangeName2(self *Person,name string)  {
	self.name=name
	fmt.Println(self)
}

posted @ 2021-08-26 19:20  刘较瘦丫  阅读(53)  评论(0)    收藏  举报