Go结构体继承指针和非指针区别(转换接口)

1.实例不转换为接口的情况下无区别

总结:
    不转换为接口时(字段继承和字段指针继承)无区别,
    在代码中1,2,3,4处(即a,b,pa,pb)都可以正常调用父类的函数
package main

import "fmt"

type iter interface {
	run()
	sleep()
}
type base struct{}

func (p *base)run()  {
	fmt.Println("Base::run()")
}

func (p base)sleep()  {
	fmt.Println("Base::sleep()")
}

type subA struct {
	base	// 字段继承
}

type subB struct {
	*base   // 字段指针继承
}

/**
总结:
    不转换为接口时(字段继承和字段指针继承)无区别,就是正常类型实例使用
    在1,2,3,4处(即a,b,pa,pb)都可以正常调用父类的函数
*/
func main() {

	// 实例[字段继承]
	a := subA{base{}}
	a.run()  // 1
	a.sleep()
	// 实例[字段指针继承]
	b := subB{&base{}}
	b.run()  // 2
	b.sleep()

	// 指针实例[字段继承]
	pa := &subA{base{}}
	pa.run()  // 3
	pa.sleep()
	// 指针实例[字段指针继承]
	pb := &subB{&base{}}
	pb.run()  // 4
	pb.sleep()
}

2.实例转换接口时有区别

总结:
   转换为接口时(字段继承和字段指针继承)有区别,
    在B1,C1,D1都可以正常运行
   在A1处出现错误,即subA实例[字段继承]未实现接口  run()方法
package main

import "fmt"

type iter interface {
	run()
	sleep()
}
type base struct{

}
func (p *base)run()  {
	fmt.Println("Base::run()")
}

func (p base)sleep()  {
	fmt.Println("Base::sleep()")
}

type subA struct {
	base
}


// ---------HERE------------
//func (p subA)run()  {
//	fmt.Println("Base::run()")
//}

type subB struct {
	*base
}

/**
总结:
	转换为接口时(字段继承和字段指针继承)有区别,
    在B1,C1,D1都可以正常运行
	在A1处出现错误,即subA实例[字段继承]未实现接口run()方法
*/
func main() {
	// ======实例转换为接口=============
	var i iter
	// a实例[字段继承]
	a := subA{base{}}

    // 如果需要将a实例转化为接口,必须实现接口 
    // Base结构体已经实现了接收者为实例的sleep()方法
    // 那么可以在subA结构体实现 接收者为实例接受的run()方法即可---位于HERE处
    // 
	i = a	// A1	erro subA未实现接口,父类仅仅实现了sleep()方法,run()没有实现
	i.run() // A1
	i.sleep()

	// b实例[字段指针继承]
	b := subB{&base{}}
	i = b	// subB实现了接口
	i.run() // B1
	i.sleep()

	// =======指针实例转换为接口==========
	// 指针实例[字段继承]
	pa := &subA{base{}}
	i = pa	 // subA实现了接口
	i.run()  // C1
	i.sleep()

	// 指针实例[字段指针继承]
	pb := &subB{&base{}}
	i = pb	//  subB实现接口
	i.run()  //  D1
	i.sleep()
}

具体可查看

go值接收者方法和指针接收者方法

猜你喜欢

转载自blog.csdn.net/jadeshu/article/details/106590159