Golang 類型斷言 vs 類型轉換

2021-01-20 吳親強的深夜食堂

這是一篇譯文,原文出處:https://www.sohamkamani.com/golang/type-assertions-vs-type-conversions/。


在Go中,類型斷言和類型轉換是一個令人困惑的事情,他們似乎都在做同樣的事情。

這篇文章,我們將看到類型斷言和類型轉換實際上是如何截然不同的,並深入了解在Go中使用它們會發生什麼。

首先,讓我們看看它們長什麼樣……

下面是一個類型斷言的例子:

var greeting interface{} = "hello world"greetingStr := greeting.(string)

接著看一個類型轉換的例子:

greeting := []byte("hello world")greetingStr := string(greeting)

最明顯的不同點是他們具有不同的語法(variable.(type) vs type(variable) )。接下來,我們進一步去研究。



類型斷言

顧名思義,類型斷言用於斷言變量是屬於某種類型。類型斷言只能發生在interface{}類型上。
上面類型斷言的例子,greeting是一個interface{}類型,我們為其分配了一個字符串。現在,我們可以認為greeting實際上是一個string,但是對外展示的是一個interface{}。
如果我們想獲取greeting的原始類型,那麼我們可以斷言它是個string,並且此斷言操作會返回其string類型。


這意味著在做類型斷言的時候,我們應該知道任何變量的基礎類型。但是情況並非總是這樣的,這就是為什麼類型斷言操作實際上還返回了第二個可選值的原因。

var greeting interface{} = "42"greetingStr, ok := greeting.(string)

第二個值是一個布爾值,如果斷言正確,返回 true ,否則返回 false。
另外,類型斷言是在程序運行時執行。


類型判斷

類型判斷是一個很實用的構造。當你不確定interface{}真正類型的時候,可以使用它。

var greeting interface{} = 42
switch g := greeting.(type) { case string: fmt.Println("g is a string with length", len(g)) case int: fmt.Println("g is an integer, whose value is", g) default: fmt.Println("I don't know what g is")}


為什麼需要斷言

在上面的例子中,我們似乎在將greeting從interface{}轉換成int類型或者string類型。但是greeting的類型是固定,並且和初始化期間聲明時的內容一樣。
當我們把greeting分配給interface{}類型的時候,請勿修改其原始類型。同樣,當我們斷言類型的時候,我們只是使用了原始類型功能,而不是使用interface公開的有限方法。


類型轉換

首先,我們花點時間了解一下什麼是 「類型」。在 Go 每種類型都定義了兩件事:

變量的存儲方式 (存儲結構)

你可以使用變量做什麼 (可以使用的方法和函數)

這裡介紹了基本類型,包括了string和int。以及一些複合類型,比如structmaparray和slice。

你可以從基本類型或通過創建複合類型來聲明一個新類型。

// `myInt` 是一個新類型,它的基類型是 `int`type myInt int
// AddOne 方法適用於 `myInt` 類型,不適用於 `int` 類型func (i myInt) AddOne() myInt { return i + 1}
func main() { var i myInt = 4 fmt.Println(i.AddOne())}

當我們聲明一個myInt類型,我們可以將變量數據基於基本的int類型,但是如果要進行變量修改,我們可以通過myInt類型變量進行操作 (通過在myInt上面聲明一個新方法)。

由於myInt 的類型基於int,意味著他們的底層基礎類型是一樣的。因此這些類型的變量可以相互轉換。

 var i myInt = 4originalInt := int(i)

上面i的類型是myInt,originalInt的類型是int。



什麼時候使用類型轉換?

只有當基礎數據結構類型相同,類型之間才可以相互轉換。來看一個使用struct例子。

