【WEB3.0零基础转行笔记】Golang编程篇-第3讲:GO语言中的运算符

目录

[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语言运算符的使用,并理解它们在区块链开发中的实际应用。运算符是编程的基础,但在区块链这种对性能和安全性要求极高的领域,正确、高效地使用运算符尤为重要。

相关推荐
小二·2 小时前
Go 语言系统编程与云原生开发实战(第9篇)安全加固实战:认证授权 × 数据加密 × 安全审计(生产级落地)
安全·云原生·golang
小高Baby@2 小时前
Go中常用字段说明
后端·golang·gin
ajole2 小时前
Linux学习笔记——基本指令
linux·服务器·笔记·学习·centos·bash
UQI-LIUWJ2 小时前
Langchain笔记:模型
笔记·langchain
傻小胖2 小时前
19.ETH-挖矿算法-北大肖臻老师客堂笔记
笔记·算法·区块链
紫罗兰盛开2 小时前
招商银行股票分析
经验分享·笔记
方安乐2 小时前
react笔记之useCallback/useEffect闭包陷阱
前端·笔记·react.js
小二·2 小时前
Go 语言系统编程与云原生开发实战(第8篇)消息队列实战:Kafka 事件驱动 × CQRS 架构 × 最终一致性(生产级落地)
云原生·golang·kafka
蒸蒸yyyyzwd10 小时前
cpp对象模型学习笔记1.1-2.8
java·笔记·学习