如下只考虑编译通过, 不考虑是否真实修改
1. 直接调用方法时的规则:
值类型可以调用值接收者方法
值类型可以调用指针接收者方法
指针类型可以调用值接收者方法
指针类型可以调用指针接收者方法
package main
type IDraw interface {
getName() string
setName(string)
}
type Rect struct {
name string
}
func (p Rect) getName() string {
return p.name
}
func (p *Rect) setName(name string) {
p.name = name
}
func main() {
var rect Rect = Rect{name: "rect"}
rect.getName()
rect.setName("rect")
var prect *Rect = &Rect{name: "rect"}
prect.getName()
prect.setName("rect")
}
2. 实现接口时的规则:
如果接口所有方法都是值接收者实现的,那么值类型和指针类型都可以实现该接口
package main
type IDraw interface {
getName() string
setName(string)
}
type Rect struct {
name string
}
func (p Rect) getName() string {
return p.name
}
func (p Rect) setName(name string) {
p.name = name
}
func main() {
var draw IDraw = Rect{}
draw.getName()
draw.setName("test")
var pdraw IDraw = &Rect{}
pdraw.getName()
pdraw.setName("test")
}
如果接口任何一个方法是指针接收者实现的,那么只有指针类型能实现该接口
package main
type IDraw interface {
getName() string
setName(string)
}
type Rect struct {
name string
}
func (p Rect) getName() string {
return p.name
}
func (p *Rect) setName(name string) {
p.name = name
}
func main() {
var draw IDraw = Rect{} //报错, cannot use Rect{} (value of type Rect) as IDraw value in variable declaration: Rect does not implement IDraw (method setName has pointer receiver)compilerInvalidIfaceAssign
draw.getName()
draw.setName("test")
var pdraw IDraw = &Rect{}
pdraw.getName()
pdraw.setName("test")
}
3. 注意
如果接口任何一个方法是指针接收者实现的,那么只有指针类型能实现该接口
type Integer int
func (i *Integer) AddV(b Integer) Integer {
return *i + b
}
func (a Integer) Add(b Integer) Integer {
return Integer(a + b)
}
func main() {
var a Integer = 1
var b Integer = 2
var i interface{} = &a
sum := i.(*Integer).Add(b)
sumV := i.(*Integer).AddV(b)
fmt.Println(sum)
fmt.Println(sumV)
}
为什么支持值类型实现该接口?
关键点在于:
- 这里并没有定义显式的接口类型,而是使用了空接口interface{}
- 空接口不包含任何方法要求,所以任何类型都实现了空接口
- 当你使用i.(*Integer)进行类型断言时,是在把接口值转换回具体类型
- 类型断言后,就可以直接调用该类型的任何方法,不管是值接收者还是指针接收者的方法