# 浣跨敤Golang杩涜鏅鸿兘鍚堢害寮€鍙�
<font color=red>娉ㄦ剰锛氭湰鏂囨。鎻忚堪鐨勬櫤鑳藉悎绾︾紪鍐欐柟娉曢€傜敤浜�2.3.0浠ヤ笂鐨勯暱瀹夐摼锛屽闇€鏌ョ湅2.x.x鐗堟湰鐨勬櫤鑳藉悎绾︾紪鍐欐枃妗o紝璇峰垏鎹㈠埌[2.x.x鐗堟湰鐨勬枃妗(https://docs.chainmaker.org.cn/v2.2.1/html/operation/%E6%99%BA%E8%83%BD%E5%90%88%E7%BA%A6.html#docker-go)銆�</font>

璇昏€呭璞★細鏈珷鑺備富瑕佹弿杩颁娇鐢℅olang杩涜ChainMaker鍚堢害缂栧啓鐨勬柟娉曪紝涓昏闈㈠悜浜庝娇鐢℅olang杩涜ChainMaker鐨勫悎绾﹀紑鍙戠殑寮€鍙戣€呫€�


**姒傝**
1銆佽繍琛屾椂铏氭嫙鏈虹被鍨嬶紙runtime_type锛夛細DOCKER_GO
2銆佷粙缁嶄簡鐜渚濊禆
3銆佷粙缁嶄簡寮€鍙戞柟寮忓強sdk鎺ュ彛
4銆佹彁渚涗簡涓€涓ず渚嬪悎绾�

## 鐜渚濊禆

1. 鎿嶄綔绯荤粺

	鐩墠浠呮敮鎸佸湪Linux绯荤粺涓嬮儴缃插拰杩愯 Docker VM锛屽悎绾︾殑缂栬瘧涔熷繀椤诲湪Linux鐜涓嬫墽琛屻€傚鏋滈渶瑕佸湪鍏朵粬绯荤粺鐜涓嬬紪璇戝悎绾︼紝璇峰弬鑰僄olang鐨勪氦鍙夌紪璇戜慨鏀圭紪璇戝懡浠ゃ€�

2. 杞欢渚濊禆

	鎺ㄨ崘浣跨敤Goland 鎴� vscode绛塈DE缂栧啓鍜岀紪璇慓olang鍚堢害銆�

	缂栬瘧鍚庣殑鍚堢害闇€瑕佺粡杩�7zip鍘嬬缉褰㈡垚鏈€缁堢殑鍚堢害鏂囦欢锛�7zip鐨勫畨瑁呰鍙傜湅[7zip瀹樼綉](https://sparanoid.com/lab/7z/)

3. 闀垮畨閾剧幆澧冨噯澶�

	鍑嗗涓€鏉℃敮鎸丏ocker_VM鐨勯暱瀹夐摼锛屼互鍙婇暱瀹夐摼CMC宸ュ叿锛岀敤浜庡皢鍐欑紪鍐欏ソ鐨勫悎绾︼紝閮ㄧ讲鍒伴摼涓婅繘琛屾祴璇曘€傜浉鍏冲畨瑁呮暀绋嬭璇﹁锛�

	- [閮ㄧ讲鏀寔Docker_VM鐨勯暱瀹夐摼鏁欑▼銆俔(./鍚姩鏀寔Docker_VM鐨勯摼.md)
	- [閮ㄧ讲闀垮畨閾綜MC宸ュ叿鐨勬暀绋嬨€俔(../dev/鍛戒护琛屽伐鍏�.md)


## 缂栧啓Golang鍚堢害

### 閫氳繃go.mod寮曠敤鍚堢害SDK

ChainMaker瀹樻柟Golang鍚堢害SDK鏀寔閫氳繃go.mod鐨勬柟寮忓紩鐢紝鍙洿鎺ヤ娇鐢╣o get寮曠敤锛岀ず渚嬪涓嬶細

   ```shell
   $ go get chainmaker.org/chainmaker/contract-sdk-go/v2@v2.3.4
   ```


鎵ц瀹屾垚鍚庯紝鍗冲彲鍙傝€冧笅鏂囩殑缂栧啓鍚堢害娉ㄦ剰浜嬮」锛岃皟鐢ㄥ悎绾dk鐨勬柟娉曪紝缂栧啓鍚堢害銆�


### 缂栧啓鍚堢害娉ㄦ剰浜嬮」

1. 浠g爜鍏ュ彛鍖呭悕蹇呴』涓篳main`

2. 浠g爜鍏ュ彛

   ```go
   package main
   
   // sdk浠g爜涓紝鏈変笖浠呮湁涓€涓猰ain()鏂规硶
   func main() {  
      // main()鏂规硶涓紝涓嬮潰鐨勪唬鐮佷负蹇呴』浠g爜锛屼笉寤鸿淇敼main()鏂规硶褰撲腑鐨勪唬鐮�
      // 鍏朵腑锛孴estContract涓虹敤鎴峰疄鐜板悎绾︾殑鍏蜂綋鍚嶇О
   	err := sandbox.Start(new(FactContract))
   	if err != nil {
   		log.Fatal(err)
   	}
   }
   ```

3. 鍚堢害蹇呰浠g爜

	```go
	// 鍚堢害缁撴瀯浣擄紝鍚堢害鍚嶇О闇€瑕佸啓鍏ain()鏂规硶褰撲腑
	type FactContract struct {
	}

   // 鍚堢害蹇呴』瀹炵幇涓嬮潰涓や釜鏂规硶锛�
   // InitContract() protogo.Response
   // UpgradeContract() protogo.Response
   // InvokeContract(method string) protogo.Response
   
   // 鐢ㄤ簬鍚堢害鐨勯儴缃�
   // @return: 	鍚堢害杩斿洖缁撴灉锛屽寘鎷琒uccess鍜孍rror
   func (f *FactContract) InitContract() protogo.Response {
   	return sdk.Success([]byte("Init contract success"))
   }
   
   // 鐢ㄤ簬鍚堢害鐨勫崌绾�
   // @return: 	鍚堢害杩斿洖缁撴灉锛屽寘鎷琒uccess鍜孍rror
   func (f *FactContract) UpgradeContract() protogo.Response {
   	return sdk.Success([]byte("Upgrade contract success"))
   }
   
   // 鐢ㄤ簬鍚堢害鐨勮皟鐢�
   // @param method: 浜ゆ槗璇锋眰璋冪敤鐨勬柟娉�
   // @return: 	鍚堢害杩斿洖缁撴灉锛屽寘鎷琒uccess鍜孍rror
   func (f *FactContract) InvokeContract(method string) protogo.Response {
		switch method {
		case "save":
			return f.save()
		case "findByFileHash":
			return f.findByFileHash()
		default:
			return sdk.Error("invalid method")
		}
	}
	```


### 鍚堢害SDK鎺ュ彛鎻忚堪

闀垮畨閾炬彁渚沢olang鍚堢害涓庨摼浜や簰鐨勭浉鍏虫帴鍙o紝鍐欏悎绾︽椂鍙洿鎺ュ鍏ュ寘锛屽苟杩涜寮曠敤锛屽叿浣撲俊鎭彲鍙傝€冩枃绔犳湯灏�"鎺ュ彛鎻忚堪绔犺妭"銆�


### 缂栬瘧鍚堢害
褰撳悎绾︾紪鍐欏畬鎴愬悗锛屽垯闇€瑕佺紪璇戝悎绾︼紝鍏蜂綋鏁欑▼濡備笅

#### 浣跨敤鑴氭湰缂栬瘧鍚堢害
1. 鍦ㄥ悎绾﹀伐绋嬩腑娣诲姞缂栬瘧鑴氭湰build.sh鎼缓缂栬瘧鐜銆�

	```shell
	#!/bin/bash

	contractName=$1
	if  [[ ! -n $contractName ]] ;then
		echo "contractName is empty. use as: ./build.sh contractName"
		exit 1
	fi

	go build -ldflags="-s -w" -o $contractName

	7z a $contractName $contractName
	rm -f $contractName

	```

2. 缂栬瘧鎾板啓濂界殑鏅鸿兘鍚堢害銆�

	鍏朵腑ContractName璇锋浛鎹㈡垚闇€瑕佸畨瑁呯殑鍚堢害鍚嶇О 

	```shell
	./build.sh ContractName
	```

	缂栬瘧鎴愬姛锛屽涓嬪浘鎵€绀猴細

	<img loading="lazy" src="../images/go-vm-contract-build_success.png" style="zoom:70%;" />

#### 鎵嬪姩缂栬瘧鍚堢害

鎵嬪姩缂栬瘧鍚堢害鏃讹紝棣栧厛浣跨敤golang缂栬瘧鎴愬彲鎵ц鏂囦欢锛屽啀瀵圭紪璇戝悗鐨勫彲鎵ц鏂囦欢杩涜7zip鍘嬬缉锛屽帇缂╁悗鐨�".7z"鏂囦欢涓哄悎绾︽枃浠躲€�

鍙傝€冨涓嬬紪璇戝懡浠わ細

```shell
go build -ldflags="-s -w" -o contract_name

7z a contract_name contract_name
```

闇€瑕佹敞鎰忕殑鏄細鍚堢害鐨勬墽琛岀幆澧冧负linux鐜锛岄渶瑕佷繚璇佹槸鍦↙inux鐜涓嬬紪璇戙€傚鏋滃湪鍏朵粬绯荤粺鐜锛坢ac鎴杦indows锛変笅缂栬瘧鍚堢害锛岃鍙傝€僄olang鐨勪氦鍙夌紪璇戜慨鏀筭o build鍛戒护銆�


### 閮ㄧ讲璋冪敤鍚堢害

缂栬瘧瀹屾垚鍚庯紝灏嗗緱鍒颁竴涓猔.7z`鏍煎紡鐨勫悎绾︽枃浠讹紝鍙皢涔嬮儴缃插埌鎸囧畾鍒伴暱瀹夐摼涓婏紝瀹屾垚鍚堢害閮ㄧ讲銆�
閮ㄧ讲鍚堢害鐨勪娇鐢ㄦ暀绋嬪彲璇﹁锛歔閮ㄧ讲绀轰緥鍚堢害](./閮ㄧ讲绀轰緥鍚堢害.md)銆�


## 绀轰緥鍚堢害浣跨敤婕旂ず

### 绀轰緥浠g爜璇存槑

ChainMaker瀹樻柟鎻愪緵浜嗛€氳繃go.mod寮曠敤鍚堢害SDK杩涜鍚堢害寮€鍙戠殑绀轰緥鍚堢害宸ョ▼銆�

浠ュ瓨璇佸悎绾︿负渚嬶紝鍙互鐩存帴涓嬭浇涓嬬紪璇戝瓨璇佸悎绾︼紝杩囩▼濡備笅锛�
   ```shell
   $ git clone  --depth=1 https://git.chainmaker.org.cn/contracts/contracts-go.git
   $ cd contracts-go/fact
   $ ./build.sh fact
   ...
   ```

鏇村鍚堢害绀轰緥鍙互鐩存帴鏌ョ湅浠撳簱[contracts-go](https://git.chainmaker.org.cn/contracts/contracts-go)


### 瀛樿瘉鍚堢害绀轰緥婧愮爜灞曠ず
鍙傝€僛瀛樿瘉鍚堢害绀轰緥婧愮爜](https://git.chainmaker.org.cn/chainmaker/contract-sdk-go/-/blob/v2.3.3/demo/contract_fact.go)

### 閮ㄧ讲璋冪敤绀轰緥鍚堢害

#### 浣跨敤cmc宸ュ叿閮ㄧ讲璋冪敤鍚堢害

   ```shell
   ## 鍒涘缓鍚堢害
   ./cmc client contract user create \
   --contract-name=fact \
   --runtime-type=DOCKER_GO \
   --byte-code-path=./testdata/claim-docker-go-demo/docker-fact.7z \
   --version=1.0 \
   --sdk-conf-path=./testdata/sdk_config.yml \
   --admin-key-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.tls.key,./testdata/crypto-config/wx-org2.chainmaker.org/user/admin1/admin1.tls.key,./testdata/crypto-config/wx-org3.chainmaker.org/user/admin1/admin1.tls.key,./testdata/crypto-config/wx-org4.chainmaker.org/user/admin1/admin1.tls.key \
   --admin-crt-file-paths=./testdata/crypto-config/wx-org1.chainmaker.org/user/admin1/admin1.tls.crt,./testdata/crypto-config/wx-org2.chainmaker.org/user/admin1/admin1.tls.crt,./testdata/crypto-config/wx-org3.chainmaker.org/user/admin1/admin1.tls.crt,./testdata/crypto-config/wx-org4.chainmaker.org/user/admin1/admin1.tls.crt \
   --sync-result=true \
   --params="{}"
   
   ## 璋冪敤鍚堢害
   ./cmc client contract user invoke \
   --contract-name=fact \
   --method=save \
   --sdk-conf-path=./testdata/sdk_config.yml \
   --params="{\"file_name\":\"name007\",\"file_hash\":\"ab3456df5799b87c77e7f88\",\"time\":\"6543234\"}" \
   --sync-result=true
   
   ## 鏌ヨ鍚堢害
   ./cmc client contract user get \
   --contract-name=fact \
   --method=findByFileHash \
   --sdk-conf-path=./testdata/sdk_config.yml \
   --params="{\"file_hash\":\"ab3456df5799b87c77e7f88\"}"
   ```

#### 浣跨敤Go SDK閮ㄧ讲璋冪敤鍚堢害

   ```go
   // 鍒涘缓鍚堢害
   func testUserContractCreate(client *sdk.ChainClient, withSyncResult bool, isIgnoreSameContract bool, usernames ...string) {
   
       resp, err := createUserContract(client, factContractName, factVersion, factByteCodePath,
           common.RuntimeType_DOCKER_GO, []*common.KeyValuePair{}, withSyncResult, usernames...)
       if !isIgnoreSameContract {
           if err != nil {
               log.Fatalln(err)
           }
       }
   
       fmt.Printf("CREATE claim contract resp: %+v\n", resp)
   }
   
   func createUserContract(client *sdk.ChainClient, contractName, version, byteCodePath string, runtime common.RuntimeType, kvs []*common.KeyValuePair, withSyncResult bool, usernames ...string) (*common.TxResponse, error) {
   
       payload, err := client.CreateContractCreatePayload(contractName, version, byteCodePath, runtime, kvs)
       if err != nil {
           return nil, err
       }
   
       endorsers, err := examples.GetEndorsers(payload, usernames...)
       if err != nil {
           return nil, err
       }
   
       resp, err := client.SendContractManageRequest(payload, endorsers, createContractTimeout, withSyncResult)
       if err != nil {
           return nil, err
       }
   
       err = examples.CheckProposalRequestResp(resp, true)
       if err != nil {
           return nil, err
       }
   
       return resp, nil
   }
   
   // 璋冪敤鍚堢害
   // 璋冪敤鎴栬€呮煡璇㈠悎绾︽椂锛宮ethod鍙傛暟璇疯缃负 invoke_contract锛屾鏂规硶浼氳皟鐢ㄥ悎绾︾殑InvokeContract鏂规硶锛屽啀閫氳繃鍙傛暟鑾峰緱鍏蜂綋鏂规硶
   func testUserContractInvoke(client *sdk.ChainClient, method string, withSyncResult bool) (string, error) {
   
       curTime := strconv.FormatInt(time.Now().Unix(), 10)
   
       fileHash := uuid.GetUUID()
       kvs := []*common.KeyValuePair{
           {
               Key: "method",
               Value: []byte("save"),
           },
           {
               Key:   "time",
               Value: []byte(curTime),
           },
           {
               Key:   "file_hash",
               Value: []byte(fileHash),
           },
           {
               Key:   "file_name",
               Value: []byte(fmt.Sprintf("file_%s", curTime)),
           },
       }
   
       err := invokeUserContract(client, factContractName, method, "", kvs, withSyncResult)
       if err != nil {
           return "", err
       }
   
       return fileHash, nil
   }
   
   func invokeUserContract(client *sdk.ChainClient, contractName, method, txId string, kvs []*common.KeyValuePair, withSyncResult bool) error {
   
       resp, err := client.InvokeContract(contractName, method, txId, kvs, -1, withSyncResult)
       if err != nil {
           return err
       }
   
       if resp.Code != common.TxStatusCode_SUCCESS {
           return fmt.Errorf("invoke contract failed, [code:%d]/[msg:%s]\n", resp.Code, resp.Message)
       }
   
       if !withSyncResult {
           fmt.Printf("invoke contract success, resp: [code:%d]/[msg:%s]/[txId:%s]\n", resp.Code, resp.Message, resp.ContractResult.Result)
       } else {
           fmt.Printf("invoke contract success, resp: [code:%d]/[msg:%s]/[contractResult:%s]\n", resp.Code, resp.Message, resp.ContractResult)
       }
   
       return nil
   }
   ```

## 鎺ュ彛鎻忚堪

鐢ㄦ埛涓庨摼浜や簰鎺ュ彛锛屽弬鑰冿細[Golang鍚堢害鎺ュ彛璇存槑](https://git.chainmaker.org.cn/chainmaker/contract-sdk-go/-/blob/v2.3.3/sdk/sdk_interface.go)