網站首頁 編程語言 正文
在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
。以及一些復合類型,比如struct``map``array
和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 = 4 originalInt := 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
)。
類型為什么稱為轉換
就像上面說的,雖然不同類型的基礎結構可能相同,但是他們可能也具有不同的限制和方法。當我們從一種類型轉換成另一種類型時,會改變對類型的處理方式,而不是像類型斷言那樣僅公開其基礎類型,這就是他們本質的差別。
如果嘗試去轉換錯誤的類型,類型轉換會提示編譯錯誤,這和類型斷言所提供的運行時通過返回值判斷錯誤,完全相反。
類型結論
類型斷言和類型轉換有著比語法層面上更根本的區別。它還強調了在Go
中接口類型 (interface
) 和非接口類型之間的區別。 接口類型沒有任何數據結構,而是公開了已有的具體類型 (具有底層數據結構) 的一些方法。
類型斷言引出了接口的具體類型,而類型轉換改變了在具有相同數據結構的兩個具體類型之間使用變量的方式。
原文鏈接:https://juejin.cn/post/7144273445595906056
相關推薦
- 2022-05-05 Android開發使用WebView打造web?app示例代碼_Android
- 2022-11-06 React?Hooks--useEffect代替常用生命周期函數方式_React
- 2023-01-01 c語言實現計算圓周率的近似值_C 語言
- 2022-01-06 npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to
- 2022-04-12 【scp】Windows 下scp報錯 bad permissions
- 2023-10-15 動態演示操作系統進程調度算法,FCFS, RR, SPN, SRT, HRRN
- 2022-01-19 C++ 獲取當前時間毫秒數
- 2022-08-18 Python壓縮包處理模塊zipfile和py7zr操作代碼_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支