【问题标题】:local Method call results in: undeclared name: [name]本地方法调用导致:未声明的名称:[名称]
【发布时间】:2020-12-16 01:39:37
【问题描述】:

总结:本地方法调用(在同一文件内)导致:[govet] undeclared name: QueryPart [Error]

编辑:请参阅帖子底部的错误和更正摘要。

我是 Go 新手,正在尝试构建一些简单的 Hyperledger Fabric 链代码。

在下面的代码中,我有一个可以成功调用的方法QueryPart。我想看看我是否可以编写另一个方法QueryPartSpecial 来调用原始的QueryPart 方法(然后做一些其他的事情),但是我遇到了一个致命错误:[govet] undeclared name: QueryPart [Error]

  231 //QueryPart: queries a single part from the ledger (with provided partID)
  232 func (s *SmartContract) QueryPart(ctx contractapi.TransactionContextInterface, partID string) (*Part, error) {
  233   assetJSON, err := ctx.GetStub().GetState(partID)
  234   if err != nil {
  235     return nil, fmt.Errorf("failed to read from world state: %v", err)
  236   }
  237   if assetJSON == nil {
  238     return nil, fmt.Errorf("the asset %s does not exist", partID)
  239   }
  240   
  241   var part Part
  242   err = json.Unmarshal(assetJSON, &part)
  243   if err != nil {
  244     return nil, err
  245   }
  246 
  247   return &part, nil
  248 }
  249 
  250 //QueryPartSpecial: calls QueryPart and does some other experimental stuff on it
  251 func QueryPartSpecial(partID string) (*Part, error) {
✘ 252   part, err := QueryPart(partID)
  253   //placeholder for some other code
  254   return part, err
  255 } 

既然上面明确声明了 func QueryPart,为什么我会收到这个错误?

注意:此问题与以下问题非常相似:
Function in same package undefined
Go: undefined function in same package

但是,与这些其他问题的主要区别在于,我的两个函数位于同一个 [file].go 中。

注意 2:我得到的错误是 linting 错误,但也阻止了我编译/安装链代码。

编辑:我做错了什么以及我学到了什么:

我收到的错误是由于 QueryPartSpecial 方法的问题,而不是 QueryPart 方法的问题。

作为 Go 新手,我犯了几个错误:

  1. 令人困惑的methods and functions。 (在我原来的帖子中,我将这两种方法都称为函数。)
  2. 错误地构造QueryPartSpecial:正如卢卡斯指出的,我没有在QueryPartSpecial 中包含任何对象。通过将此函数修改为带有 SmartContract 指针接收器的方法,我可以在调用 QueryPart 时提供一个对象。
  3. 错误调用方法QueryPart:由于方法对对象进行操作,因此应在对象上调用它们。

这是我更正后的代码(没有返回错误的功能):

255 //QueryPartSpecial: calls QueryPart and does some other experimental stuff on it
256 func (s *SmartContract) QueryPartSpecial(ctx contractapi.TransactionContextInterface, partID string) (*Part, error) {
257   part, err := s.QueryPart(ctx,partID)
258   //placeholder for some other code
259   return part, err
260 } 

(感谢 Lucas、Adrian 和 Volker 的帮助并引导我朝着正确的方向前进。)

【问题讨论】:

  • 请学习 Go,例如通过tour.golang.org。 QueryPart 是一种方法,因此不能在没有对象的情况下调用。
  • QueryPart*SmartContract 的方法,因此必须在*SmartContract 实例上调用。 QueryPartSpecial 是一个没有接收器的普通函数。
  • @Volker Golang 中的“对象”是什么意思?
  • 感谢 Adrian 和 Volker 的反馈。 (我已经通过了 tour.golang,但诚然我仍在努力学习。)我理解 QueryPart 是一种方法(而不是像我最初所说的那样的函数)。但是,我仍然对为什么会收到上述错误感到困惑。 (请注意,如果我删除第 250-255 行,则不会出现错误。)
  • 对象:一个类型的实例。学习语言。

标签: go


【解决方案1】:

您正在为方法QueryPart 使用pointer receiver。来自文档:

带有指针接收器的方法可以修改指针接收器的值 接收点

所以你需要调用对象本身的方法,类似这样:

contract := SmartContract{}
contract.QueryPart(ctx)

或者直接调用它删除接收器(转换为上面Adrian评论的函数):

func QueryPart(...) // (s *SmartContract) receiver removed

【讨论】: