# Solidity基础概念的区分——可见性 **Published by:** [albertma](https://paragraph.com/@albertma-2/) **Published on:** 2022-06-17 **URL:** https://paragraph.com/@albertma-2/solidity ## Content Solidity作为一个图灵完备的编程语言,跟javascript还有这诸多相似之处。作为目前主流的智能合约语言,有着易学,易用的特点。但是由于区块链的早期阶段和EVM的早期阶段,所有有着各种概念需要区分。 首先讲一下可见性,可见性分为变量可见性和函数可见性。 对于变量的private,public, internal 对于public变量,会自动生成getter函数 //solidity source codes contract Token{ string public name = "Hardhat Token"; string public symbol = "HHT"; .... } //javascript describe("getter test", function(){ it("getter test", async function(){ const name = await token.name(); console.log("name: "+ name); }); }); 不会默认生成setter函数,内部直接访问name internal 内部可见性变量, 可以在派生和本合约内访问。 private 本合约内部可见,派生合约不可见。 值得注意的是无论是internal, private,还是public都可以通过getStorageA(index)的方式,从区块链节点获取变量的内容,所以不要将confidential的内容上传到blockchain上。 对于函数而言的public,private,external, internal public public 函数是合约接口的一部分,可以在内部或通过消息调用。Java中含义一致。函数默认是public。 private 只能在当前合约内部访问,外部和派生的合约是无法访问的。这个与java的private含义也是一致的。 external external标识的函数是合约接口的一部分。函数只能通过外部的方式调用。外部函数在接收大的数组时更有效。Java中无与此对应的关键字。 internal 函数只能通过内部访问(当前合约或者继承的合约),可在当前合约或继承合约中调用。类似于Java的protected。 这里最让人迷惑的其实就是public和external,有了public为什么还要提供external呢? 这里涉及到一个概念叫calldata,就是在交易中发出交易的data部分。 当使用external的时候,函数不会对参数进行copy,仅仅从calldata引用就可以了。 当使用public的时候,函数会对参数进行复制操作。public为了支持从内部和从外部两种调用方式,所以要一视同仁的进行参数拷贝。 所以如果你能确认只有外部调用,那么就使用external,这样可以为你节省不少gas。 以下是calldata的说明 go-ethereum https://github.com/ethereum/go-ethereum/blob/01e5e9c2c3fa1cf7a9747148dca22d59ff9839b6/core/types/transaction.go#L71 以上是Transaction部分的源码,有兴趣可以自己看。 ## Publication Information - [albertma](https://paragraph.com/@albertma-2/): Publication homepage - [All Posts](https://paragraph.com/@albertma-2/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@albertma-2): Subscribe to updates - [Twitter](https://twitter.com/Albert_B_Ma): Follow on Twitter