python转go学习笔记———面向对象

面向对象OOP
结构体Struct

go语言没有类,只有结构体,等同于类(class)

//定义一个结构体(类)
type Book struct {		//如果类首字母大写,表示其他包也能够访问
	Title string		//如果类属性首字母大写,表示该属性公有,否则为私有
	auth string			
}
//创建实例
func main() {
    // 方式一
    var bk1 Book = Book{title: "xixi",auth: "flandre"}
    // 方式二
	bk2 := Book{title: "haha",auth: "flandre"}
	// 方式三
	var bk3 *Book = new(Book)
	(*bk3).auth = "flandre"
    // 方式四
    var bk3 *Book = &Book{title: "heihei",auth: "flandre}
}

方式三四返回的都是结构体指针。但go也支持bk3.auth

type Point struct {
	x int
	y int
}

type Rect struct {
	leftUp,rightDown Point
}

func main()  {
	r1 := Rect{Point{1,2},Point{3,4}}
	// r1的四个点内存连续
	fmt.Printf("r1.leftUp.x地址 = %p r1.leftUp.y地址 = %p\n r1.rightDown.x地址 = %p r1.rightDown.y地址 = %p",
		&r1.leftUp.x,&r1.leftUp.y,&r1.rightDown.x,&r1.rightDown.y)
	//r1.leftUp.x地址 = 0xc000012200 r1.leftUp.y地址 = 0xc000012208
	//r1.rightDown.x地址 = 0xc000012210 r1.rightDown.y地址 = 0xc000012218
}

两个结构体之间相互转换,需要字段完全相同

type A struct {
	Num int
}
type B struct {
	Num int
}
func main()  {
	var a A
	var b B
	a = A(b)
	fmt.Println(a,b)
}

结构体进行type重新定义(相当于取别名),Golang认识是新的数据类型,但是相互可以强转

type Student struct {
	Name string
	Age int
}
type Stu Student

type integer int

func main()  {
	var stu1 Student
	var stu2 Stu
	stu2=Stu(stu1)
	fmt.Println(stu1,stu2)

	var i integer = 10
	var j int = 20
	j = int(i)
	fmt.Println(i,j)
}

结构体的每个字段上,可以写一个tag,该tag可以通过反射机制获取,使用场景多为序列化和反序列化

type Monster struct {
	Name string `json:"name"`		// tag `json:"name"`
	Age int	`json:"age"`
	Skill string `json:"skill"`
}

func main()  {
	monster := Monster{"翠花",20,"xixi"}

	jsonStr,err := json.Marshal(monster)
	if err != nil{
		fmt.Println("json处理错误")
	}									// tag前:{"Name":"翠花","Age":20,"Skill":"xixi"}
	fmt.Println("jsonStr:",string(jsonStr)) 
}										// tag后:{"name":"翠花","age":20,"skill":"xixi"}
方法
//方法声明
func (recevier type) methodName(参数列表) (返回值列表) {
    方法体
    return 返回值
}
type Person struct {
	Name string
}

func (p Person) speak() {
	fmt.Println(p.Name)
}
func main()  {
	var p Person
	p.Name = "flandre"
	p.speak()				// My name is flandre
}
  1. 结构体类型是值类型,遵守值类型的传递机制,是值拷贝传递方式
  2. 修改结构体变量的值,可以通过结构体指针的方式处理
  3. Golang中方法作用在指定的数据类型上,不光struct,int、float32也可以有方法
  4. 方法的访问范围控制规则和函数一样。方法名首字母小写,只能在本包访问,首字母大写可以在本包和其他包访问
  5. 如果一个变量实现了String()方法,那么fmt.Println默认会调用这个变量的String()输出。
type Person struct {
	Name string
	Age int
}
// Person实现方法String()
func (this *Person) String() string {
	str := fmt.Sprintf("Name=[%v],Age=[%v]",this.Name,this.Age)
	return str
}

func main()  {
	pp := Person{
		Name: "flandre",
		Age: 20,
	}
	fmt.Println(pp)			// {flandre 20}
    fmt.Println(&pp)		// Name=[flandre],Age=[20]
}

方法和函数的区别

  1. 调用方式不一样
    • 函数调用方式:函数名(实参列表)
    • 方法调用方式:变量.方法名(实参列表)
  2. 对于普通函数,接收者为值类型,不能将指针类型的数据直接传递,反之亦然
  3. 对于方法(struct),接收者为值类型时,可以直接用指针类型的变量调用方法,反之亦然
工厂模式

Golang的结构体没有构造函数,通常使用工厂模式解决这个问题

工厂模式:实现跨包创建结构体实例

type student struct {
	Name string
	age int
}
// 因为student结构体首字母小写,所以私有(只能在本包使用)
// 使用工厂模式解决
func NewStudent(n string,a int) *student {
	return &student{
		Name: n,
		age: a,
	}
}
// age首字母小写,也需要提供一个方法
func (this *student) GetAge() int {
	return this.age
}
三大特征----封装继承多态

**封装:**结构体、属性小写(私有化),提供工厂模式,Set、Get方法

type Hero struct {
	name string
	Ad int
	Level int
}

func (this *Hero)GetName() string {
	return this.Name
}
func (this *Hero)SetName(newName string)  {
	this.Name = newName
}

继承:

type Human struct {
	name string
	sex string
}
// 子类
type Superman struct {
	Human  //该类继承了Human
	level int
}

// 多继承情况下必须指定继承那个结构体的属性
type A struct {
	Name string
	Age int
}
type B struct {
	Name string
	id int
}
type C struct {
	A
	B
}

func main()  {
	var c C
	c.A.Name = "flandre"
}
接口(interface)

Golang中多态的特性主要是由接口实现的

type AnimalIF interface {	//本质是一个指针
	Sleep()
	GetColor() string		// string是返回值
}
//具体的类
type Cat struct {
	color string
}

func (this *Cat) Sleep()  {
	fmt.Println("Cat is Sleep")
}
func (this *Cat) GetColor() string {
	return this.color
}
func showAnimal(animal AnimalIF)  {
	animal.Sleep()  //多态
	fmt.Println(animal.GetColor())
}
func main()  {

	var animal AnimalIF //接口的数据类型
	animal = &Cat{"Green"}
	animal.Sleep() //调用cat的sleep方法		// Cat is Sleep
    fmt.Println(animal.GetColor())			// Green
    
    //cat := Cat{"Green"}
	//showAnimal(&cat)
}
  1. 接口可以定义一组方法,不能包含任何变量,而且本身不能创建实例
  2. 一个自定义类型可以实现多个接口
type A interface {
	Start()
}
type B interface {
	End()
}
type C struct {

}

func (this *C) End() {
	fmt.Println("游戏概述")
}
func (this *C) Start() {
	fmt.Println("芜湖!起飞!")
}
func main()  {
	var c C
	var a1 A = &c
	var b1 B = &c
	a1.Start()				// 芜湖!起飞!
	b1.End()				// 游戏概述
}
  1. 如果一个接口(A)继承了多个别的接口(B,C),那么实现A接口就必须将B,C的接口也全部实现

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zJ6gPJeW-1645582469622)(C:\Users\11140\Desktop\md笔记\images\接口vs继承.png)]

