Comprehensive understanding of Golang interface interface (2)

Now your life, life in the future to play you, now do not work hard, the future suck.

If you don’t play your life now, your life will play on you in the future. If you don’t work hard now, you won’t be able to work hard in the future.

 Pointers vs Value Types Implementing Interfaces

All of the example interfaces we discussed in Part 1 are implemented using the value receivers. Interfaces can also be implemented using pointer receivers. There are subtleties to be aware of when implementing interfaces using pointer receivers. Let us understand using the procedure below.

package main

import "fmt"

type Describer interface {
	Describe()
}
type Person struct {
	name string
	age  int
}

func (p Person) Describe() { //implemented using value receiver
	fmt.Printf("%s is %d years old\n", p.name, p.age)
}

type Address struct {
	state   string
	country string
}

func (a *Address) Describe() { //implemented using pointer receiver
	fmt.Printf("State %s Country %s", a.state, a.country)
}

func main() {
	var d1 Describer // 接口类型变量
	p1 := Person{"Sam", 25}
	d1 = p1  // 值类型
	d1.Describe()

	p2 := Person{"James", 32}
	d1 = &p2  // 指针类型
	d1.Describe()

	var d2 Describer
	a := Address{"Washington", "USA"}

	//d2 = a  // 不能使用值类型(编译失败)①

	d2 = &a 
	d2.Describe()
    a.Describe()  // 直接使用值类型调用②

}

Why does panic occur at d2 = a above (this is not panic, but a compilation error. 

cannot use a (type Address) as type Describer in assignment: Address does not implement Describer (Describe method has pointer receiver ) .

.\interface1.go:39:5: cannot use a (type Address) as type Describer in assignment:
	Address does not implement Describer (Describe method has pointer receiver)

And a.Describe() will not cause compilation failure? ? ?

The reason is: It is legal to call a pointer method on any pointer variable or variable that can obtain a pointer. But the value stored in the interface is not addressable, so the compiler can't get the pointer address automatically throws panic.

In other words: d2 = a This line reports an error. Simply put, the object passed (assigned) must implement the method required by the interface, a does not implement the Describe() method, and the pointer of a implements the Describe() method.

 

Implement multiple interfaces

A type can implement multiple interfaces. Let's see how this is done in the program below.

package main

import (
	"fmt"
)

type SalaryCalculator interface {
	DisplaySalary()
}

type LeaveCalculator interface {
	CalculateLeavesLeft() int
}

type Employee struct {
	firstName string
	lastName string
	basicPay int
	pf int
	totalLeaves int
	leavesTaken int
}

func (e Employee) DisplaySalary() {
	fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf))
}

func (e Employee) CalculateLeavesLeft() int {
	return e.totalLeaves - e.leavesTaken
}

func main() {
	e := Employee {
		firstName: "Naveen",
		lastName: "Ramanathan",
		basicPay: 5000,
		pf: 200,
		totalLeaves: 30,
		leavesTaken: 5,
	}
	var s SalaryCalculator = e
	s.DisplaySalary()
	var l LeaveCalculator = e
	fmt.Println("\nLeaves left =", l.CalculateLeavesLeft())
}

 

nesting of interfaces

Although go does not provide JAVA-like inheritance, new interfaces can be created by embedding other interfaces.

Let's see how this is done:

package main

import (
	"fmt"
)

type SalaryCalculator interface {
	DisplaySalary()
}

type LeaveCalculator interface {
	CalculateLeavesLeft() int
}

type EmployeeOperations interface {
	SalaryCalculator
	LeaveCalculator
}

type Employee struct {
	firstName string
	lastName string
	basicPay int
	pf int
	totalLeaves int
	leavesTaken int
}

func (e Employee) DisplaySalary() {
	fmt.Printf("%s %s has salary $%d", e.firstName, e.lastName, (e.basicPay + e.pf))
}

func (e Employee) CalculateLeavesLeft() int {
	return e.totalLeaves - e.leavesTaken
}

func main() {
	e := Employee {
		firstName: "Naveen",
		lastName: "Ramanathan",
		basicPay: 5000,
		pf: 200,
		totalLeaves: 30,
		leavesTaken: 5,
	}
	var empOp EmployeeOperations = e
	empOp.DisplaySalary()
	fmt.Println("\nLeaves left =", empOp.CalculateLeavesLeft())
	
	//当然更是实现了两个子接口
	var lc SalaryCalculator = e
	lc.DisplaySalary()
}

 

interface zero value

The zero value of an interface is nil, and it also has a nil type.

package main

import "fmt"

type Describer interface {  
    Describe()
}

func main() {  
    var d1 Describer
    if d1 == nil {
        fmt.Printf("d1 is nil and 类型 %T 值%v\n", d1, d1)
    }
}

If we call a method with a nil interface, the program panics because a nil interface has neither an underlying value nor a corresponding concrete type. Or like JAVA's null pointer exception!

 

The End!

 

 

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326044367&siteId=291194637