# 【Solidity 入门教学】一周搞定基础语法:每天 2 小时的实战学习指南

对于想入门区块链智能合约开发的同学,Solidity 是必须掌握的核心语言。今天给大家拆解一份 **“每天 2 小时、连续 6 天” 的 Solidity 基础语法学习计划 **—— 不仅讲知识点,更带大家一步步写代码,帮你从 “概念” 落地到 “实操”。

# 计划总览:用 6 天搭好 Solidity 基础框架

这张学习表是典型的 “从基础到整合” 的入门路径:先学变量、再学复杂数据结构、然后写函数、加逻辑控制、最后整合成完整合约。每天的 “学习内容” 是理论,“实操任务” 是落地,咱们逐个拆解。

# Day1:值类型变量 —— 智能合约的 “基础数据单元”

# 学习内容解读

Solidity 是强类型语言,变量必须先声明类型再使用。Day1 学的是 “值类型”(存储具体数值,而非引用地址),核心类型包括:

  • uint256 :无符号整数(常用作金额、数量,比如代币数量)

  • address :以太坊账户地址(相当于 “用户唯一 ID”)

  • bool :布尔值(仅 true/false ,用于状态判断,比如 “账户是否激活”)

  • string :字符串(存储文本,比如用户名)

# 实操任务教学(附代码)

目标:写一个存变量、赋值并打印的合约

  1. 新建合约文件 Variables.sol

  2. 写入代码(注意导入 Hardhat 的 console 工具):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19; // 指定Solidity版本

import "hardhat/console.sol"; // 导入console工具用于打印

contract Variables {
// 声明值类型变量(public修饰会自动生成读取函数)
uint256 public amount; // 金额
address public userAddr; // 用户地址
bool public isActive; // 是否激活

// 构造函数:部署合约时执行,给变量赋值
constructor() {
amount = 100 ether; // ether是单位,100 ether = 100*10^18 wei
userAddr = msg.sender; // msg.sender是部署者地址
isActive = true;

// 打印变量(部署后在Hardhat控制台能看到输出)
console.log(unicode"初始金额:", amount);
console.log(unicode"部署者地址:", userAddr);
console.log(unicode"是否激活:", isActive);
}
}

在 Remix 左侧的「SOLIDITY COMPILER」标签下:

  1. 确认编译器版本是 0.8.19 左右(和代码里的 pragma 版本匹配);
  2. 点击「Compile variables.sol」按钮,等待编译完成(如果没报错,按钮会变成绿色)。

# 步骤 3:部署合约

切换到左侧的「DEPLOY & RUN TRANSACTIONS」标签(小火箭图标):

  1. 「Environment」选择「Remix VM (London)」(Remix 的本地测试环境);
  2. 「CONTRACT」下拉框选择「Variables」;
  3. 点击「Deploy」按钮,等待部署完成。

# 步骤 4:测试变量

部署完成后,在「Deployed Contracts」区域会出现你的 Variables 合约:

  • 点击 amount 按钮:会显示 100000000000000000000 (这是 100 ether 对应的 wei 值);
  • 点击 userAddr 按钮:会显示当前部署者的测试地址;
  • 点击 isActive 按钮:会显示 true

111

完成这一步,你就搞定了 Day1 的实操任务

# Day2:引用类型 —— 管理复杂数据的 “容器”

# 学习内容解读

