# Solidity基础概念的区分——可见性

By [albertma](https://paragraph.com/@albertma-2) · 2022-06-17

---

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://storage.googleapis.com/papyrus_images/0838edcf0e1499a21c03f2c97cf5e434772958866c8ddc605075670b58cf2a55.png)

go-ethereum

[https://github.com/ethereum/go-ethereum/blob/01e5e9c2c3fa1cf7a9747148dca22d59ff9839b6/core/types/transaction.go#L71](https://github.com/ethereum/go-ethereum/blob/01e5e9c2c3fa1cf7a9747148dca22d59ff9839b6/core/types/transaction.go#L71)

以上是Transaction部分的源码，有兴趣可以自己看。

---

*Originally published on [albertma](https://paragraph.com/@albertma-2/solidity)*
