189 8069 5689

GO语言bytes32 go语言bytes

Go语言和其他语言的不同之基本语法

Go语言作为出现比较晚的一门编程语言,在其原生支持高并发、云原生等领域的优秀表现,像目前比较流行的容器编排技术Kubernetes、容器技术Docker都是用Go语言写的,像Java等其他面向对象的语言,虽然也能做云原生相关的开发,但是支持的程度远没有Go语言高,凭借其语言特性和简单的编程方式,弥补了其他编程语言一定程度上的不足,一度成为一个热门的编程语言。

10年积累的成都网站设计、网站建设经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先网站制作后付款的网站建设流程,更有赛罕免费网站建设让你可以放心的选择与我们合作。

最近在学习Go语言,我之前使用过C#、Java等面向对象编程的语言,发现其中有很多的编程方式和其他语言有区别的地方,好记性不如烂笔头,总结一下,和其他语言做个对比。这里只总结差异的地方,具体的语法不做详细的介绍。

种一棵树最好的时间是十年前,其次是现在。

3)变量初始化时候可以和其他语言一样直接在变量后面加等号,等号后面为要初始化的值,也可以使用变量名:=变量值的简单方式

3)变量赋值 Go语言的变量赋值和多数语言一致,但是Go语言提供了多重赋值的功能,比如下面这个交换i、j变量的语句:

在不支持多重赋值的语言中,交换两个变量的值需要引入一个中间变量:

4)匿名变量

在使用其他语言时,有时候要获取一个值,却因为该函数返回多个值而不得不定义很多没有的变量,Go语言可以借助多重返回值和匿名变量来避免这种写法,使代码看起来更优雅。

假如GetName()函数返回3个值,分别是firstName,lastName和nickName

若指向获得nickName,则函数调用可以这样写

这种写法可以让代码更清晰,从而大幅降低沟通的复杂度和维护的难度。

1)基本常量

常量使用关键字const 定义,可以限定常量类型,但不是必须的,如果没有定义常量的类型,是无类型常量

2)预定义常量

Go语言预定义了这些常量 true、false和iota

iota比较特殊,可以被任务是一个可被编译器修改的常量,在每个const关键字出现时被重置为0,然后在下一个const出现之前每出现一个iota,其所代表的数字会自动加1.

3)枚举

1)int 和int32在Go语言中被认为是两种不同类型的类型

2)Go语言定义了两个浮点型float32和float64,其中前者等价于C语言的float类型,后者等价于C语言的double类型

3)go语言支持复数类型

复数实际上是由两个实数(在计算机中使用浮点数表示)构成,一个表示实部(real)、一个表示虚部(imag)。也就是数学上的那个复数

复数的表示

实部与虚部

对于一个复数z=complex(x,y),就可以通过Go语言内置函数real(z)获得该复数的实部,也就是x,通过imag(z)获得该复数的虚部,也就是y

4)数组(值类型,长度在定义后无法再次修改,每次传递都将产生一个副本。)

5)数组切片(slice)

数组切片(slice)弥补了数组的不足,其数据结构可以抽象为以下三个变量:

6)Map 在go语言中Map不需要引入任何库,使用很方便

Go循环语句只支持for关键字,不支持while和do-while

goto语句的语义非常简单,就是跳转到本函数内的某个标签

今天就介绍到这里,以后我会在总结Go语言在其他方面比如并发编程、面向对象、网络编程等方面的不同及使用方法。希望对大家有所帮助。

golang之大端序、小端序

当分别处于大小端模式下的内容存放如下

(1)大端模式存储(存储地址为16位)

地址 数据

0x0004(高地址) 0x44

0x0003 0x33

0x0002 0x22

0x0001(低地址) 0x11

(2)小端模式存储(存储地址为16位)

地址 数据

0x0004(高地址) 0x11

0x0003 0x22

0x0002 0x33

0x0001(低地址) 0x44

在前面也简单阐述了大小端序的定义并结合简单实例来说明,接下来会给出详细实例来说明:

1、大端序(Big-Endian):或称大尾序

