目录
[3.1 Golang 内置的运算符](#3.1 Golang 内置的运算符)
[3.2 算数运算符](#3.2 算数运算符)
[3.3 关系运算符](#3.3 关系运算符)
[3.4 逻辑运算符](#3.4 逻辑运算符)
[3.5 赋值运算符](#3.5 赋值运算符)
[3.6 运算符练习](#3.6 运算符练习)
[3.7 位运算符](#3.7 位运算符)
[3.8 其他运算符](#3.8 其他运算符)
[3.9 运算符优先级总结表](#3.9 运算符优先级总结表)
[3.10 区块链专用运算符技巧](#3.10 区块链专用运算符技巧)

3.1 Golang 内置的运算符
(1) 算术运算符:用于执行基本的数学计算操作,如加减乘除、取余等数值运算。
(2) 关系运算符:用于比较两个值或表达式之间的关系,返回布尔值(真/假)表示比较结果。
(3) 逻辑运算符:用于连接或组合多个布尔表达式,进行逻辑判断(与、或、非),返回布尔结果。
(4) 位运算符:在二进制位级别上对整数进行操作,直接操作数据的二进制表示形式。
(5) 赋值运算符:将右侧表达式的结果存储到左侧变量中,可以包含复合操作简化代码。
3.2 算数运算符
|-----|----|----------|----------------------------------------|
| 运算符 | 描述 | 区块链示例 | 代码示例 |
| + | 加法 | 计算账户总余额 | totalBalance := wallet1 + wallet2 |
| - | 减法 | 计算交易后的余额 | remaining := balance - amount |
| * | 乘法 | 计算挖矿奖励 | reward := blocksMined * blockReward |
| / | 除法 | 计算代币价格 | pricePerToken := totalValue / tokens |
| % | 取模 | 区块高度分片 | shard := blockHeight % 16 |
| ++ | 自增 | 区块计数器 | blockNumber++ |
| -- | 自减 | 递减Gas费用 | gasRemaining-- |
注意:++(自增)和 --(自减)在 Go 语言中是单独的语句,并不是运算符。
示例代码一:
Go
package main
import "fmt"
func main() {
// 1. 账户余额计算
aliceBalance := 5.75 // ETH
bobBalance := 3.25 // ETH
totalNetworkBalance := aliceBalance + bobBalance
fmt.Printf("网络总余额: %.2f ETH\n", totalNetworkBalance)
// 2. Gas费用计算
gasLimit := 21000
gasUsed := 18950
gasRemaining := gasLimit - gasUsed
fmt.Printf("剩余Gas: %d\n", gasRemaining)
// 3. 挖矿奖励计算
blockReward := 2.0 // 每个区块奖励
blocksMined := 150
totalReward := blockReward * float64(blocksMined)
fmt.Printf("总挖矿奖励: %.1f ETH\n", totalReward)
// 4. 代币价格计算
poolLiquidity := 1000000.0 // 流动性池总价值(美元)
totalTokens := 500000.0 // 总代币数
tokenPrice := poolLiquidity / totalTokens
fmt.Printf("代币价格: $%.4f\n", tokenPrice)
// 5. 分片算法(用于区块链分片)
blockHeight := 123456
shardCount := 16
shardID := blockHeight % shardCount
fmt.Printf("区块高度 %d 属于分片 %d\n", blockHeight, shardID)
// 6. 区块计数器
currentBlock := 1000
fmt.Printf("当前区块: %d\n", currentBlock)
currentBlock++ // 挖出新区块
fmt.Printf("新区块: %d\n", currentBlock)
}
示例代码二:
Go
package main
import "fmt"
func main() {
fmt.Println("10 + 3 = ", 10+3)
fmt.Println("10 - 3 = ", 10-3)
fmt.Println("10 * 3 = ", 10*3)
// 除法注意:通过运算的数都是整数,那么除后,去掉小数部分,保留整数部分
fmt.Println("10/3=", 10/3)
fmt.Println("10.0/3=", 10.0/3)
// 取余注意:余数 = 被除数 - (被除数/除数)
fmt.Println("10 % 3 = ", 10%3)
fmt.Println("-10 % 3 = ", -10%3)
fmt.Println("10 % -3 = ", 10%-3)
fmt.Println("-10 % -3 = ", -10%-3)
}
注意: 在 golang 中,++ 和 -- 只能独立使用 错误写法如下:
Go
var i int = 8
var a int
a = i++ //错误,i++只能独立使用
a = i-- //错误, i--只能独立使用
注意: 在 golang 中没有前++ 错误写法如下:
Go
var i int = 1
++i // 错误,在 golang 没有 前++
--i // 错误,在 golang 没有 前--
fmt.Println("i=", i)
++ --正确写法:
Go
var i int = 1
i++
fmt.Println("i=", i)
3.3 关系运算符
| 运算符 | 描述 | 区块链示例 | 代码示例 |
|---|---|---|---|
== |
检查两个值是否相等,如果相等返回 True,否则返回 False。 | 验证哈希是否匹配 | hash == expectedHash |
!= |
检查两个值是否不相等,如果不相等返回 True,否则返回 False。 | 检查地址是否不同 | from != to |
> |
检查左边值是否大于右边值,如果是返回 True,否则返回 False。 | 验证余额是否足够 | balance > amount |
< |
检查左边值是否小于右边值,如果是返回 True,否则返回 False。 | 检查Gas限制 | gasUsed < gasLimit |
>= |
检查左边值是否大于等于右边值,如果是返回 True,否则返回 False。 | 最低质押要求 | stake >= minStake |
<= |
检查左边值是否小于等于右边值,如果是返回 True,否则返回 False。 | 区块大小限制 | blockSize <= maxBlockSize |
示例代码一:
Go
package main
import "fmt"
func main() {
var n1 int = 9
var n2 int = 8
fmt.Println("n1 == n2的结果(检查两个值是否相等,从哈希的角度来判断):", n1 == n2)
fmt.Println("n1 != n2的结果(检查两个值是否相等,从地址的角度来判断):", n1 != n2)
fmt.Println("n1 > n2的结果:", n1 > n2)
fmt.Println("n1 < n2的结果:", n1 < n2)
fmt.Println("n1 <= n2的结果:", n1 <= n2)
flag := n1 > n2
fmt.Println("flag = ", flag)
}
示例代码二:
Go
package main
import (
"fmt"
"strings"
)
type Transaction struct {
From string
To string
Amount float64
}
type Block struct {
Hash string
PrevHash string
GasUsed int
GasLimit int
Size int
}
func main() {
// 1. 验证交易有效性
tx := Transaction{
From: "0xabc123",
To: "0xdef456",
Amount: 1.5,
}
// 检查发送方和接收方是否相同(防止自己给自己转账浪费Gas)
if tx.From != tx.To {
fmt.Println("✓ 交易有效:发送方和接收方不同")
} else {
fmt.Println("✗ 交易无效:不能给自己转账")
}
// 2. 验证余额是否足够
accountBalance := 2.0
transferAmount := 1.5
if accountBalance >= transferAmount {
fmt.Println("✓ 余额充足,可以转账")
} else {
fmt.Println("✗ 余额不足")
}
// 3. 检查Gas使用情况
block := Block{
GasUsed: 1500000,
GasLimit: 3000000,
}
if block.GasUsed < block.GasLimit {
fmt.Printf("✓ Gas使用正常: %d/%d\n", block.GasUsed, block.GasLimit)
} else {
fmt.Println("✗ Gas超出限制")
}
// 4. 验证区块哈希
calculatedHash := "0x123abc"
receivedHash := "0x123abc"
if calculatedHash == receivedHash {
fmt.Println("✓ 区块哈希验证通过")
} else {
fmt.Println("✗ 区块哈希不匹配")
}
// 5. 检查质押要求(PoS共识)
minStake := 32.0 // 最低质押32个ETH
validatorStake := 40.0
if validatorStake >= minStake {
fmt.Println("✓ 满足验证者质押要求")
} else {
fmt.Printf("✗ 质押不足,需要至少 %.0f ETH\n", minStake)
}
// 6. 区块大小限制
maxBlockSize := 1024 * 1024 * 2 // 2MB
currentBlockSize := 1024 * 1500 // 1.5MB
if currentBlockSize <= maxBlockSize {
fmt.Printf("✓ 区块大小 %dKB 符合要求\n", currentBlockSize/1024)
} else {
fmt.Printf("✗ 区块大小超出限制: %dKB > %dKB\n",
currentBlockSize/1024, maxBlockSize/1024)
}
}
3.4 逻辑运算符
| 运算符 | 描述 |
|---|---|
| && | 逻辑 AND 运算符。如果两边的操作数都是 True,则为 True,否则为 False。 |
| || | 逻辑 OR 运算符。如果两边的操作数有一个 True,则为 True,否则为 False。 |
| ! | 逻辑 NOT 运算符。如果条件为 True,则为 False,否则为 True。 |
实例案例1:
Go
package main
import "fmt"
func main() {
var age int = 40
// 演示逻辑运算符号:&&
if age > 30 && age < 50 {
fmt.Println("满足第一个条件。")
}
if age > 30 && age < 40 {
fmt.Println("不满足第一个条件,但是满足第二个条件。")
}
// 演示逻辑运算符号:||
if age > 30 || age < 50 {
fmt.Println("满足第三个条件。")
}
if age > 30 || age < 40 {
fmt.Println("满足第四个条件。")
}
// 演示逻辑运算符号:!
if age > 30 {
fmt.Println("满足第五个条件。")
}
if !(age > 30) {
fmt.Println("满足第六个条件")
}
}
实例案例2:
Go
package main
import "fmt"
func test() bool {
fmt.Println("test....")
return true
}
func main() {
var i int = 10
if i < 9 && test() {
fmt.Println("ok....")
}
if i > 9 || test() {
fmt.Println("Hello...")
}
}
实例案例3:
Go
package main
import "fmt"
type Validator struct {
Address string
IsActive bool
HasVoted bool
IsMalicious bool
}
type SmartContract struct {
Owner string
Admin string
Moderator string
}
func main() {
// 1. 多重签名验证(需要3个签名中的2个)
var sig1 bool = true
var sig2 bool = false
var sig3 bool = true
// 至少需要2个签名
if (sig1 && sig2) || (sig1 && sig3) || (sig2 && sig3) {
fmt.Println("✓ 多重签名验证通过")
} else {
fmt.Println("✗ 签名不足")
}
// 2. 验证者状态检查
validator := Validator{
Address: "0xval123",
IsActive: true,
HasVoted: false,
IsMalicious: false,
}
// 验证者必须活跃、未投票且不是恶意节点
if validator.IsActive && !validator.HasVoted && !validator.IsMalicious {
fmt.Println("✓ 验证者可以参与共识")
} else {
fmt.Println("✗ 验证者不符合条件")
}
// 3. 智能合约权限控制
contract := SmartContract{
Owner: "0xowner",
Admin: "0xadmin",
Moderator: "0xmod",
}
caller := "0xadmin"
// 只有Owner、Admin或Moderator可以调用
if caller == contract.Owner || caller == contract.Admin || caller == contract.Moderator {
fmt.Println("✓ 有权限调用合约")
} else {
fmt.Println("✗ 无权限")
}
// 4. 交易过滤器(组合条件)
var isWhitelisted bool = true
var hasSufficientGas bool = true
var isNotSpam bool = true
if isWhitelisted && hasSufficientGas && isNotSpam {
fmt.Println("✓ 交易可以通过mempool")
} else {
fmt.Println("✗ 交易被过滤")
}
// 5. 紧急暂停机制
var isEmergency bool = false
var isHacked bool = false
if !isEmergency && !isHacked {
fmt.Println("✓ 系统运行正常")
} else {
fmt.Println("⚠️ 触发紧急暂停")
}
}
3.5 赋值运算符
| 运算符 | 描述 | 区块链示例 | 代码示例 |
|---|---|---|---|
= |
简单赋值 | 设置区块哈希 | block.Hash = hash |
+= |
加后赋值 | 累计收益 | totalReward += reward |
-= |
减后赋值 | 扣除Gas费用 | balance -= gasFee |
*= |
乘后赋值 | 复利计算 | stake *= interestRate |
/= |
除后赋值 | 稀释代币 | price /= dilutionFactor |
%= |
取模后赋值 | 循环索引 | index %= validatorsCount |
&= |
位与后赋值 | 更新权限 | perms &= mask |
| ` | =` | 位或后赋值 | 添加权限 |
^= |
位异或后赋值 | 切换状态 | state ^= toggle |
<<= |
左移后赋值 | 缩放值 | value <<= 2 |
>>= |
右移后赋值 | 缩小值 | value >>= 2 |
示例代码1:
Go
package main
import "fmt"
type Miner struct {
Address string
Balance float64
TotalReward float64
HashRate int
}
type TokenPool struct {
TotalSupply float64
Price float64
Burned float64
}
func main() {
fmt.Println("=== 区块链赋值运算符示例 ===")
// 1. 矿工收益累计
miner := Miner{
Address: "0xminer123",
Balance: 10.5,
TotalReward: 0,
HashRate: 100,
}
// 挖到一个区块
blockReward := 2.0
miner.TotalReward += blockReward
miner.Balance += blockReward
fmt.Printf("矿工 %s 挖到区块,总收益: %.1f ETH\n",
miner.Address, miner.TotalReward)
// 2. 扣除Gas费用
gasFee := 0.025
miner.Balance -= gasFee
fmt.Printf("支付Gas费用后余额: %.3f ETH\n", miner.Balance)
// 3. 复利计算(PoS质押)
stakedAmount := 100.0
annualInterest := 0.05 // 5%
// 计算一年的复利
for i := 0; i < 12; i++ {
stakedAmount *= (1 + annualInterest/12)
}
fmt.Printf("一年后质押金额: %.2f ETH\n", stakedAmount)
// 4. 代币稀释(新增发行)
pool := TokenPool{
TotalSupply: 1000000,
Price: 1.0,
Burned: 0,
}
// 新增50%的代币供应
dilutionFactor := 1.5
pool.TotalSupply *= dilutionFactor
pool.Price /= dilutionFactor // 价格稀释
fmt.Printf("稀释后 - 总供应: %.0f, 价格: $%.4f\n",
pool.TotalSupply, pool.Price)
// 5. 循环验证者选择
validators := []string{"V1", "V2", "V3", "V4", "V5"}
currentIndex := 0
// 模拟选择下一个验证者
for i := 0; i < 10; i++ {
fmt.Printf("轮次 %d: 验证者 %s\n", i+1, validators[currentIndex])
currentIndex = (currentIndex + 1) % len(validators) // 循环
}
// 6. 权限更新
var permissions uint8 = READ | WRITE
fmt.Printf("\n原始权限: %08b\n", permissions)
// 移除写权限
permissions &^= WRITE
fmt.Printf("移除WRITE后: %08b\n", permissions)
// 添加执行权限
permissions |= EXECUTE
fmt.Printf("添加EXECUTE后: %08b\n", permissions)
// 7. Gas费用缩放(EIP-1559)
baseFeePerGas := 15 // Gwei
fmt.Printf("\n原始BASEFEE: %d Gwei\n", baseFeePerGas)
// 当网络拥堵时,BASEFEE增加12.5%
baseFeePerGas += baseFeePerGas >> 3 // 相当于 * 1.125
fmt.Printf("拥堵时BASEFEE: %d Gwei\n", baseFeePerGas)
// 当网络空闲时,BASEFEE减少12.5%
baseFeePerGas -= baseFeePerGas >> 3
fmt.Printf("空闲时BASEFEE: %d Gwei\n", baseFeePerGas)
// 8. 哈希率调整
fmt.Println("\n=== 哈希率动态调整 ===")
// 矿工根据难度调整哈希率
difficulty := 1000
targetHashRate := 100
// 如果难度增加,需要提高哈希率
if difficulty > 800 {
miner.HashRate <<= 1 // 哈希率翻倍
fmt.Printf("难度高,哈希率提升至: %d MH/s\n", miner.HashRate)
} else if difficulty < 200 {
miner.HashRate >>= 1 // 哈希率减半
fmt.Printf("难度低,哈希率降低至: %d MH/s\n", miner.HashRate)
}
}
实例代码2:
Go
package main
import "fmt"
func main() {
d := 8 + 2*8
fmt.Println(d)
x := 10
x += 5
fmt.Println("x += 5的值:", x)
y := 10
y -= 5
fmt.Println("y -= 5的值:", y)
n := 10.0
n /= 5
fmt.Println("n /= 5的值:", n)
m := 10
m %= 3
fmt.Println("x %= 3的值:", m)
}
3.6 运算符练习
练习 1:有两个变量,a 和 b,要求将其进行交换,最终打印结果。
Go
package main
import "fmt"
func main() {
var b int = 23
var a int = 12
var t int = 0
fmt.Printf("a的值为:%v,b的值为%v\n", a, b)
t = a
a = b
b = t
fmt.Printf("a的值为:%v,b的值为%v", a, b)
}
练习 2:假如还有 100 天放假,问:xx 个星期零 xx 天
Go
package main
import "fmt"
func main() {
var cou_days = 100
var weeks = cou_days / 7
var days = cou_days % 7
fmt.Printf("还有%v周,%v天", weeks, days)
}
练习 3:定义一个变量保存华氏温度,华氏温度转换摄氏温度的公式为:5/9*(华氏温度-100), 请求出华氏温度对应的摄氏温度。
Go
package main
import "fmt"
func main() {
var huashi float64 = 200
var sheshi float64 = 5.0 / 9 * (huashi - 100)
fmt.Printf("华氏温度%v,对应的摄氏温度为:%v", huashi, sheshi)
}
3.7 位运算符
位运算符在区块链中特别重要,常用于:
**(1)权限位掩码:**使用整数的二进制位来表示和验证多个权限标志,通过位运算高效检查、设置和清除权限。
区块链使用场景:
-
智能合约 的权限管理系统 :在ERC-721/ERC-1155 NFT合约中,用位掩码管理铸币、转移、暂停等权限,例如OpenZeppelin的AccessControl库使用
uint256存储256个不同角色的权限。 -
多签钱包权限控制:Gnosis Safe等多签钱包使用位掩码记录哪些地址已对交易签名,每位代表一个签名者的确认状态。
-
DAO 治理 投票 权重:将投票权限分解为不同类别(如提案创建、投票、资金管理等),通过位运算组合和验证。
**(2)状态压缩:**将多个布尔状态或有限状态变量打包存储在一个整数中,通过位运算读写,极大节省存储成本和Gas费用。
区块链使用场景:
-
NFT 属性存储优化 :将NFT的多个属性(是否可交易、是否锁定、稀有度等级等)压缩到一个
uint256中存储,避免为每个属性单独占用存储槽。 -
DeFi 协议用户状态管理:在借贷协议中,将用户的抵押、借款、清算状态打包存储,单次SSTORE操作更新多个状态。
-
Layer2状态证明:在ZK-Rollup中,将大量账户状态压缩为Merkle树叶子节点,使用位运算验证状态有效性。
(3)哈希计算优化:
在哈希函数和默克尔树计算中,使用位移和位掩码操作优化数据分块、填充和组合,提升计算性能和Gas效率。
区块链使用场景:
-
默克尔树证明验证:通过位移操作高效提取和组合哈希值的各个部分,验证默克尔证明时减少Gas消耗。
-
地址生成 与验证:从公钥计算以太坊地址时,使用位运算提取Keccak256哈希的最后20字节。
-
工作量证明(PoW)难度调整:在挖矿算法中,通过位移比较哈希值是否满足目标难度(比较前导零的数量)。
-
存储槽计算优化:在EVM存储布局中,使用位运算高效计算映射变量和数组的存储位置。
| 运算符 | 描述 | 区块链示例 | 代码示例 |
|---|---|---|---|
& |
按位与:参与运算的两数各对应的二进位相与。(两位均为1才为1) | 权限检查 | permissions & ADMIN |
| ` | ` | 按位或:参与运算的两数各对应的二进位相或。(两位有一个为1就为1) | 添加权限 |
^ |
按位 异或:参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。(两位不一样则为1) | 切换权限 | permissions ^ READ |
&^ |
位清空 | 移除权限 | permissions &^ MINT |
<< |
左移:左移 n 位就是乘以 2 的 n 次方。"a<<b" 是把 a 的各二进位全部左移 b 位,高位丢弃,低位补0。 | 创建掩码 | 1 << role |
>> |
右移:右移 n 位就是除以 2 的 n 次方。"a>>b" 是把 a 的各二进位全部右移 b 位。 | 提取值 | value >> 8 |
位运算符对整数在内存中的二进制位进行操作。
(1)& :两位均为 1 才为 1;
(2)| :两位有一个为 1 就为 1;
(3)^ :相异或两位不一样则为 1 ;
(4)<< :左移 n 位就是乘以 2 的 n 次方。
注意:"a<<b"是把 a 的各二进位全部左移 b 位,高位丢弃,低位补 0;
(5)>> :右移 n 位就是除以 2 的 n 次方;
案例实例1:
Go
package main
import "fmt"
func main() {
var a int = 5 // 101
var b int = 2 // 010
fmt.Println("a&b=", a&b) // 000 值 0
fmt.Println("a|b=", a|b) // 111 值 7
fmt.Println("a^b=", a^b) // 111 值 7
fmt.Println("5>>2=", a>>b) // 5 右移 2 位 1
fmt.Println("5<<2=", a<<b) // 5 左移 2 位 10100
fmt.Println("5<<1=", 5<<1) // 1010
fmt.Println("5>>1=", 5>>1) // 10
fmt.Println("7>>2=", 7>>2) // 1
}
位运算符 的主要场景:
一句话:Go 的位运算只干两件事------把数据当二进制切片与*"把布尔/标志压缩成一位,所以凡是要抠位、压空间、跑得快的地方就有它。
下面给出 7 个真实主流场景:
(1)秒级权限 / 特性标志(flag 字段)
Go
const (
FlagRead = 1 << 0 // 001
FlagWrite = 1 << 1 // 010
FlagExec = 1 << 2 // 100
)
func grant(flags uint8) bool { return flags & FlagWrite != 0 }()
(2)位掩码存多个 bool ,省 87 % 内存
Go
func set(mask *uint64, i int) { *mask |= 1 << i }
func test(mask uint64, i int) bool { return mask&(1<<i) != 0 }
(3) 网络协议 "拼包头"
IP 分片偏移、TCP 窗口、DNS 头部全是"几位放一段值":
Go
head := (version<<4 | ihl) << 24 | (tos<<16) | total
(4)哈希 & 布隆 过滤器
内部用 []uint64 位图,哈希值 h 定位:
Go
block := bits[h>>6] // 哪一块
mask := uint64(1) << (h & 63) // 哪一位
(5) 位操作 快速乘除 2 的 n 次方
Go
x <<= 3 // x *= 8
y >>= 4 // y /= 16
(6)交换两数不用第三方变量(面试技巧)
Go
package main
import (
"fmt"
"strconv"
)
func main() {
var a int = 12
var b int = 23
fmt.Printf("a = %v,b = %v,\n", a, b)
fmt.Printf("a:%v。b:%v\n", strconv.FormatInt(int64(a), 2), strconv.FormatInt(int64(b), 2))
a = a ^ b // a:01100 ^ b:10111 = 11011 a 的二进制为:11011
b = b ^ a // b:10111 ^ a:11011 = 01100 b 的二进制为:01100
a = a ^ b // a:11011 ^ b:01100 = 10111 a 的二进制为:10111
fmt.Printf("a的值为:%v,b的值为%v", a, b)
}
(7)计算汉明权重 / 1 的个数
Go
func popcount(x uint64) int {
x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555)
x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333)
x = (x & 0x0f0f0f0f0f0f0f0f) + (x >> 4 & 0x0f0f0f0f0f0f0f0f)
return int((x * 0x0101010101010101) >> 56)
}
口诀记忆:
"权限掩码哈希图,网络包头布隆滤;乘除用移位,布尔压位省内存"。
示例代码2:
Go
package main
import "fmt"
// 权限位掩码(使用位表示不同权限)
const (
NONE = 0 // 0000
READ = 1 << iota // 0001
WRITE // 0010
EXECUTE // 0100
ADMIN // 1000
ALL = READ | WRITE | EXECUTE | ADMIN // 1111
)
type User struct {
Address string
Permissions uint8
}
func main() {
fmt.Println("=== 区块链权限管理系统 ===")
// 1. 创建用户并设置权限
alice := User{Address: "0xalice", Permissions: READ | WRITE}
bob := User{Address: "0xbob", Permissions: READ}
admin := User{Address: "0xadmin", Permissions: ALL}
// 2. 检查权限
fmt.Printf("\nAlice 权限: %08b\n", alice.Permissions)
fmt.Printf("Bob 权限: %08b\n", bob.Permissions)
fmt.Printf("Admin 权限: %08b\n", admin.Permissions)
// 检查是否具有READ权限
if alice.Permissions&READ != 0 {
fmt.Println("✓ Alice 有读权限")
}
if bob.Permissions&WRITE == 0 {
fmt.Println("✗ Bob 没有写权限")
}
// 3. 添加权限
fmt.Println("\n给Bob添加写权限...")
bob.Permissions |= WRITE
fmt.Printf("Bob新权限: %08b\n", bob.Permissions)
if bob.Permissions&WRITE != 0 {
fmt.Println("✓ Bob 现在有写权限")
}
// 4. 移除权限
fmt.Println("\n移除Alice的写权限...")
alice.Permissions &^= WRITE
fmt.Printf("Alice新权限: %08b\n", alice.Permissions)
if alice.Permissions&WRITE == 0 {
fmt.Println("✗ Alice 已移除写权限")
}
// 5. 切换权限(有则移除,无则添加)
fmt.Println("\n切换Alice的执行权限...")
alice.Permissions ^= EXECUTE
fmt.Printf("Alice权限: %08b (添加EXECUTE)\n", alice.Permissions)
alice.Permissions ^= EXECUTE
fmt.Printf("Alice权限: %08b (移除EXECUTE)\n", alice.Permissions)
// 6. 区块链状态压缩示例
fmt.Println("\n=== 状态压缩示例 ===")
// 将多个布尔状态压缩到一个字节中
var nodeState uint8 = 0
// 设置状态位
isSyncing := true // 位0
isValidator := true // 位1
hasPeers := false // 位2
isMining := true // 位3
if isSyncing {
nodeState |= 1 << 0
}
if isValidator {
nodeState |= 1 << 1
}
if hasPeers {
nodeState |= 1 << 2
}
if isMining {
nodeState |= 1 << 3
}
fmt.Printf("节点状态字节: %08b\n", nodeState)
// 解压状态
fmt.Printf("正在同步: %v\n", (nodeState>>0)&1 == 1)
fmt.Printf("是验证者: %v\n", (nodeState>>1)&1 == 1)
fmt.Printf("有对等节点: %v\n", (nodeState>>2)&1 == 1)
fmt.Printf("正在挖矿: %v\n", (nodeState>>3)&1 == 1)
// 7. Gas费用计算优化(使用位移代替乘除)
fmt.Println("\n=== Gas优化计算 ===")
// 传统方式
gasPrice := 20 // Gwei
gasUsed := 21000
fee1 := gasPrice * gasUsed // 乘法
fmt.Printf("交易费用: %d Gwei\n", fee1)
// 使用位移优化(当乘除2的幂时)
// 例如:计算gas的1/1024(用于EIP-1559的BASEFEE)
baseFee := 15 // Gwei
scaledBaseFee := baseFee >> 10 // 除以1024
fmt.Printf("缩放后的BASEFEE: %d Gwei\n", scaledBaseFee)
}
3.8 其他运算符
| 运算符 | 描述 | 区块链示例 | 代码示例 |
|---|---|---|---|
& |
取地址 | 获取账户地址 | &account |
* |
指针解引用 | 访问合约状态 | *contract |
<- |
通道操作 | 区块链事件流 | event <- data |
: |
切片/范围 | 区块范围查询 | blocks[start:end] |
. |
成员访问 | 访问结构体字段 | block.Number |
... |
可变参数 | 验证多个签名 | verify(sigs...) |
示例代码:
Go
package main
import (
"fmt"
"time"
)
type Block struct {
Number uint64
Hash string
Timestamp int64
Txs []Transaction
}
type Transaction struct {
From string
To string
Value float64
}
// 模拟区块链事件
type BlockchainEvent struct {
Type string
Block Block
Message string
}
func main() {
fmt.Println("=== 其他运算符在区块链中的应用 ===")
// 1. 地址和指针操作
account := "0xabc123"
accountPtr := &account
fmt.Printf("账户地址: %s\n", account)
fmt.Printf("账户指针: %p\n", accountPtr)
fmt.Printf("通过指针访问: %s\n", *accountPtr)
// 2. 区块链事件通道
eventCh := make(chan BlockchainEvent, 10)
// 启动事件生产者(模拟区块生成)
go func() {
for i := 1; i <= 3; i++ {
block := Block{
Number: uint64(i),
Hash: fmt.Sprintf("0xblock%d", i),
Timestamp: time.Now().Unix(),
Txs: []Transaction{
{From: "0x1", To: "0x2", Value: 1.0},
},
}
event := BlockchainEvent{
Type: "NEW_BLOCK",
Block: block,
Message: fmt.Sprintf("区块 #%d 已生成", i),
}
eventCh <- event // 发送事件到通道
time.Sleep(500 * time.Millisecond)
}
close(eventCh)
}()
// 事件消费者
fmt.Println("\n监听区块链事件:")
for event := range eventCh {
fmt.Printf("事件: %s - %s\n", event.Type, event.Message)
fmt.Printf(" 区块哈希: %s\n", event.Block.Hash)
}
// 3. 切片操作:查询区块范围
fmt.Println("\n=== 区块范围查询 ===")
// 创建模拟区块链
var blockchain []Block
for i := 0; i < 10; i++ {
blockchain = append(blockchain, Block{
Number: uint64(i + 1000),
Hash: fmt.Sprintf("0xhash%d", i),
})
}
// 查询区块 1002-1005
startIndex := 2
endIndex := 6
blockRange := blockchain[startIndex:endIndex]
fmt.Printf("查询区块范围 %d-%d:\n",
blockchain[startIndex].Number,
blockchain[endIndex-1].Number)
for _, block := range blockRange {
fmt.Printf(" 区块 #%d: %s\n", block.Number, block.Hash)
}
// 4. 结构体成员访问
fmt.Println("\n=== 智能合约状态访问 ===")
type SmartContract struct {
Owner string
Balance float64
IsActive bool
}
contract := SmartContract{
Owner: "0xowner123",
Balance: 1000.0,
IsActive: true,
}
// 使用点运算符访问成员
fmt.Printf("合约所有者: %s\n", contract.Owner)
fmt.Printf("合约余额: %.1f ETH\n", contract.Balance)
// 5. 可变参数:批量验证签名
fmt.Println("\n=== 多重签名验证 ===")
// 验证多个签名
verifySignatures := func(signatures ...bool) bool {
validCount := 0
for _, sig := range signatures {
if sig {
validCount++
}
}
return validCount >= 2 // 至少需要2个有效签名
}
// 三个签名者,两个有效
sig1, sig2, sig3 := true, false, true
if verifySignatures(sig1, sig2, sig3) {
fmt.Println("✓ 多重签名验证通过")
} else {
fmt.Println("✗ 签名不足")
}
// 也可以传递切片
sigs := []bool{true, true, false, false}
if verifySignatures(sigs...) {
fmt.Println("✓ 批量签名验证通过")
}
// 6. 类型断言(接口操作)
fmt.Println("\n=== 智能合约接口 ===")
type Token interface {
Transfer(to string, amount float64) bool
BalanceOf(owner string) float64
}
type ERC20 struct {
Name string
}
func (e *ERC20) Transfer(to string, amount float64) bool {
fmt.Printf("ERC20转账: %s -> %s 金额: %.1f\n", e.Name, to, amount)
return true
}
func (e *ERC20) BalanceOf(owner string) float64 {
return 100.0
}
var token Token = &ERC20{Name: "MyToken"}
// 类型断言检查
if erc20, ok := token.(*ERC20); ok {
fmt.Printf("Token类型: %s\n", erc20.Name)
erc20.Transfer("0xrecipient", 10.0)
}
}
3.9 运算符优先级总结表
| 优先级 | 运算符 | 描述 | 区块链应用 |
|---|---|---|---|
| 1 | () [] . |
括号、索引、成员访问 | block.Txs[0].Value |
| 2 | * 、/、 %、 << 、>>、 &、 &^ |
乘除、位移、位运算 | reward * blocks << 2 |
| 3 | + - ` |
^` |
加减、位或、位异或 |
| 4 | == 、!= 、< <= 、> >= |
关系比较 | balance >= amount |
| 5 | && |
逻辑与 | valid && signed && funded |
| 6 | ` | ` | |
| 7 | =、``+=、 -=、 *=、 etc. |
赋值运算 | total += reward |
优先级示例:
Go
// 复杂的区块链计算公式
func calculateValidatorReward(blocksMined int, baseReward float64,
commissionRate float64, isActive bool) float64 {
// 注意运算符优先级
reward := float64(blocksMined)*baseReward*(1+commissionRate)
// 等同于
reward = (float64(blocksMined) * baseReward) * (1 + commissionRate)
// 使用括号明确优先级
if isActive && blocksMined > 0 || commissionRate > 0 {
return reward
}
return 0
}
3.10 区块链专用运算符技巧
(1)Gas优化技巧
Go
// 使用位移代替乘除(当除数是2的幂时)
func calculateGasRefund(gasUsed int) int {
// 传统方式
// refund := gasUsed / 2
// 优化方式
refund := gasUsed >> 1 // 除以2
return refund
}
// 快速判断是否为2的幂(用于分片)
func isPowerOfTwo(n int) bool {
return n > 0 && (n&(n-1)) == 0
}
(2)权限检查优化
Go
// 一次性检查多个权限
func hasAllPermissions(userPerms, requiredPerms uint32) bool {
return userPerms & requiredPerms == requiredPerms
}
// 检查至少一个权限
func hasAnyPermission(userPerms, checkPerms uint32) bool {
return userPerms & checkPerms != 0
}
(3)区块链ID生成
Go
// 使用位运算组合生成唯一ID
func generateTxID(blockNum uint64, txIndex uint32) uint64 {
// 将区块号放在高位,交易索引放在低位
return (blockNum << 32) | uint64(txIndex)
}
// 解析ID
func parseTxID(txID uint64) (blockNum uint64, txIndex uint32) {
blockNum = txID >> 32
txIndex = uint32(txID & 0xFFFFFFFF)
return
}
通过以上详细的讲解和区块链相关的示例,你应该能够全面掌握Go语言运算符的使用,并理解它们在区块链开发中的实际应用。运算符是编程的基础,但在区块链这种对性能和安全性要求极高的领域,正确、高效地使用运算符尤为重要。