Go語言的類型轉換和類型斷言

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

類型轉換和類型斷言是Go語言中比較繞的地方.

Go語言要求所有統一運算式的不同的類型之間必須做顯示的類型轉換.
而作為Go語言鼻祖的C語言是可以直接做隱式的類型轉換的.
當然作為const類的字面值常量是要靈活很多的.

不過Go語言必須做顯示的類型轉換的要求也有例外的情況:

  • 當普通T類型變數向I介面類型轉換時是隱式的!
  • IX介面變數向I介面類型轉換可以在編譯期完成時是隱式的!

類型之間轉換的例子

下面是Go語言規範給出的部分例子:

*Point(p)        // same as *(Point(p))(*Point)(p)      // p is converted to *Point<-chan int(c)    // same as <-(chan int(c))(<-chan int)(c)  // c is converted to <-chan intfunc()(x)        // function signature func() x(func())(x)      // x is converted to func()(func() int)(x)  // x is converted to func() intfunc() int(x)    // x is converted to func() int (unambiguous)

簡單的說, x需要轉換為T類型的文法是T(x).
如果對於某些地方的優先順序拿不準可以自己加()約束.

最後一個轉換就是一個容易混淆的語句, 因此需要用括弧(func() int)(x)提高優先順序.

還有一個容易混淆的地方是 唯讀和唯寫的通道類型 <-chan int/chan<- int .

介面之間轉換的例子

Go語言中介面的類型轉換有很多奇怪的特性: 有時候是隱式轉換, 有時候需要類型斷言.

Go語言的介面之間雖然也有強制轉換的文法, 但是因為介面間支援隱式轉換, 因此介面之間
的強制轉換文法只是一個擺設.

比如有以下2個介面類型:

type IA interface {}type IB interface {Foo()}

IA要向IB轉換如何操作呢? 這個操作無法在編譯期確定, 因此必然不是類型轉換.
由於2者都是介面類型, 因此肯定是類型斷言:

var a Avar b = a.(B)

當然因為上面的代碼中的anil, 會導致a.(B)錯誤.
但是請注意: 這隻是運行錯誤, 並不是編譯錯誤!

IB要向IA轉換如何操作呢? 這個操作可以在編譯期確定, 因此必然是類型轉換.

var b Bvar a = A(b)

前面我們說過, Go語言的介面是隱式轉換的, 因此還可以省略強制轉換的語句:

var b Bvar a = b

介面和類型之間的轉換例子

雖然前面看到介面之間偶爾也會有類似普通類型之間的強制強制轉換文法,
但從本意上來說介面是一個特殊的類型(和普通的類型區別).

我們先定義2個和前面的IA/IB匹配的普通類型(底層類型一樣):

type TA inttype TB intfunc (TB) Foo() {}

如果是TATB之間的轉換, 可以參考前面的類型之間轉換的例子.
我們這裡重點關注 TA/TBIA/IB 之間的轉換.

普通類型向介面類型轉換是隱式的(可以編譯期確定, 介面的隱式轉換特權):

var ta TAvar ia = tavar tb TBvar ib = tb

介面類型向普通類型是類型斷言(運行期確定):

var ia IAvar ta = ia.(TA)var ib IBvar tb = ib.(TB)

類型斷言在編譯期是沒有任何保障的, 錯誤的代碼也可以編譯通過:

var ta = ib.(TA)var tb = ia.(TB)

總結

因為Go語言的類型轉換和類型斷言設計的不夠完美, 因此很難簡單歸納.

下面是我整理的判斷是類型轉換還是類型斷言的虛擬碼:

func x 轉換為 y    if x 是介面嗎 ? {        if 可以編譯期轉換嗎 ? {            這是類型轉換 (介面之間可以隱式轉換)            // 這裡也可以用類型斷言, 如果編譯期不最佳化的效率可能低一些        } else {            這是類型斷言 (運行時也可能會失敗)        }    } else {        if 可以編譯期轉換 ? {            這是類型轉換 (顯示轉換, 必須成功, 但可能會遺失資料)        } else {            禁止!        }    }}

我們可以看到, 當介面之間可以用類型轉換的時候, 其實也是可以用類型斷言的.

Go語言介面之間的轉換是最混亂的特徵之一. 期望Go2.0能夠有所改善.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.