一个类型: int32 的数 0X0A0B0C0D的内存存放情况

数据是以8bits为单位

2、小端序(little-endian):或称小尾序

比如0x00000001

大端序:内存低比特位 00000000 00000000 00000000 00000001 内存高比特位

小端序:内存低比特位 10000000 00000000 00000000 00000000 内存高比特位

其实在前面罗列出那么东西,最终是为了接下来讲述的在golang中涉及到网络传输、文件存储时的选择。一般来说网络传输的字节序,可能是大端序或者小端序,取决于软件开始时通讯双方的协议规定。TCP/IP协议RFC1700规定使用“大端”字节序为网络字节序,开发的时候需要遵守这一规则。默认golang是使用大端序。详情见golang中包encoding/binary已提供了大、小端序的使用

输出结果:

16909060 use big endian:

int32 to bytes: [1 2 3 4] ### [0001 0002 0003 0004]

bytes to int32: 16909060

16909060 use little endian:

int32 to bytes: [4 3 2 1] ### [0004 0003 0002 0001]

bytes to int32: 16909060

在RPCX框架中关于RPC调用过程涉及的传递消息进行编码的,采用的就是大端序模式

GO语言运行32位

第一种

1.使用go env命令,查看系统的配置环境,可以看到GOARCH(当前系统)是amd64

2.执行 set GOARCH=386 配置go输出系统平台为32位,此时再用go env命令查看系统的配置环境,如图:

第二种

打开Run Edit Configurations Configuration标签

为Environment添加两个设置项

参考

用Go来做以太坊开发⑤事件日志

智能合约具有在执行期间“发出”事件的能力。 事件在以太坊中也称为“日志”。 事件的输出存储在日志部分下的事务处理中。 事件已经在以太坊智能合约中被广泛使用,以便在发生相对重要的动作时记录,特别是在代币合约(即ERC-20)中,以指示代币转账已经发生。 这些部分将引导您完成从区块链中读取事件以及订阅事件的过程,以便交易事务被矿工打包入块的时候及时收到通知。

为了订阅事件日志,我们需要做的第一件事就是拨打启用websocket的以太坊客户端。 幸运的是,Infura支持websockets。

下一步是创建筛选查询。 在这个例子中,我们将阅读来自我们在之前课程中创建的示例合约中的所有事件。

我们接收事件的方式是通过Go channel。 让我们从go-ethereum core/types 包创建一个类型为 Log 的channel。

现在我们所要做的就是通过从客户端调用 SubscribeFilterLogs 来订阅,它接收查询选项和输出通道。 这将返回包含unsubscribe和error方法的订阅结构。

最后,我们要做的就是使用select语句设置一个连续循环来读入新的日志事件或订阅错误。

我们会在下个章节介绍如何解析日志。

Commands

Store.sol

event_subscribe.go

智能合约可以可选地释放“事件”,其作为交易收据的一部分存储日志。读取这些事件相当简单。首先我们需要构造一个过滤查询。我们从go-ethereum包中导入 FilterQuery 结构体并用过滤选项初始化它。我们告诉它我们想过滤的区块范围并指定从中读取此日志的合约地址。在示例中,我们将从在 智能合约章节 创建的智能合约中读取特定区块所有日志。

下一步是调用ethclient的 FilterLogs ,它接收我们的查询并将返回所有的匹配事件日志。

返回的所有日志将是ABI编码,因此它们本身不会非常易读。为了解码日志,我们需要导入我们智能合约的ABI。为此,我们导入编译好的智能合约Go包,它将包含名称格式为 ContractABI 的外部属性。之后,我们使用go-ethereum中的 accounts/abi 包的 abi.JSON 函数返回一个我们可以在Go应用程序中使用的解析过的ABI接口。

现在我们可以通过日志进行迭代并将它们解码为我么可以使用的类型。若您回忆起我们的样例合约释放的日志在Solidity中是类型为 bytes32 ,那么Go中的等价物将是 [32]byte 。我们可以使用这些类型创建一个匿名结构体,并将指针作为第一个参数传递给解析后的ABI接口的 Unpack 函数,以解码原始的日志数据。第二个参数是我们尝试解码的事件名称,最后一个参数是编码的日志数据。

