GoLang实现接口的方式

本文探讨了Golang中接口的实现方式,包括结构体、结构体指针及函数实现,并通过实例演示了不同情况下接口的调用过程及其注意事项。

接口的实现

如果接口类型只包含一个方法,那么这个类型的名字以er结尾。
golang中实现接口的方式:
• 结构体形式实现结构

type Duck interface{
  Swim()
  Quack()
}

type Person struct{}

func (p Person) Swim(){
  fmt.Println("游泳")
}
func (p Person) Quack(){
  fmt.Println("鸭子叫")
}

• 结构体指针实现接口

type Handler interface {
    ServerHTTP(ResponseWriter, *Request)
}

type ServeMux struct {}

func (mux *ServeMux) ServeHTTP( w ResponseWriter, r *Request) {
    // 具体的实现
}

• 函数实现接口

type Handler interface {
    ServerHTTP(ResponseWriter, *Request)
}

type HandlerFunc func(ResponseWriter, *Request)

func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    // 具体的实现
}

探讨下调用接口的情况:

如下实现接口:

package main

import "fmt"

type Matcher interface {
	Search(searchTerm string) (string, error)
}

// 实现这个接口
type rssMatcher struct{}

func (r rssMatcher) Search(searchTerm string) (string, error){
	fmt.Println(searchTerm)
	return searchTerm, nil
}

它的调用方式有4种:

func main()  {
	var dm0 rssMatcher
	//指针来调用
	dm1 :=new(rssMatcher)
	dm1.Search("test1")
	//值来调用
	var dm2 rssMatcher
	dm2.Search("test2")
	// 将值传给接口
	var dm4 Matcher = dm0
	dm4.Search("test3")
	// 将指针 传给接口
	var dm5 Matcher = &dm0
	dm5.Search("test4")
}

如果改成指针作为接收者:

package main

import "fmt"

type Matcher interface {
	Search(searchTerm string) (string, error)
}

// 实现这个接口
type rssMatcher struct{}

func (r *rssMatcher) Search(searchTerm string) (string, error){
	fmt.Println(searchTerm)
	return searchTerm, nil
}

func main()  {
	var dm0 rssMatcher
	//指针来调用
	dm1 :=new(rssMatcher)
	dm1.Search("test1")
	//值来调用
	var dm2 rssMatcher
	dm2.Search("test2")
	// 将值传给接口 Cannot use 'dm0' (type rssMatcher) as type Matcher Type does not implement 'Matcher' as 'Search' method has a pointer receiver
	var dm4 Matcher = dm0
	dm4.Search("test3")
	// 将指针 传给接口
	var dm5 Matcher = &dm0
	dm5.Search("test4")
}

调用方式变成了三种, 其中将值赋值给接口的方式会编译出错。
现象:

  • 如果用值作为方法的接收者,编译器会隐式的转换成指针去调用方法。这样无论传给接口类型的是值还是指针都没有问题。
    但是如果用指针作为方法的接收者,在将值传给接口类型的时候,会提示该值没有实现这个接口。

总结:

  • 赋值的时候类型不匹配,说明接口的接收者类型必须要小于等于定义的类型
  • 假设指针为子类型,值的情况为父类型:
    • 那么接收者定义为值就可以用指针和值来赋值。
    • 那么接收者定义为指针就不能用值来赋值。
<think>好的,我需要回答用户关于如何在Golang中定义和实现接口的问题。首先,我需要回忆Golang接口的基本概念。根据引用[3]和[4],Golang接口是隐式实现的,不需要显式声明。接口定义一组方法签名,任何类型只要实现了这些方法就自动满足该接口。 接下来,用户需要具体的定义和实现的示例。根据引用[4],接口的定义使用type关键字,后面跟接口名和方法列表。例如: type Animal interface { Speak() string Move() string } 然后,实现接口的类型需要定义这些方法。比如结构体Dog和Cat分别实现Speak和Move方法。这里要注意,Golang中不需要像其他语言那样显式注明实现接口,只要方法存在即可。 需要检查示例是否正确。比如,引用[5]中有一个接口定义,包含getVideoFrame和FrameCount方法,用户可能需要类似的例子。所以可以构造一个简单的例子,比如Shape接口,有Area和Perimeter方法,然后让结构体Circle和Rectangle实现这些方法。 还需要注意接口的零值是nil,引用[4]提到空接口interface{}可以存储任何类型的值。这部分可能需要说明,但用户的问题主要是定义和实现,所以可以放在注意事项里。 另外,引用[2]和[3]都强调方法签名的匹配,参数和返回类型必须一致。所以在示例中要确保方法签名完全符合接口定义。 最后,生成相关问题时要围绕接口的定义、实现、使用场景、空接口、类型断言等,确保问题覆盖用户可能感兴趣的后续知识点。</think>### 如何在Golang中定义和实现接口? #### 1. 定义接口Golang中,接口通过`type`关键字定义,包含一组方法签名(无具体实现)。语法如下: ```go type 接口名 interface { 方法名1(参数列表) 返回值列表 方法名2(参数列表) 返回值列表 // ... } ``` **示例**:定义一个表示几何图形的接口`Shape`: ```go type Shape interface { Area() float64 // 计算面积 Perimeter() float64 // 计算周长 } ``` #### 2. 实现接口 Golang接口实现是隐式的,只要类型定义了接口中所有的方法,即自动实现接口,无需显式声明[^3][^4]。 **示例**:为`Circle`和`Rectangle`类型实现`Shape`接口: ```go // Circle结构体 type Circle struct { Radius float64 } // 实现Area方法 func (c Circle) Area() float64 { return math.Pi * c.Radius * c.Radius } // 实现Perimeter方法 func (c Circle) Perimeter() float64 { return 2 * math.Pi * c.Radius } // Rectangle结构体 type Rectangle struct { Width, Height float64 } // 实现Area方法 func (r Rectangle) Area() float64 { return r.Width * r.Height } // 实现Perimeter方法 func (r Rectangle) Perimeter() float64 { return 2 * (r.Width + r.Height) } ``` #### 3. 使用接口 接口可声明变量并接收实现接口的具体类型实例: ```go func main() { var s Shape s = Circle{Radius: 5} fmt.Println("圆面积:", s.Area()) // 输出: 78.5398... fmt.Println("圆周长:", s.Perimeter()) // 输出: 31.4159... s = Rectangle{Width: 3, Height: 4} fmt.Println("矩形面积:", s.Area()) // 输出: 12 fmt.Println("矩形周长:", s.Perimeter()) // 输出: 14 } ``` #### 注意事项 1. **方法签名严格匹配**:实现接口的方法必须与接口定义的方法名、参数、返回值完全一致[^2][^4]。 2. **空接口`interface{}`**:未定义任何方法的接口,可存储任意类型的值,常用于泛型场景[^4]。 3. **类型断言**:通过`value, ok := var.(具体类型)`可检查接口底层类型。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值