Golang中请解释为什么会出现这种情况

Golang中请解释为什么会出现这种情况 请解释这个现象:在第一个例子中,dogs方法需要指针,当我在animal切片中声明为&Dog时工作正常,但当我声明为Dog{}时编译器报错:

不能将Dog字面量(类型Dog)作为Animal类型用于数组或切片字面量: Dog未实现Animal(Speak方法具有指针接收器)

但在第二个例子中,当我声明dog的方法不带指针时,使用指针和非指针(&Dog, Dog{})都能正常工作

第一个例子:

package main

import (
	"fmt"
)

type Animal interface {
	Speak() string
}

type Dog struct {
}

func (d *Dog) Speak() string {
	return "BARK!"
}

func main() {
	animals := []Animal{&Dog{}}
	for _, animal := range animals {
		fmt.Println(animal.Speak())
	}
}

第二个例子:

package main

import (
	"fmt"
)

type Animal interface {
	Speak() string
}

type Dog struct {
}

func (d Dog) Speak() string {
	return "BARK!"
}

func main() {
	animals := []Animal{Dog{}}
	for _, animal := range animals {
		fmt.Println(animal.Speak())
	}
}

更多关于Golang中请解释为什么会出现这种情况的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

&Dog{} 就是您要找的。 &Dog{} 会在 animal 切片中添加一个新的动物。

func main() {
    fmt.Println("hello world")
}

更多关于Golang中请解释为什么会出现这种情况的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


实际上我需要解释,为什么在第一个例子中我只能传递指针(&Dog{}) 而在第二个例子中指针和值都有效(&Dog{}, Dog{})

func main() {
    fmt.Println("hello world")
}

在你第一个示例中,尝试将具体类型传递给接口类型时,Dog 本身并未实现 Animal 接口,只有指向 Dog 的指针才实现了该接口。在第二个示例中,(Dog.Speak()) 满足了接口的方法要求。

并非总是能够获取值的地址。由于并非总是能够获取值的地址,因此值的方法集仅包含通过值接收器实现的方法。

01 // 示例程序展示为何有时无法获取值的地址
02 package main
03
04 import "fmt"
05
06 // duration 是基于 int 的自定义类型
07 type duration int
08
09 // format 优雅地格式化 duration 值
10 func (d *duration) pretty() string {
11     return fmt.Sprintf("Duration: %d", *d)
12 }
13
14 // main 是应用程序的入口点
15 func main() {
16     duration(42).pretty()
17
18     // ./listing46.go:17: 无法在 duration(42) 上调用指针方法
19     // ./listing46.go:17: 无法获取 duration(42) 的地址
20 }

清单5.46中的代码尝试获取 duration 类型值的地址但失败了。这表明并非总是能够获取值的地址。让我们再次查看方法集的规则。

在Go语言中,接口实现与方法的接收器类型密切相关。第一个例子中,Speak方法使用指针接收器(d *Dog),这意味着只有*Dog类型(指向Dog的指针)实现了Animal接口。因此,在切片[]Animal中,只能使用&Dog{}(指针),而不能使用Dog{}(值类型),因为值类型Dog没有实现Speak方法。

第二个例子中,Speak方法使用值接收器(d Dog),这允许Dog*Dog类型都实现Animal接口。Go语言会自动处理值类型和指针类型的转换,因此Dog{}&Dog{}都可以在切片中使用。

示例代码说明:

第一个例子(指针接收器):

  • &Dog{}*Dog 类型,实现了 Animal 接口。
  • Dog{}Dog 类型,未实现 Animal 接口,导致编译器错误。

第二个例子(值接收器):

  • Dog{}Dog 类型,实现了 Animal 接口。
  • &Dog{}*Dog 类型,也实现了 Animal 接口(通过自动解引用)。

这种行为是Go语言类型系统的一部分,确保接口实现的一致性。如果方法需要修改接收器的状态,应使用指针接收器;否则,值接收器更高效。

回到顶部