在使用GO编写的Hyperledger链代码中,可以将泛型类型的实例用作返回值类型。

huangapple go评论78阅读模式
英文:

Using instances of generic types as return value type in a Hyperledger chain code written in GO

问题

在我的项目中,我正在使用一个类似于以下定义的包装器结构:

type Wrapper[T any] struct {
   Foo  int
   Data T
}

此外,我的链码提供了一个具有以下签名的方法:

func(contract *MyContract) DoSomething() *Wrapper[mypkg.Bar]

其中Bar是一个简单的结构定义,例如:

package mypkg

struct Bar {
  Foo string
  Bar string
}

然而,如果我尝试部署我的链码,我会得到以下错误:

Error compiling schema for MyContract[DoSomething]. Return schema invalid. Object has no key 'Wrapper[[]<part of module name>'

奇怪的是,Wrapper[[]<part of module name>部分被截断了。所以只显示了部分模块名,并且如你所见,括号的配对是错误的:第二个闭合括号缺失(所以这不是我犯的错误)。我的模块名是指向GitHub存储库的链接。

我尝试手动将Wrapper中的通用类型T替换为Bar,创建结构体:

type WrapperBar struct {
  Foo int
  Data Bar
}

如果我现在将函数签名调整为:

func(contract *MyContract) DoSomething() *WrapperBar

它可以正常工作。不幸的是,我多次使用了具有不同类型实例化的Wrapper结构。因此,尽管手动创建所有类型可能是一种解决方法,但显然不是一种非常优雅的解决方法。

是否有另一种解决方法,以便我仍然可以使用通用的Wrapper结构?
我目前使用的是go版本1.18fabric-contract-api-go版本v1.1.1

英文:

In my project, I am using a wrapper structure, that is defined similar to this:

type Wrapper[T any] struct {
   Foo  int
   Data T
}

Additionally, my chain code offers a method with the following signature

func(contract *MyContract) DoSomething() *Wrapper[mypkg.Bar]

where Bar is a simple structure defined - for example - like this:

package mypkg

struct Bar {
  Foo string
  Bar string
}

Anyhow, if I try to deploy my chaincode, I get the following error:

Error compiling schema for MyContract[DoSomething]. Return schema invalid. Object has no key &#39;Wrapper[[]&lt;part of module name&gt;&#39;

Strangely, the part with Wrapper[[]&lt;part of module name&gt; is cropped. So only part of the module name is showing, and, as you can see, the bracketing is wrong: The second closing bracket is missing (so that is not a mistake made by me). The name of my module is the link to the GitHub repository.

I have tried to manually replace the generic type T in Wrapper with Bar by creating the structure

type WrapperBar struct {
  Foo int
  Data Bar
}

If I now adapt the function signature to

func(contract *MyContract) DoSomething() *WrapperBar

it works just fine. Unfortunately, I am using the structure Wrapper several times with different
type instantiations. So although creating all the types manually would be a workaround, it is obviously not a very elegant one.

Is there another workaround so that I can still use my generic Wrapper structure?
I am currently using go in version 1.18 and fabric-contract-api-go in version v1.1.1.

答案1

得分: 2

这个时候的Go contract-api不支持Go泛型。我能建议的解决方法是你已经尝试过的那个,就是在这个问题中提到的,或者你可以在不使用contract API的情况下编写你的链码。这里有一个示例:https://github.com/hyperledger/fabric-samples/tree/main/chaincode/marbles02/go,它是一个不使用contract-api的实现。

你的实现将需要在链码中做更多的工作,比如提供自己的方法分派、验证和解组输入数据。

你可以在https://github.com/hyperledger/fabric-contract-api-go上提出一个问题,并最好贡献一个解决这个问题的PR,因为我不能确定是否会在将来支持这个功能。

英文:

The Go contract-api at this time doesn't support Go Generics, the only workarounds I can suggest are the one that you have tried noted in this question or to write your chaincode without using the contract API, there is an example here https://github.com/hyperledger/fabric-samples/tree/main/chaincode/marbles02/go of an implementation that doesn't use the contract-api.
Your implemention will have to do more work in your chaincode such as providing your own method dispatching, validating and unmarshalling the input data

You could raise an issue at https://github.com/hyperledger/fabric-contract-api-go and ideally also contribute a PR that addresses this issue as I can't say when or if this would ever be supported.

huangapple
  • 本文由 发表于 2022年10月20日 21:46:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/74140988.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定