是否可以利用 Go 中的模块系统将链代码划分为多个文件?
Is it possible to divide chaincode in multiple files by taking advantage of module system in Go?
我目前将我的链代码放在一个文件中,并且随着我添加更多函数它变得越来越大,所以维护它真的很令人沮丧。
我认为在 Go 中利用模块系统是个好主意,但我想不出办法。
我有:
my_chaincode
├── go.mod
├── go.sum
└── chaincode.go (whole chaincode)
和
my_chaincode
├── go.mod
├── go.sum
├── modules
│ └── smartcontract.go (All other functions)
└── chaincode.go (Only main function)
我想要的:
my_chaincode
├── go.mod
├── go.sum
├── modules
│ ├── admin.go (Some functions)
│ ├── system.go (Some functions)
│ └── user.go (Some functions)
└── chaincode.go (Only main function)
(*注意:我有创建和使用 Go 模块的基本知识。)
我尝试划分链代码(就像我想要的那样)并部署链代码,但是当我尝试执行事务时,链代码容器崩溃并出现错误 -
status:500 message:"error in simulation: failed to execute transaction
我前两次尝试都没有发生这种情况。
我确定我缺乏一些关于 Go 模块的知识。
我错过了什么?
一些像 GitHub 结构像我想要的存储库这样的参考会很棒吗?
是的,可以使用 Go 模块。
让我用一个例子来解释,考虑如下文件结构
my_chaincode (not necessary to use modules as folder name)
├── go.mod (created after executing `go mod init`)
├── go.sum (created after executing `go mod tidy`)
├── modules (not necessary to use modules as folder name)
│ ├── module1.go (Some functions)
│ ├── module2.go (Some functions)
│ └── module3.go (Some functions)
└── main.go (not necessary to use "main" as file name)
- 创建文件夹“my_chaincode”
cd my_chaincode
go mod init my_chaincode
// main.go
package main
import (
"fmt"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
"my_chaincode/modules" // importing all files from modules folder
)
func main() {
chaincode, err := contractapi.NewChaincode(new(modules.SmartContract))
if err != nil {
fmt.Printf("Error create chaincode: %s", err.Error())
return
}
if err := chaincode.Start(); err != nil {
fmt.Printf("Error starting chaincode: %s", err.Error())
}
}
// modules/module1.go
package modules
type SmartContract struct {
contractapi.Contract
}
type User struct {
// anything
}
func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {
// your logic
}
// modules/module2.go
package modules
import (
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
// private function (because name starts with a small letter)
func validateUid (uid string) (bool, error) {
// your logic
}
// public function (because name starts with a capital letter)
func (s *SmartContract) Create_User (ctx contractapi.TransactionContextInterface, uid string, name string, age int) error {
// your logic
// you can use "validateUid(uid)" function here
}
// modules/module3.go
import (
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
func (s *SmartContract) Create_Record (ctx contractapi.TransactionContextInterface, rid int, uid int) error {
// your logic
// you can use "validateUid(uid)" function here
// you can use "User" struct here
// you can use "ctx.Create_User(uid, 'user1', '20')" function here
// all above uses may seem irrelevant, but my intention is to show
// that you can directly use them without again defining in this file,
// which is the main goal. So, the whole chaincode can be divided
// into small modules.
}
go mod tidy
GO111MODULE=on go mod vendor
-(可选,如果你知道它的作用)
我目前将我的链代码放在一个文件中,并且随着我添加更多函数它变得越来越大,所以维护它真的很令人沮丧。
我认为在 Go 中利用模块系统是个好主意,但我想不出办法。
我有:
my_chaincode
├── go.mod
├── go.sum
└── chaincode.go (whole chaincode)
和
my_chaincode
├── go.mod
├── go.sum
├── modules
│ └── smartcontract.go (All other functions)
└── chaincode.go (Only main function)
我想要的:
my_chaincode
├── go.mod
├── go.sum
├── modules
│ ├── admin.go (Some functions)
│ ├── system.go (Some functions)
│ └── user.go (Some functions)
└── chaincode.go (Only main function)
(*注意:我有创建和使用 Go 模块的基本知识。)
我尝试划分链代码(就像我想要的那样)并部署链代码,但是当我尝试执行事务时,链代码容器崩溃并出现错误 -
status:500 message:"error in simulation: failed to execute transaction
我前两次尝试都没有发生这种情况。 我确定我缺乏一些关于 Go 模块的知识。
我错过了什么? 一些像 GitHub 结构像我想要的存储库这样的参考会很棒吗?
是的,可以使用 Go 模块。
让我用一个例子来解释,考虑如下文件结构
my_chaincode (not necessary to use modules as folder name)
├── go.mod (created after executing `go mod init`)
├── go.sum (created after executing `go mod tidy`)
├── modules (not necessary to use modules as folder name)
│ ├── module1.go (Some functions)
│ ├── module2.go (Some functions)
│ └── module3.go (Some functions)
└── main.go (not necessary to use "main" as file name)
- 创建文件夹“my_chaincode”
cd my_chaincode
go mod init my_chaincode
// main.go
package main
import (
"fmt"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
"my_chaincode/modules" // importing all files from modules folder
)
func main() {
chaincode, err := contractapi.NewChaincode(new(modules.SmartContract))
if err != nil {
fmt.Printf("Error create chaincode: %s", err.Error())
return
}
if err := chaincode.Start(); err != nil {
fmt.Printf("Error starting chaincode: %s", err.Error())
}
}
// modules/module1.go
package modules
type SmartContract struct {
contractapi.Contract
}
type User struct {
// anything
}
func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {
// your logic
}
// modules/module2.go
package modules
import (
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
// private function (because name starts with a small letter)
func validateUid (uid string) (bool, error) {
// your logic
}
// public function (because name starts with a capital letter)
func (s *SmartContract) Create_User (ctx contractapi.TransactionContextInterface, uid string, name string, age int) error {
// your logic
// you can use "validateUid(uid)" function here
}
// modules/module3.go
import (
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
func (s *SmartContract) Create_Record (ctx contractapi.TransactionContextInterface, rid int, uid int) error {
// your logic
// you can use "validateUid(uid)" function here
// you can use "User" struct here
// you can use "ctx.Create_User(uid, 'user1', '20')" function here
// all above uses may seem irrelevant, but my intention is to show
// that you can directly use them without again defining in this file,
// which is the main goal. So, the whole chaincode can be divided
// into small modules.
}
go mod tidy
GO111MODULE=on go mod vendor
-(可选,如果你知道它的作用)