golang interface实现中遇到的问题

本文探讨了在Go语言中使用接口与方法接收者时的常见问题,特别是当使用值接收者与指针接收者时的区别。通过具体的代码示例,解释了为何某些类型无法实现预期的接口。
部署运行你感兴趣的模型镜像
package main

import (
       "fmt"
)

type Human struct {
       name string
       age int
       phone string
}

type Student struct {
       Human
       school string
       loan float32
}

type Employee struct {
       Human
       company string
       money float32
}

func (h Human) SayHi()  {
       fmt.Printf("Hi,I am %s you can call me on %s\n",h.name,h.phone)
}

func (h Human) sing(lyrics string)  {
       fmt.Println("la la la la la la la la la la la la ...",lyrics)
}


func (e Employee) SayHi()  {
       fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
              e.company, e.phone) //Yes you can split into 2 lines here.
}

type Men interface {
       SayHi()
       sing(lyrics string)
}

func main()  {
       mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
       paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
       sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
       Tom := Employee{Human{"Sam", 36, "444-222-XXX"}, "Things Ltd.", 5000}

       //定义Men类型的变量i
       var i Men

       //i能存储Student
       i = mike
       fmt.Println("this is mike, astudent")
       i.SayHi()
       i.sing("November rain")

       //i 也能存储Employee
       i = Tom
       fmt.Println("this is tom, an Employee:")
       i.SayHi()
       i.sing("Born to be wild")

       //定义了slice Men
       fmt.Println("Let's use a slice of Men and see what happens")
       x := make([]Men,3)
       //这三个都是不同类型的元素,但是他们实现了interface同一个接口
       x[0],x[1],x[2] = paul,sam,mike

       for _,value := range x{
              value.SayHi()
       }

}

以上代码可以运行,但是把mathoed中的struct换成指针为什么就不能运行了,如下所示

package main

import (
       "fmt"
)

type Human struct {
       name string
       age int
       phone string
}

type Student struct {
       Human
       school string
       loan float32
}

type Employee struct {
       Human
       company string
       money float32
}

func (h *Human) SayHi()  {
       fmt.Printf("Hi,I am %s you can call me on %s\n",h.name,h.phone)
}

func (h *Human) sing(lyrics string)  {
       fmt.Println("la la la la la la la la la la la la ...",lyrics)
}


func (e *Employee) SayHi()  {
       fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
              e.company, e.phone) //Yes you can split into 2 lines here.
}

type Men interface {
       SayHi()
       sing(lyrics string)
}

func main()  {
       mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
       paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
       sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
       Tom := Employee{Human{"Sam", 36, "444-222-XXX"}, "Things Ltd.", 5000}

       //定义Men类型的变量i
       var i Men

       //i能存储Student
       i = mike
       fmt.Println("this is mike, astudent")
       i.SayHi()
       i.sing("November rain")

       //i 也能存储Employee
       i = Tom
       fmt.Println("this is tom, an Employee:")
       i.SayHi()
       i.sing("Born to be wild")

       //定义了slice Men
       fmt.Println("Let's use a slice of Men and see what happens")
       x := make([]Men,3)
       //这三个都是不同类型的元素,但是他们实现了interface同一个接口
       x[0],x[1],x[2] = paul,sam,mike

       for _,value := range x{
              value.SayHi()
       }
}
报错是接口不能接受此种类型了 如下:

"C:\Program Files (x86)\JetBrains\Gogland 163.10154.18\bin\runnerw.exe" C:/Go\bin\go.exe run C:/Users/Administrator/GoglandProjects/untitled/src/test.go
# command-line-arguments
src\test.go:54: cannot use mike (type Student) as type Men in assignment:
Student does not implement Men (SayHi method has pointer receiver)
src\test.go:60: cannot use Tom (type Employee) as type Men in assignment:
Employee does not implement Men (SayHi method has pointer receiver)
src\test.go:69: cannot use paul (type Student) as type Men in assignment:
Student does not implement Men (SayHi method has pointer receiver)
src\test.go:69: cannot use sam (type Employee) as type Men in assignment:
Employee does not implement Men (SayHi method has pointer receiver)
src\test.go:69: cannot use mike (type Student) as type Men in assignment:
Student does not implement Men (SayHi method has pointer receiver)


Process finished with exit code 2


对此深深不解,以作记录。


您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

<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.(具体类型)`可检查接口底层类型。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值