【Solidity 从入门到精通】第3章 Solidity 基础语法详解

本章将深入讲解 Solidity 的语言结构与基本语法,让你从"能看懂"走向"能写出"。我们将探索变量、数据类型、函数、可见性、事件、修饰符等概念,用生动的比喻、清晰的表格和实战示例帮助你理解。通过构建一个简单的"留言墙(Message Wall)"智能合约,你将掌握状态与内存变量的区别、函数的 Gas 成本、事件的日志机制,以及 Solidity 编程的独特思维方式。这一章是你成为 Solidity 开发者的真正起点。

关键词: 变量作用域、数据类型、函数修饰符、事件、状态管理


3.1 语言基础概览:Solidity 的语法风格

"Solidity 看起来像 JavaScript,却更像法律文件。"

Solidity 的语法灵感来源于 JavaScript、C++ 和 Python。

它像 JS 一样使用大括号 {},但又像 C 一样严格定义类型。

如果你熟悉这些语言,你会觉得 Solidity "似曾相识",但又"处处不同"。


🧠 Solidity 与常见语言语法对比

特性 JavaScript Solidity 备注
变量声明 let a = 1; uint a = 1; Solidity 要声明类型
数组 [1, 2, 3] uint[] nums = [1,2,3]; 固定/动态长度皆可
字符串 "hello" "hello" 字符串不能直接拼接
函数定义 function add(a,b){} function add(uint a, uint b) public returns(uint){} 必须声明可见性与返回值
class contract 合约即类

Solidity 就像"严格模式的 JavaScript",

但它运行在全球分布式计算机网络上


3.2 数据类型与变量:区块链上的存储单位

"每一个变量,都是写进账本的墨迹。"

🧩 Solidity 中的主要数据类型

类型分类 示例 说明
整数类型 uint256, int8 uint 表示无符号整数(0或正数)
布尔类型 bool truefalse
地址类型 address 表示账户地址(钱包/合约)
字符串 string 存储文本
固定字节数组 bytes1 ~ bytes32 固定长度的二进制数据
动态数组 uint[], string[] 可扩展集合
映射(mapping) mapping(address => uint) 类似字典或哈希表
结构体(struct) 自定义类型 类似类的简单形式

📦 状态变量与局部变量

  • 状态变量(State Variable)
    保存在区块链上,修改它需要交易与 Gas。
  • 局部变量(Local Variable)
    保存在内存中,只在函数执行时存在,不上链。
solidity 复制代码
pragma solidity ^0.8.0;

contract VariableDemo {
    uint public counter = 0; // 状态变量

    function increase() public {
        uint temp = counter; // 局部变量
        temp += 1;
        counter = temp; // 写回区块链(消耗 Gas)
    }
}
操作类型 存储位置 是否消耗 Gas 生命周期
状态变量 区块链存储(storage) ✅ 是 永久保存
局部变量 内存(memory) ❌ 否 函数执行期间
常量 编译时写死 ❌ 否 永久不变

💡 "Storage、Memory、Calldata"的区别图解

复制代码
+----------------------------------------------------------+
| 区块链永久存储 (Storage) → 状态变量                     |
| 函数临时存储 (Memory) → 临时对象                        |
| 只读外部数据 (Calldata) → 外部函数参数                  |
+----------------------------------------------------------+

可简单理解为:

  • storage:存到硬盘;
  • memory:存到内存;
  • calldata:传参快递箱。

3.3 函数与可见性修饰符

"在 Solidity 世界中,函数不仅定义行为,也定义信任边界。"

🧠 函数的定义格式

solidity 复制代码
function functionName(type parameter) 
    visibility 
    stateMutability 
    returns(type) 
{
    // 函数体
}

例如:

solidity 复制代码
function add(uint a, uint b) public pure returns(uint) {
    return a + b;
}

📜 可见性(Visibility)关键字

修饰符 说明 谁能调用 类比
public 任何人可调用 所有用户与合约 公共服务
external 仅外部调用 外部账户 API 接口
internal 合约内部可见 继承合约 保护函数
private 当前合约内部 无法继承 私有函数

💧 状态修饰符(State Mutability)

关键字 说明 是否修改状态 是否消耗 Gas
pure 不读不写
view 只读
(无修饰) 可写
payable 可接收 ETH

示例:

solidity 复制代码
function getCounter() public view returns(uint) {
    return counter;
}

function add(uint a, uint b) public pure returns(uint) {
    return a + b;
}

function receiveEther() public payable {
    // 可接收 ETH
}

3.4 修饰符(Modifier):智能合约的"守门员"

"Modifier 是 Solidity 的防线,用来设定进入规则。"

修饰符(modifier)允许你在函数执行前后添加条件逻辑。

比如:只有管理员能执行某个函数。