此外,日志结构体包含附加信息,例如,区块摘要,区块号和交易摘要。

若您的solidity事件包含 indexed 事件类型,那么它们将成为 主题 而不是日志的数据属性的一部分。在solidity中您最多只能有4个主题,但只有3个可索引的事件类型。第一个主题总是事件的签名。我们的示例合约不包含可索引的事件,但如果它确实包含,这是如何读取事件主题。

正如您所见,首个主题只是被哈希过的事件签名。

这就是阅读和解析日志的全部内容。要学习如何订阅日志,阅读上个章节。

命令

Store.sol

event_read.go

首先,创建ERC-20智能合约的事件日志的interface文件 erc20.sol :

然后在给定abi使用 abigen 创建Go包

现在在我们的Go应用程序中,让我们创建与ERC-20事件日志签名类型相匹配的结构类型:

初始化以太坊客户端

按照ERC-20智能合约地址和所需的块范围创建一个“FilterQuery”。这个例子我们会用 ZRX 代币:

用 FilterLogs 来过滤日志:

接下来我们将解析JSON abi,稍后我们将使用解压缩原始日志数据:

为了按某种日志类型进行过滤,我们需要弄清楚每个事件日志函数签名的keccak256哈希值。 事件日志函数签名哈希始终是 topic [0] ,我们很快就会看到。 以下是使用go-ethereum crypto 包计算keccak256哈希的方法:

现在我们将遍历所有日志并设置switch语句以按事件日志类型进行过滤:

现在要解析 Transfer 事件日志,我们将使用 abi.Unpack 将原始日志数据解析为我们的日志类型结构。 解包不会解析 indexed 事件类型,因为它们存储在 topics 下,所以对于那些我们必须单独解析,如下例所示:

Approval 日志也是类似的方法:

最后,把所有的步骤放一起:

我们可以把解析的日志与etherscan的数据对比:

Commands

erc20.sol

event_read_erc20.go

solc version used for these examples

要读取 0x Protocol 事件日志,我们必须首先将solidity智能合约编译为一个Go包。

安装solc版本 0.4.11

为例如 Exchange.sol 的事件日志创建0x Protocol交易所智能合约接口:

Create the 0x protocol exchange smart contract interface for event logs as Exchange.sol :

接着给定abi,使用 abigen 来创建Go exchange 包:

Then use abigen to create the Go exchange package given the abi:

现在在我们的Go应用程序中,让我们创建与0xProtocol事件日志签名类型匹配的结构体类型:

初始化以太坊客户端:

创建一个 FilterQuery ,并为其传递0x Protocol智能合约地址和所需的区块范围:

用 FilterLogs 查询日志:

接下来我们将解析JSON abi,我们后续将使用解压缩原始日志数据:

为了按某种日志类型过滤,我们需要知晓每个事件日志函数签名的keccak256摘要。正如我们很快所见到的那样,事件日志函数签名摘要总是 topic[0] :

现在我们迭代所有的日志并设置一个switch语句来按事件日志类型过滤:

现在要解析 LogFill ,我们将使用 abi.Unpack 将原始数据类型解析为我们自定义的日志类型结构体。Unpack不会解析 indexed 事件类型,因为这些它们存储在 topics 下,所以对于那些我们必须单独解析,如下例所示:

对于 LogCancel 类似:

最后是 LogError :

将它们放在一起并运行我们将看到以下输出:

将解析后的日志输出与etherscan上的内容进行比较:

命令

Exchange.sol

event_read_0xprotocol.go

这些示例使用的solc版本

Go语言中的字节序

Go中的binary包实现了简单的数字与字节序列的转换以及变长值的编解码

package main