多态

上面的代码中有

类型断言
if person,ok := arg.(Person);ok{
    person.Say()
}

例1:

//interface{}是万能数据类型
func myFunc(arg interface{})  {
	fmt.Println("万能类型")
	fmt.Println(arg)

	//interface{}该如何区分,其实引用的数据类型是什么?
	//给interface{}提供了“断言”机制
	value,ok := arg.(string)
	if !ok {
		fmt.Println("arg is not string type")
	}else {
		fmt.Println("arg is string type,value = ",value)
	}
}

type Book struct {
	auth string
}

func main()  {
	book := Book{"Golang"}
	myFunc(book)
	myFunc(100)
	myFunc("abc")
	myFunc(3.14)
}

例2:循环判断传入参数的类型

func TypeJudge(arg ...interface{})  {
	for index,value := range arg {
		switch value.(type) {
		case bool:
			fmt.Printf("arg %d is bool type,value is %v\n",index,value)
		case string:
			fmt.Printf("arg %d is string type,value is %v\n",index,value)
		case int,int64:
			fmt.Printf("arg %d is int type,value is %v\n",index,value)
		case float32,float64:
			fmt.Printf("arg %d is float type,value is %v\n",index,value)
		case nil:
			fmt.Printf("arg %d is nil type,value is %v\n",index,value)
		case Student:
			fmt.Printf("arg %d is Student type,value is %v\n",index,value)
		case *Student:
			fmt.Printf("arg %d is *Student type,value is %v\n",index,value)
		default:
			fmt.Printf("arg %d is unknown type,value is %v\n",index,value)
		}
	}
}

func main()  {
	var n1 float32 = 1.1
	var n2 float64 = 1.2
	var n3 int = 30
	var name string = "flandre"
	var ty bool = true

	stu1 := Student{}
	stu2 := &Student{}

	TypeJudge(n1,n2,n3,name,ty,stu1,stu2)
}
//arg 0 is float type,value is 1.1
//arg 1 is float type,value is 1.2
//arg 2 is int type,value is 30
//arg 3 is string type,value is flandre
//arg 4 is bool type,value is true
//arg 5 is Student type,value is {}
//arg 6 is *Student type,value is &{}

你可能感兴趣的:(GO,python,golang,python转go,go,go语言)