Golang中接口实现和调用的代码问题求解

Golang中接口实现和调用的代码问题求解 请先回答以下问题再提交问题,谢谢!

你使用的 Go 版本是什么(go version)?

  • go version go1.11 darwin/amd64

这个问题在最新版本中是否仍然存在?

  • 未测试

你使用的操作系统和处理器架构是什么(go env)?

  • 与此无关

你做了什么?

如果可能,请提供重现错误的步骤。
一个完整的可运行程序更好。
play.golang.org 上的链接最佳。

代码1:

package main

import "fmt"

type myintf interface {
	GotU()
}

type esc struct {
	 i int
}

//func GotU(t esc);
func (e esc)GotU() {
	e.i = 10
}

func TestFunc(it myintf) string {
	it.GotU()
	return  "kk"
}

func main() {

	var test esc
	test.i = 9

	TestFunc(test)

	fmt.Println(test.i)

}

代码2:

package main

import "fmt"

type myintf interface {
	GotU()
}

type esc struct {
	 i int
}

func (e esc)GotU() {
	e.i = 10
}

func TestFunc(it myintf) string {
	it.GotU()
	return  "kk"
}

func main() {

	var test esc
	test.i = 9

	TestFunc(test)

	fmt.Println(test.i)

}

代码3:

package main

import "fmt"

type myintf interface {
	GotU()
}

type esc struct {
	 i int
}

func (e *esc)GotU() {
	e.i = 10
}

func TestFunc(it myintf) string {
	it.GotU()
	return  "kk"
}

func main() {

	var test esc
	test.i = 9

	TestFunc(test)

	fmt.Println(test.i)

}

你期望看到什么?

  • 没有预期

你实际看到了什么?

代码1输出:9

代码2输出:9
代码3由于类型不匹配无法编译

既然只实现了 func (e esc)GotU(),为什么两段代码都能工作并产生相同的结果?
将结构体指针传递给该函数(TestFunc)却得到相同答案,这让我感到困惑。


更多关于Golang中接口实现和调用的代码问题求解的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

我认为解决您问题的方法是将结构体作为引用传递。

https://play.golang.org/p/Vucg9bflX9f

更多关于Golang中接口实现和调用的代码问题求解的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go语言中,接口实现和调用的行为取决于方法接收器的类型。让我分析这三个代码示例:

代码1和代码2分析

代码1和代码2实际上是相同的(代码1中注释掉了一行),它们都使用值接收器:

func (e esc) GotU() {
    e.i = 10
}

输出结果都是9的原因:

  • 值接收器操作的是副本,对字段的修改不会影响原始对象
  • TestFunc(test) 传递的是 esc 类型的值,接口方法操作的是这个值的副本

代码3分析

代码3使用指针接收器:

func (e *esc) GotU() {
    e.i = 10
}

编译错误的原因:

  • *esc 类型实现了 myintf 接口,但 esc 类型没有
  • TestFunc(test) 传递的是 esc 值类型,不满足接口要求

正确的指针接收器用法

要让代码3工作,需要传递指针:

package main

import "fmt"

type myintf interface {
    GotU()
}

type esc struct {
    i int
}

func (e *esc) GotU() {
    e.i = 10
}

func TestFunc(it myintf) string {
    it.GotU()
    return "kk"
}

func main() {
    var test esc
    test.i = 9

    // 传递指针而不是值
    TestFunc(&test)

    fmt.Println(test.i) // 输出: 10
}

关键区别总结

// 值接收器 - 操作副本,不影响原对象
func (e esc) GotU() {
    e.i = 10 // 修改的是副本
}

// 指针接收器 - 操作原对象
func (e *esc) GotU() {
    e.i = 10 // 修改的是原对象
}

接口实现规则:

  • 值类型 T 的方法集包含所有值接收器声明的方法
  • 指针类型 *T 的方法集包含所有值接收器和指针接收器声明的方法

这就是为什么代码1和代码2能工作(值类型实现了接口),而代码3需要传递指针才能编译通过。

回到顶部