type person struct {    name string    age int}
type child struct { name string age int}
type pet { name string}
func main() { bob := person{ name: "bob", age: 15, } babyBob := child(bob) // "babyBob := pet(bob)" 會導致編譯錯誤 fmt.Println(bob, babyBob)}

在這裡,person 和 child 擁有相同的數據結構,即:

struct {    name string    age int}

因此他們可以相互轉換。


type可用於聲明具有相同數據結構的多種類型。

這只是意味著child和person基於相同的數據結構 (類似於之前的int和myInt)。


類型為什麼稱為轉換

就像上面說的,雖然不同類型的基礎結構可能相同,但是他們可能也具有不同的限制和方法。當我們從一種類型轉換成另一種類型時,會改變對類型的處理方式,而不是像類型斷言那樣僅公開其基礎類型,這就是他們本質的差別。(ps:這句話是我自己加的)。
如果嘗試去轉換錯誤的類型,類型轉換會提示編譯錯誤,這和類型斷言所提供的運行時通過返回值判斷錯誤,完全相反。


類型結論

類型斷言和類型轉換有著比語法層面上更根本的區別。它還強調了在Go中接口類型 (interface) 和非接口類型之間的區別。

接口類型沒有任何數據結構,而是公開了已有的具體類型 (具有底層數據結構) 的一些方法。
類型斷言引出了接口的具體類型,而類型轉換改變了在具有相同數據結構的兩個具體類型之間使用變量的方式。

如果文章對你有所幫助,點讚、轉發留言都是一種支持!

相關焦點

  • matlab數據類型轉換實用案例
    之前群友在群裡發了一張有關數據類型轉換的圖片 相互之間轉換關係很複雜不容易記,每次使用的時候都要百度,為了方便大家記住數據類型轉換關係,轉換圖便應運而生,下圖就是過冷水給大家分享的轉換圖。
  • 深入揭秘Spring類型轉換-框架設計的基石
    正文Java是個多類型且強類型語言,類型轉換這個概念對它來說並不陌生。比如:自動類型轉換(隱式):小類型 -> 大類型。說明:類型轉換其實每個框架都會存在,其中Java領域以Spring的實現最為經典,學會後便可舉一反三Spring類型轉換Spring的類型轉換也並非一步到位。完全掌握Spring的類型轉換並非易事,需要有一定的脈絡按步驟進行。
  • 一文讀懂js中的隱式類型轉換
    前言今天來詳細了解一下javascript中的隱式類型轉換,通過在各種情況下發生的隱式類型的例子,來詳細的了解隱式類型轉換的過程。如何轉換-前置知識1.對象類型轉換當對象類型進行類型轉換時,會調用js內部一個方法toPrimitive, 此方法接收兩個參數,一個參數為需要轉換的對象,另一個方法接收一個期望類型,string或number。
  • V49.VBA數據類型轉換函數有哪些?
    一.VBA數據類型轉換函數有哪些?答:VBA數據類型轉換函數有:1、CBool(expression) 轉換為Boolean型2、CByte(expression) 轉換為Byte型3、CCur(expression) 轉換為Currency型
  • 如何用Bull轉換任意類型的Java Bean
    } }但是,我們可以將庫配置為為欄位類型分配默認值(如:0為int類型,null為String等等)ToBean toBean = new BeanUtils().getTransformer
  • C/C++編程筆記:C語言中的類型轉換,今天教你怎麼寫!
    所謂類型轉換基本上是從一種類型到另一種類型的轉換。類型轉換有兩種類型: 一、隱式類型轉換 通常在表達式中存在多個數據類型時發生。在這種情況下,將進行類型轉換(類型提升)以避免數據丟失。 變量的所有數據類型將升級為具有最大數據類型的變量的數據類型。
  • 夢幻西遊:玩轉武器類型轉換,知道這些買無級別能省好幾萬!
    今天這篇文章,叫獸就來為大家詳細講解武器轉換的規則。夢幻西遊中的武器轉換分為兩種:第一種是武器造型轉換,即90-140級的武器,通過寶象國的武器大師,花費2000仙玉即可轉換成另外兩種同類型的武器。第二種方式則是武器類型轉換,而武器類型是通過轉角色/轉門派來實現的。
  • Meta分析的類型簡介
    ,因此其類型可根據原始研究的設計分為不同的類型。不同類型的系統評價與Meta分析的製作步驟相似,不同的地方在於因原始研究特點及研究目的帶來的資料提取、方法學質量評價工具、報告內容、結果解讀上的不同。本文在上期在介紹系統評價與Meta分析的內涵及價值的基礎上,介紹系統評價與Meta分析的類型及製作步驟。
  • CASE……WHEN和cast類型轉換(Hive日誌案例分析應用)
    先補充兩個知識點:CASE … WHEN和CAST類型轉換CASE … WHEN…的用法創建資料庫創建員工表create table emp(empno int comment '員工編號',ename string comment '員工姓名',job string comment
  • 《鬼滅之刃》手遊是什麼類型遊戲 遊戲類型玩法...
    玩家將於再現原作世界觀的地圖上,運用角色持有的技能、招式、武器,展開「獵鬼人 vs 食人鬼」的死鬥。 鬼滅之刃 類型:休閒 平臺:安卓 狀態:運營 安卓版暫無下載   蘋果版暫無下載
  • 大數據開發基礎:Java基礎數據類型
    在Java基礎入門學習階段,Java基礎數據類型無疑是基礎當中的重點,掌握基礎數據類型,對於後續去理解和掌握更深入的理論,是有緊密的關聯性的。今天的大數據開發基礎學習,我們就來講講,Java八種基礎數據類型。
  • 詳解C語言數據類型:float與double
    當較小尺寸的參數(特別是char,short和float)傳遞給可變參數函數(如printf之類的函數,其參數數量不固定)時,它們將轉換為較大尺寸。Char和short轉換為int,float轉換為double。為什麼這樣 據我所知,純粹出於歷史原因。
  • 馮提莫進入B站一年,轉換類型路人緣變好,綜藝晚會不停歇!
    許多主播都在嘗試著轉型,例如當年大司馬就轉換了自己的直播風格,從而靠著詼諧的直播風格爆紅。許多主播不是調整自己直播方向,就是更換自己的直播類型,例如爐石傳說王師傅之前是教C語言,後來轉型爐石主播。
  • 跟我學java編程—Java布爾類型
    這裡面有個字符判斷的過程,判斷的結果影響後面程序的執行,因此程序需要把判斷結果存儲到一個變量中,用於控制程序執行不同的分支語句,這個變量的類型就是布爾類型。布爾類型是表示邏輯狀態的類型。java語言通過關鍵字boolean來定義布爾類型變量,只有true和false兩個值,分別代表布爾邏輯中的「真」和「假」。
  • 教師招聘考試:氣質類型
    氣質的高級神經活動類型學說是俄國的生理學家巴甫洛夫提出來的,巴甫洛夫認為氣質與高級神經活動的類型有關。他認為,高級神經活動的基本過程有三種特性即高級神經過程的強度、均衡性和靈活性。因此,巴甫洛夫把高級神經活動類型劃分為以下四種:興奮型、活潑型、安靜型、抑鬱型。
  • 不同類型舉牌照在線製作軟體
    不同類型舉牌照在線製作軟體 圖像轉換 大小: 751KB
  • 初中英語同義句轉換的九種類型
    1運用同義詞(組)進行轉換   用同義詞或同義詞組對原句中的某些詞或詞組進行替換,注意轉換後的詞或詞組的詞形變化要與句子其他成分相適應。如:   1. That day we could see flowers here and there.
  • NET開發-詳解SQL Server資料庫數據類型,對應C#的那些數據類型?
    1.概述在 SQL Server 中,每個列、局部變量、表達式和參數都具有一個相關的數據類型。 數據類型是一種屬性,用於指定對象可保存的數據的類型:整數數據、字符數據、貨幣數據、日期和時間數據、二進位字符串等。
  • 傷害類型轉化的幾個原則!
    首先,這裡所說的傷害類型的轉化,指的是原傷害類型部分或者全部轉化為新的傷害類型,如「50%物理傷害轉化為火焰傷害」。不是指附加其他類型的傷害,如「附加30%物理傷害的火焰傷害」。轉化是原傷害被轉化或者部分轉化;附加是原傷害不變,以其為基數新增其他類型傷害(在不考慮各類加成的情況下,這本身相當於more傷害提升)。