Type cannot implement ‘_xxx‘ as it has a non-exported method and is defined in a different package

Cannot use xxx as the type xxxx Type cannot implement ‘_xxx’ as it has a non-exported method and is defined in a different package原因及解决方案

一、问题描述

以下是我在_interface包定义的一个Say接口,可以看到其中有两个方法签名,即实现了该接口里的ViewMan方法和sayHello方法,就可以实现Say接口。

package _interface

import _struct "gin/test_interface/struct"

type Say interface {
	ViewMan(string, _struct.InfoSs) (string, error)
	sayHello()
}

然后,我在_struct包里定义InfoSs结构体,并且尝试用其实现_interface包的Say接口,从以下代码中可以看到,我已经实现了Say接口中的两个方法。

package _struct

type InfoSs struct {
	Addr string
	Id   int
	Age  int
	Name string
}

func (i *InfoSs) ViewMan(s string, ss InfoSs) (string, error) {
	//TODO implement me
	panic("implement me")
	return "", nil
}

func (i *InfoSs) sayHello() {
	//TODO implement me
	panic("implement me")
}

但是,如下图所示,idea里面并没有看到实现接口的箭头。

请添加图片描述

于是,我想着测试一下,就在_function包里编写了Abc函数,该函数接受一个string类型和一个Say接口类型作为参数。

package _function

import (
	"fmt"
	_interface "gin/test_interface/interface"
)

func Abc(a string, say _interface.Say) {

	fmt.Println(a, '\n', say)

}

最后在main包的main函数里,实例化一个&_struct. InfoSs赋值给infoss,并且尝试将变量abc和infoss赋值给Abc函数。

package main

import (
	_function "gin/test_interface/function"
	_interface "gin/test_interface/interface"
	_struct "gin/test_interface/struct"
)

func main() {
	infoss := &_struct.InfoSs{Id: 1, Name: "aaa", Addr: "xxx@abc", Age: 20}
	abc := "abc"
	//var a _interface.Say = infoss
	_function.Abc(abc, infoss)
}

然而出现以下错误

Cannot use ‘infoss’(type *_struct.InfoSs) as the type _interface.Say Type cannot implement ‘_interface.Say’ as it has a non-exported method and is defined in a different package.

在这里插入图片描述

二、原因

经过反复思索,发现了错误原因如下:

在 main 函数中,我试图把 infoss(一个*_struct.InfoSs 类型的变量)作为参数传入_function.Abc 函数,但是这个函数要求的参数类型是 Say接口类型,而*_struct.InfoSs 类型并没有实现这个接口,所以编译器报错了。

虽然看似我已经实现了该接口,但是由于Say 接口中有一个方法是 sayHello(),它的首字母是小写的,而且Say接口所在的包和InfoSs所在的包分别为_interface和_struct包,因此,sayHello ()方法不能被其他包的类型实现(与go语言,不同包下首字母小写的变量不可导出,不能让其他包进行跨包使用类似)。因此,即使我在 struct 包中定义了一个 InfoSs 结构体,并且也定义了一个同名的方法 sayHello()(注意大小写),但是这个方法并不是 Say 接口中的那个方法,而是一个不同的方法,所以 InfoSs 结构体并没有实现 Say 接口。

三、解决方案

1.把 Say接口中的 sayHello()方法改成首字母大写 SayHello(),并且在_struct包中InfoSs 结构体实现的方法也相应地修改,这样就可以让 InfoSs 结构体实现 Say接口了。(推荐)

package _interface

import _struct "gin/test_interface/struct"

type Say interface {
	ViewMan(string, _struct.InfoSs) (string, error)
	SayHello()
}
package _struct

type InfoSs struct {
	Addr string
	Id   int
	Age  int
	Name string
}

func (i *InfoSs) ViewMan(s string, ss InfoSs) (string, error) {
	//TODO implement me
	panic("implement me")
	return "", nil
}

func (i *InfoSs) SayHello() {
	//TODO implement me
	panic("implement me")
}

2.把 Say接口和 InfoSs 结构体定义在同一个包中,这样就可以让 InfoSs 结构体实现接口中的非导出方法,因为它们在同一个包中是可见的。但是这样做可能会破坏的代码结构和模块化。(不推荐)

四、修改后结果

未报错

在这里插入图片描述

成功编译

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值