当需要存储 “一组相关数据”(比如用户的姓名、年龄、余额),或 “批量数据” 时,要用引用类型

  • struct :自定义结构体(把多个字段打包成一个类型,比如 User

  • mapping :键值对映射(类似字典,常用 address → 结构体 存用户数据)

  • array :数组(存储多个同类型数据,比如 “所有用户的地址列表”)

  • 关键区分: storage (合约的 “持久存储”,写在区块链上) vs memory (函数的 “临时内存”,执行完就销毁)

# 实操任务教学(附代码)

目标:用 struct、mapping、array 存储用户数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract UserData {
// 1. 定义struct:打包用户信息
struct User {
string name; // 姓名
uint age; // 年龄
uint balance; // 余额
}

// 2. mapping:用地址映射到User(存储单个用户)
mapping(address => User) public userMap;

// 3. array:存储所有用户的地址(方便遍历)
address[] public userAddrs;
}

# Day3:函数 —— 合约的 “功能操作入口”

# 学习内容解读

函数是合约的 “逻辑执行单元”,核心要掌握 3 点:

  • 定义格式: 可见性 函数名(参数类型 参数名) returns(返回类型)

  • 返回值: return (返回具体值)/ returns (声明返回类型)

  • 可见性(控制谁能调用函数):

    • public :合约内外都能调用

    • external :仅外部(比如其他合约、前端)能调用

    • internal :仅当前合约 / 继承合约能调用

    • private :仅当前合约能调用

# 实操任务教学(附代码)

目标:写 “查询用户” 和 “添加用户” 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 接上面UserData合约的代码
contract UserData {
// ...(struct、mapping、array的代码省略)

// 1. 查询用户:根据地址返回User结构体
function getUserInfo(address _user) public view returns(User) {
return userMap[_user];
}

// 2. 添加用户:传入姓名、年龄,给当前调用者创建用户
function addUser(string memory _name, uint _age) public {
// 给mapping赋值(storage类型)
userMap[msg.sender] = User({
name: _name,
age: _age,
balance: 0 // 初始余额0
});
// 把地址加入array
userAddrs.push(msg.sender);
}
}

view 是 Solidity 中函数的只读修饰符 —— 给函数加了 view,就意味着这个函数只能读取合约的状态变量,不能修改任何区块链上的数据(比如不能改状态变量的值、不能触发事件、不能转账等)。

  1. 为什么要用 view?​
  • 节省 gas 费:区块链上 “读取数据” 不需要消耗 gas(因为不用写入区块),而 “修改数据” 需要消耗 gas(要记录到区块中)。加了 view 的函数,调用时不会产生 gas 费用(仅外部调用时,合约内部调用不影响)。

  • 明确函数用途:告诉开发者 / 编译器,这个函数是 “查询用” 的,不会改变合约状态,避免误操作。

测试可见性:比如把 addUser 改成 private ,部署后外部调用会直接报错。

# Day4:控制流 + 修饰符 —— 让合约 “有逻辑、有权限”

# 学习内容解读

  • 控制流:用 if-else 做条件判断、 for 做循环(比如遍历数组)

  • 修饰符( modifier ):代码复用 + 权限控制的工具(比如 onlyOwner 仅让合约部署者调用函数)

# 实操任务教学(附代码)

目标:写 “转账函数”+“仅 owner 可用” 的修饰符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 接上面UserData合约的代码
contract UserData {
// 先定义owner变量
address public owner;

// 构造函数:部署时把owner设为部署者
constructor() {
owner = msg.sender;
}

// 1. 定义onlyOwner修饰符
modifier onlyOwner() {
// require是“断言”:不满足条件就回滚交易
require(msg.sender == owner, "你不是合约拥有者");
_; // 表示“执行被修饰的函数代码”
}

// 2. 转账函数:用if-else判断余额
function transferBalance(address _to, uint _amount) public onlyOwner {
// 判断调用者余额是否足够
if (userMap[msg.sender].balance >= _amount) {
// 扣自己余额
userMap[msg.sender].balance -= _amount;
// 加对方余额
userMap[_to].balance += _amount;
}
}
}

  • onlyOwner 修饰符加在函数后,调用函数前会先执行修饰符的逻辑。

# Day5:合约结构 + 事件 —— 让合约 “可监控”

# 学习内容解读

合约的核心组成:

  • 状态变量:定义在合约内、函数外的变量(存在区块链上,持久存储)

  • 局部变量:定义在函数内的变量(存在 memory,临时存储)

  • 事件( Event ):合约 “状态变化的通知”—— 前端可以监听事件,实时获取合约数据(比如 “新用户添加了”)

# 实操任务教学(附代码)

目标:给 “添加用户” 函数加事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 接上面UserData合约的代码
contract UserData {
// 1. 定义事件(indexed可以让前端按该字段过滤)
event UserAdded(address indexed _user, string _name);

// 2. 改造addUser函数:触发事件
function addUser(string memory _name, uint _age) public {
userMap[msg.sender] = User({
name: _name,
age: _age,
balance: 0
});
userAddrs.push(msg.sender);

// emit触发事件
emit UserAdded(msg.sender, _name);
}
}

  • 前端监听:比如用 Ethers.js 监听 UserAdded 事件,就能实时收到新用户的地址和姓名。

# Day6:语法复盘 —— 写一个完整的 “用户管理合约”

# 学习内容解读

把前 5 天的知识点整合:写一个包含 “添加用户、查询信息、修改年龄(仅 owner)” 的完整合约,然后在 Remix(在线 Solidity 编译器)中验证。

# 实操任务教学(完整代码)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract UserManager {
// 1. 结构体
struct User {
string name;
uint age;
uint balance;
}

// 2. 状态变量
mapping(address => User) public userMap;
address[] public userAddrs;
address public owner;

// 3. 事件
event UserAdded(address indexed _user, string _name);

// 4. 构造函数
constructor() {
owner = msg.sender;
}

// 5. 修饰符
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}

// 6. 添加用户
function addUser(string memory _name, uint _age) public {
userMap[msg.sender] = User({
name: _name,
age: _age,
balance: 0
});
userAddrs.push(msg.sender);
emit UserAdded(msg.sender, _name);
}

// 7. 查询用户
function getUserInfo(address _user) public view returns(User) {
return userMap[_user];
}

// 8. 修改年龄(仅owner)
function updateUserAge(address _user, uint _newAge) public onlyOwner {
userMap[_user].age = _newAge;
}
}

  • Remix 编译步骤:打开 Remix 官网 → 新建文件粘贴代码 → 选对应 Solidity 版本 → 点 “Compile” → 无报错即成功。

# 写在最后:这一周能收获什么?

跟着这个计划学完,你已经掌握了 Solidity 的核心基础:从变量、函数到合约结构,从逻辑控制到权限管理,甚至能写一个简单的 “用户管理合约”。