import ( "fmt" "bytes" "encoding/binary" ) func main(){ n := 0x12345678 bytesBuffer := bytes.NewBuffer([]byte{}) //BigEndian 大端顺序存储 LittleEndian小端顺序存储 binary.Write(bytesBuffer, binary.BigEndian, int32(n)) data:=bytesBuffer.Bytes() fmt.Printf("[0]: %#x addr:%#x\n",data[0],data[0]) fmt.Printf("[0]: %#x addr:%#x\n",data[1],data[1]) fmt.Printf("[0]: %#x addr:%#x\n",data[2],data[2]) fmt.Printf("[0]: %#x addr:%#x\n",data[3],data[3]) }

输出

[0]: 0x12 addr:0xc042010248 [1]: 0x34 addr:0xc042010249 [2]: 0x56 addr:0xc04201024a [3]: 0x78 addr:0xc04201024b

也可以使用下面的方式

n := 0x12345678 var data []byte = make([]byte,4) //操作的都是无符号整型 binary.BigEndian.PutUint32(data,uint32(n))

可以使用下面的方式判断当前系统的字节序类型

const INT_SIZE int = int(unsafe.Sizeof(0))

//判断我们系统中的字节序类型 func systemEdian() { var i int = 0x1 bs := (*[INT_SIZE]byte)(unsafe.Pointer(i)) if bs[0] == 0 { fmt.Println("system edian is little endian") } else { fmt.Println("system edian is big endian") } }

用Go来做以太坊开发④智能合约

在这个章节中我们会介绍如何用Go来编译,部署,写入和读取智能合约。

与智能合约交互,我们要先生成相应智能合约的应用二进制接口ABI(application binary interface),并把ABI编译成我们可以在Go应用中调用的格式。

第一步是安装 Solidity编译器 ( solc ).

Solc 在Ubuntu上有snapcraft包。

Solc在macOS上有Homebrew的包。

其他的平台或者从源码编译的教程请查阅官方solidity文档 install guide .

我们还得安装一个叫 abigen 的工具,来从solidity智能合约生成ABI。

假设您已经在计算机上设置了Go,只需运行以下命令即可安装 abigen 工具。

我们将创建一个简单的智能合约来测试。 学习更复杂的智能合约,或者智能合约的开发的内容则超出了本书的范围。 我强烈建议您查看 truffle framework 来学习开发和测试智能合约。

这里只是一个简单的合约,就是一个键/值存储,只有一个外部方法来设置任何人的键/值对。 我们还在设置值后添加了要发出的事件。

虽然这个智能合约很简单,但它将适用于这个例子。

现在我们可以从一个solidity文件生成ABI。

它会将其写入名为“Store_sol_Store.abi”的文件中

现在让我们用 abigen 将ABI转换为我们可以导入的Go文件。 这个新文件将包含我们可以用来与Go应用程序中的智能合约进行交互的所有可用方法。

为了从Go部署智能合约,我们还需要将solidity智能合约编译为EVM字节码。 EVM字节码将在事务的数据字段中发送。 在Go文件上生成部署方法需要bin文件。

现在我们编译Go合约文件,其中包括deploy方法,因为我们包含了bin文件。

在接下来的课程中,我们将学习如何部署智能合约,然后与之交互。

Commands

Store.sol

solc version used for these examples

如果你还没看之前的章节,请先学习 编译智能合约的章节 因为这节内容,需要先了解如何将智能合约编译为Go文件。

假设你已经导入从 abigen 生成的新创建的Go包文件,并设置ethclient,加载您的私钥,下一步是创建一个有配置密匙的交易发送器(tansactor)。 首先从go-ethereum导入 accounts/abi/bind 包,然后调用传入私钥的 NewKeyedTransactor 。 然后设置通常的属性,如nonce,燃气价格,燃气上线限制和ETH值。

如果你还记得上个章节的内容, 我们创建了一个非常简单的“Store”合约,用于设置和存储键/值对。 生成的Go合约文件提供了部署方法。 部署方法名称始终以单词 Deploy 开头,后跟合约名称,在本例中为 Store 。

deploy函数接受有密匙的事务处理器,ethclient,以及智能合约构造函数可能接受的任何输入参数。我们测试的智能合约接受一个版本号的字符串参数。 此函数将返回新部署的合约地址,事务对象,我们可以交互的合约实例,还有错误(如果有)。

就这么简单:)你可以用事务哈希来在Etherscan上查询合约的部署状态:

Commands

Store.sol

contract_deploy.go

solc version used for these examples

这写章节需要了解如何将智能合约的ABI编译成Go的合约文件。如果你还没看, 前先读 上一个章节 。

一旦使用 abigen 工具将智能合约的ABI编译为Go包,下一步就是调用“New”方法,其格式为“Newcontractname style="box-sizing: border-box; font-size: 16px; -ms-text-size-adjust: auto; -webkit-tap-highlight-color: transparent;"”,所以在我们的例子中如果你 回想一下它将是 NewStore 。 此初始化方法接收智能合约的地址,并返回可以开始与之交互的合约实例。/contractname

Commands

Store.sol

contract_load.go

solc version used for these examples

这写章节需要了解如何将智能合约的ABI编译成Go的合约文件。如果你还没看, 前先读 上一个章节 。

在上个章节我们学习了如何在Go应用程序中初始化合约实例。 现在我们将使用新合约实例提供的方法来阅读智能合约。 如果你还记得我们在部署过程中设置的合约中有一个名为 version 的全局变量。 因为它是公开的,这意味着它们将成为我们自动创建的getter函数。 常量和view函数也接受 bind.CallOpts 作为第一个参数。了解可用的具体选项要看相应类的 文档 一般情况下我们可以用 nil 。

Commands

Store.sol

contract_read.go

solc version used for these examples

这写章节需要了解如何将智能合约的ABI编译成Go的合约文件。如果你还没看, 前先读 上一个章节 。

写入智能合约需要我们用私钥来对交易事务进行签名。

我们还需要先查到nonce和燃气价格。

接下来,我们创建一个新的keyed transactor,它接收私钥。

然后我们需要设置keyed transactor的标准交易选项。

现在我们加载一个智能合约的实例。如果你还记得 上个章节 我们创建一个名为 Store 的合约,并使用 abigen 工具生成一个Go文件。 要初始化它,我们只需调用合约包的 New 方法,并提供智能合约地址和ethclient,它返回我们可以使用的合约实例。

我们创建的智能合约有一个名为 SetItem 的外部方法,它接受solidity“bytes32”格式的两个参数(key,value)。 这意味着Go合约包要求我们传递一个长度为32个字节的字节数组。 调用 SetItem 方法需要我们传递我们之前创建的 auth 对象(keyed transactor)。 在幕后,此方法将使用它的参数对此函数调用进行编码,将其设置为事务的 data 属性,并使用私钥对其进行签名。 结果将是一个已签名的事务对象。

现在我就可以看到交易已经成功被发送到了以太坊网络了:

要验证键/值是否已设置,我们可以读取智能合约中的值。

搞定!

Commands

Store.sol

contract_write.go

solc version used for these examples

有时您需要读取已部署的智能合约的字节码。 由于所有智能合约字节码都存在于区块链中,因此我们可以轻松获取它。

首先设置客户端和要读取的字节码的智能合约地址。

现在你需要调用客户端的 codeAt 方法。 codeAt 方法接受智能合约地址和可选的块编号,并以字节格式返回字节码。

你也可以在etherscan上查询16进制格式的字节码

contract_bytecode.go

首先创建一个ERC20智能合约interface。 这只是与您可以调用的函数的函数定义的契约。

然后将interface智能合约编译为JSON ABI,并使用 abigen 从ABI创建Go包。

假设我们已经像往常一样设置了以太坊客户端,我们现在可以将新的 token 包导入我们的应用程序并实例化它。这个例子里我们用 Golem 代币的地址.

我们现在可以调用任何ERC20的方法。 例如,我们可以查询用户的代币余额。

我们还可以读ERC20智能合约的公共变量。

我们可以做一些简单的数学运算将余额转换为可读的十进制格式。

同样的信息也可以在etherscan上查询:

Commands

erc20.sol

contract_read_erc20.go

solc version used for these examples


网站栏目:GO语言bytes32 go语言bytes
URL地址:http://cdxtjz.cn/article/doccpge.html

其他资讯