我有多种类型,我想传递这些类型的数据,比如将它们存储在变量中并将它们传递给函数:
type Pizza struct {
Toppings []string
Diameter int
}
type Steak struct {
Weight float64
Doneness string
}
type Car struct {
Speed int
}
type Chair struct {
}
func main() {
var favoriteFood interface{}
favoriteFood = Pizza{
Diameter: 20,
}
cook(favoriteFood, Chair{})
}
func cook(food interface{}, vehicle interface{}) {
fmt.Print("Cooking ")
if pizza, ok := food.(Pizza); ok {
fmt.Println("a " + strconv.Itoa(pizza.Diameter) + " cm pizza")
}
if steak, ok := food.(Steak); ok {
fmt.Println("a " + steak.Doneness + " steak")
}
if car, ok := vehicle.(Car); ok {
fmt.Print(" in a car at " + strconv.Itoa(car.Speed) + " km/h")
}
if _, ok := vehicle.(Chair); ok {
fmt.Print(" on a chair")
}
}
我希望cook()
接受Pizza
而Steak
接受food
但不接受Car
。
由于接口是由他们的方法定义的,而我的类型不共享任何常用方法,我不能让他们实现"界面。
我还可以介绍一个识别接收器功能,如下所示:
type Food interface {
IsFood() bool
}
func (f *Pizza) IsFood() bool { return true }
func (f *Steak) IsFood() bool { return true }
这是常见/惯用吗?
答案 0 :(得分:0)
Go提供了支持您需求的界面。例如,您可以使用名为Food
的接口:
type Food interface {
Cook()
}
现在让Pizza
和Steak
满足此界面:
func (p *Pizza) Cook() {
// use Pizza's fields
// ...
}
您现在可以使用CookFood
方法同时接受Pizza
和Steak
:
func CookFood(f Food) {
// ...
f.Cook()
// ...
}
你可以这样称呼:
func main() {
var favoriteFood = Pizza{
Diameter: 20,
}
CookFood(favoriteFood)
}
使用CookFood
(未实现Car
方法)调用Cook
会使编译器抛出错误,从而提供正确的类型安全性。
答案 1 :(得分:0)
好的,我使用界面更改了您的代码:here
界面部分:
type Food interface {
CookedInfo() string
}
func (p Pizza) CookedInfo() string {
return "a " + strconv.Itoa(p.Diameter) + " cm pizza"
}
func (s Steak) CookedInfo() string {
return "a" + s.Doneness + " steak"
}
type Location interface { //chair is hardly a vehicle
Where() string
}
func (c Chair) Where() string {
return "on a chair"
}
func (c Car) Where() string {
return "in a car at " + strconv.Itoa(c.Speed) + " km/h"
}
interface
的重点(好吧,可能不完整但非常密切)是隐藏实施细节。例如,Pizza
的大小,名称或其他属性就是这样的细节,函数cook
不关心它们。它也不关心牛排是否过度完成,也不关心你是否正在烹饪龙,因为龙有一种方法CookedInfo
。每种食物都有自己的方法来提供被Cook
使用的烹饪信息。这就对了。它会阻止您编写一个无限的测试类型列表(当函数在lib中导出时甚至变得不可能)并简化您的逻辑。
答案 2 :(得分:0)
我稍微修改过上一个示例 - https://play.golang.org/p/uN1m7pNZbsv
您可以尝试将嵌入和嵌入接口SOL_SOCKET/SO_PRIORITY
用于具体结构Food
和Pizza
,但不能使用car。
Steak
这种方式只接受匹配type Food interface {
Cook()
}
type Pizza struct {
Food
Diameter int
}
func Cook(food Food) {
...
}
的结构。
但是不要忘记Go是鸭式语言,所以如果你突然在Food
上实现方法Cook
,你可以start cooking it)
但是它没有明确嵌入Chair
。