solidity 复制代码
modifier onlyOwner() {
    require(msg.sender == owner, "Not authorized");
    _;
}

_ 表示函数主体在此处执行。

在函数中使用:

solidity 复制代码
function withdraw() public onlyOwner {
    payable(owner).transfer(address(this).balance);
}

执行流程图:

复制代码
调用函数 → 检查 onlyOwner → 如果通过 → 执行函数体

(图3-1:Modifier 执行流程)


3.5 事件(Event):区块链的日志系统

"区块链没有数据库,但它有事件日志。"

事件是 Solidity 用来在区块链上记录活动的机制。

类似于后端日志(log),但会被写入链上。

solidity 复制代码
event NewMessage(address indexed sender, string content);

function postMessage(string memory content) public {
    emit NewMessage(msg.sender, content);
}

事件会在区块中被永久记录,可被 DApp 前端监听。

前端可通过 ethers.jsweb3.js 读取事件日志。


事件元素 说明
event 声明事件
emit 触发事件
indexed 可检索字段
区块日志 可供前端监听

3.6 实战项目:构建一个"留言墙(Message Wall)"智能合约

"从一句留言,开始你的链上交流。"

让我们结合本章所学,写一个完整可运行的项目。

这个合约允许用户:

  • 留下留言;
  • 记录留言者地址;
  • 触发事件;
  • 读取所有留言。

💬 合约代码

solidity 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract MessageWall {
    struct Message {
        address sender;
        string text;
        uint timestamp;
    }

    Message[] public messages;
    address public owner;

    event NewMessage(address indexed sender, string text, uint timestamp);

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    constructor() {
        owner = msg.sender;
    }

    function postMessage(string memory _text) public {
        messages.push(Message(msg.sender, _text, block.timestamp));
        emit NewMessage(msg.sender, _text, block.timestamp);
    }

    function getMessagesCount() public view returns (uint) {
        return messages.length;
    }

    function clearMessages() public onlyOwner {
        delete messages;
    }
}

🧩 功能说明表

函数 功能 修饰符 Gas 成本
postMessage() 发布新留言
getMessagesCount() 查询留言数 view
clearMessages() 删除所有留言 onlyOwner

🧠 运行逻辑示意图

复制代码
用户 → postMessage() → 写入 messages[] → emit NewMessage() → 区块链事件日志

(图3-2:MessageWall 执行流程)


3.7 区块链思维:为什么写入成本高?

"区块链上的每一个字节,都是全球共识的成本。"

当你写入一条留言时:

  • 所有节点都要保存这条信息;
  • 共识算法要验证这条交易;
  • 因此写入成本(Gas)远高于传统数据库。

阅读(view)是免费的,写入是昂贵的。

这也引出了区块链的设计哲学:
计算要轻,存储要少,逻辑要明。


3.8 小结与思考

本章你学会了:

  • Solidity 的基本语法与类型;
  • 函数可见性与状态修饰符;
  • 使用修饰符定义权限;
  • 事件机制;
  • 构建完整留言墙项目。

📘 思考练习

  1. MessageWall 添加一个 like 功能,每条留言可被点赞。
  2. 实现留言分页查询函数。
  3. 使用事件记录点赞行为。
  4. 通过 MetaMask 将合约部署到测试网。

下一章预告:

第4章《Solidity 进阶特性与合约间交互》

我们将探索继承、多态、接口(Interface)、抽象合约、库(Library),以及合约之间如何互相调用。

这将是从"代码逻辑"迈向"智能生态"的关键一步。

相关推荐
leijiwen3 小时前
S11e Protocol 数字身份体系架构白皮书
架构·web3·区块链·品牌·rwa
野老杂谈3 小时前
【Solidity 从入门到精通】第2章 Solidity 语言概览与环境搭建
web3·区块链·智能合约·solidity·remix ide
MicroTech202521 小时前
微算法科技(NASDAQ MLGO):DPoS驱动区块链治理与DAO机制融合,共筑Web3.0坚实基石
科技·web3·区块链
野老杂谈1 天前
【Solidity 从入门到精通】前言
web3·智能合约·solidity·以太坊·dapp
Web3_Daisy2 天前
消除链上气泡图:为什么换仓正在成为新的链上生存策略?
大数据·人工智能·安全·web3·区块链
许强0xq2 天前
Solidity 的十年与重生:从 Classic 到 Core
web3·区块链·智能合约·solidity·以太坊
小攻城狮长成ing3 天前
从0开始学区块链第12天—如何使用可见性标识符
web3·区块链·智能合约·solidity·以太坊
小小测试开发3 天前
Python Web3库入门:从零开始与以太坊区块链交互
python·web3·区块链
Web3_Daisy4 天前
从透明到可控:链上换仓与资产路径管理的下一阶段
人工智能·安全·web3·区块链·比特币