{"content":{"title":"Solidity 存储变量","body":"到目前为止，我们所有的函数都只是返回纯粹依赖于函数参数的值。它们不依赖于除立即输入之外的任何内容。这就是为什么它们被称为**纯**函数。它们不知道区块链的状态或过去发生的任何事情。\r\n\r\n如果我们要跟踪某些内容，比如某人欠了多少钱，或者他们在游戏中有多少分数，这将会非常成问题。\r\n\r\n现在我们介绍**存储变量**。\r\n\r\n这些变量看起来像其他语言中的“类变量”，但行为并不像它们。你可以将它们视为**行为类似于微型数据库的变量**。\r\n\r\n让我们看一个例子\r\n\r\n```solidity\r\n\r\ncontract ExampleContract {\r\n\r\n    uint256 internal x;\r\n\r\n    function setX(\r\n        uint256 newValue\r\n    )\r\n        public {\r\n            x = newValue;\r\n    }\r\n\r\n    function getX()\r\n        public\r\n        view\r\n        returns (uint256) {\r\n            return x;\r\n    }\r\n}\r\n\r\n```\r\n\r\n我们有很多东西要解释！\r\n\r\n**在函数外声明的变量是存储变量。它们在交易结束后仍然保留其值。**\r\n\r\n注意**`getX()`**有修饰符**`view`**，而不是**`pure`**。这是因为它会查看区块链的状态，即存储在变量`x`中的内容。如果你在这个例子中将`view`改为`pure`，代码将无法编译。你也可以将**view**视为**只读**。还要注意`getX`的返回值与`x`的类型相同，都是`uint256`。\r\n\r\n其次，请注意**`setX`**没有`view`或`pure`修饰符。这是因为它是一个**状态改变函数**。改变存储变量或对区块链进行其他持久性更改的函数不能有`view`或`pure`修饰符，因为它们不是**只读**的，因此不能被标记为`view`，当然也不能标记为**`pure`**。\r\n\r\n为了强调这一点，请注意以下代码是无效的\r\n\r\n```solidity\r\n\r\ncontract ExampleContract {\r\n\r\n    uint256 internal x;\r\n\r\n    function setX(\r\n        uint256 newValue\r\n    )\r\n        public {\r\n            x = newValue;\r\n    }\r\n\r\n    // error: this function cannot be pure\r\n    function getX()\r\n        public\r\n        pure\r\n        returns (uint256) {\r\n            return x;\r\n    }\r\n}\r\n\r\n```\r\n\r\n请注意，变量`x`本身有修饰符**`internal`**。这意味着其他智能合约无法看到这个值。\r\n\r\n**变量是`internal`的并不意味着它是隐藏的。它仍然存储在区块链上，任何人都可以通过解析区块链来获取该值！**\r\n\r\n这才是事情变得令人困惑的地方。\r\n\r\n以下代码也是有效的，但它被认为是**不好的做法**。\r\n\r\n```solidity\r\n\r\ncontract ExampleContract {\r\n\r\n    uint256 x;\r\n\r\n    function setX(\r\n        uint256 newValue\r\n    )\r\n        public {\r\n            x = newValue;\r\n    }\r\n\r\n    function getX()\r\n        public\r\n        view\r\n        returns (uint256) {\r\n            return x;\r\n    }\r\n}\r\n\r\n```\r\n\r\n在这种情况下，我们去掉了`x`的`internal`修饰符，它仍然可以编译。这被认为是不好的做法，因为你没有明确表达`X`的可见性意图。\r\n\r\n以下代码也是有效的\r\n\r\n```solidity\r\n\r\ncontract ExampleContract {\r\n\r\n    uint256 public x;\r\n\r\n    function setX(\r\n        uint256 newValue\r\n    )\r\n        public {\r\n            x = newValue;\r\n    }\r\n\r\n    function getX()\r\n        public\r\n        view\r\n        returns (uint256) {\r\n            return x;\r\n    }\r\n}\r\n\r\n```\r\n\r\n**当变量被声明为`public`时，意味着其他智能合约可以读取该值但不能修改它。**\r\n\r\n这很令人困惑，因为`public`函数可以修改变量，但`public`变量不能被修改，除非有一个函数来改变它们的值。\r\n\r\n**总结**\r\n\r\n- 存储变量在函数外声明\r\n- 没有`view`或`pure`修饰符的public函数可以改变存储变量\r\n- 纯函数不能访问存储变量\r\n\r\n* * *\r\n\r\n**练习题目**\r\n\r\n[PublicVariable](https://github.com/RareSkills/Solidity-Exercises/tree/main/PublicVariable)\r\n\r\n[BasicStorage](https://github.com/RareSkills/Solidity-Exercises/blob/main/BasicStorage/src/BasicStorage.sol)\r\n\r\n[PublicFunction](https://github.com/RareSkills/Solidity-Exercises/tree/main/PublicFunction)\r\n\r\n[PureVsView](https://github.com/RareSkills/Solidity-Exercises/tree/main/PureVsView)\r\n\r\n### 更多学习资源\r\n\r\n请查看 [Web3 区块链培训营](https://learnblockchain.cn/openspace/1)，了解更多关于智能合约开发和代币标准的信息。\r\n\r\n \r\n\r\n>- 原文链接： [rareskills.io/learn-soli...](https://www.rareskills.io/learn-solidity/storage-variables)\r\n>- 登链社区 AI 助手，为大家转译优秀英文文章，如有翻译不通的地方，还请包涵～"},"author":{"user":"https://learnblockchain.cn/people/20722","address":null},"history":null,"timestamp":1740576853,"version":1}