Go語言 一些簡單的總結(jié)

2023-02-16 17:40 更新

哪些種類型的值可以有間接底層部分?

在Go中,下列種類的類型的值可以有間接底層部分:

  • 字符串類型
  • 函數(shù)類型
  • 切片類型
  • 映射類型
  • 通道類型
  • 接口類型

注意:此答案基于標準編譯器的實現(xiàn)。事實上,函數(shù)類型的值是否有間接底層部分是難以證明的。 另外,字符串和接口類型的值在邏輯上應(yīng)該被認為是不含間接底層部分。 請閱讀值部一文獲取更多信息。

哪些種類型的值可以用做內(nèi)置len(以及cap、close、delete和make)函數(shù)調(diào)用的實參?

len cap close delete make
字符串值 可以
數(shù)組或者數(shù)組指針值 可以 可以
切片值 可以 可以 可以
映射值 可以 可以 可以
通道值 可以 可以 可以 可以

可以被用做內(nèi)置函數(shù)len調(diào)用的參數(shù)的值的類型都可以被稱為(廣義上的)容器類型。 這些容器類型的值都可以跟在for-range循環(huán)的range關(guān)鍵字后。

各種容器類型比較

類型 容器值是否支持添加新的元素? 容器值中的元素是否可以被替換? 容器值中的元素是否可尋址? 訪問容器值元素是否會更改容器長度? 容器值是否可以有間接底層部分?
字符串 (1)
數(shù)組 (2) (2)
切片 (3)
映射
通道 (4)

(1) 對于標準編譯器和運行時來說。
(2) 對于可尋址的數(shù)組值來說。
(3) 一般說來,一個切片的長度只能通過將另外一個切片賦值給它來被整體替換修改,這里我們不視這種情況為“添加新的元素”。 其實,切片的長度也可以通過調(diào)用reflect.SetLen來單獨修改。增加切片的長度可以看作是一種變相的向切片添加元素。 但reflect.SetLen函數(shù)的效率很低,因此很少使用。
(4) 對于帶緩沖并且緩沖未滿的通道來說。

哪些種類型的值可以用組合字面量(T{...})表示?

下面在四種類型的值(除了切片和映射類型的零值)可以用組合字面量表示。

類型(T T{}是類型T的零值?
結(jié)構(gòu)體類型
數(shù)組類型
切片類型
(零值用nil表示)
映射類型
(零值用nil表示)

各種類型的尺寸

詳見值復(fù)制成本一文。

哪些種類型的零值使用預(yù)聲明的nil標識符表示?

下面這些類型的零值可以用預(yù)聲明的nil標識符表示。

類型(T T(nil)的尺寸
指針 1 word
切片 3 words
映射 1 word
通道 1 word
函數(shù) 1 word
接口 2 words

上表列出的尺寸為標準編譯器的結(jié)果。 一個word(原生字)在32位的架構(gòu)中為4個字節(jié),在64位的架構(gòu)中為8個字節(jié)。 一個Go值的間接底層部分未統(tǒng)計在尺寸中。

一個類型的零值的尺寸和其它非零值的尺寸是一致的。

我們可以為什么樣的類型聲明方法?

詳見方法一文。

什么樣的類型可以被內(nèi)嵌在結(jié)構(gòu)體類型中?

詳見類型內(nèi)嵌一文。

哪些函數(shù)調(diào)用將在編譯時刻被估值?

如果一個函數(shù)調(diào)用在編譯時刻被估值,則估值結(jié)果為一個常量。

函數(shù) 返回類型 其調(diào)用是否總是在編譯時刻估值?
unsafe.Sizeof uintptr
unsafe.Alignof
unsafe.Offsetof


len


int

Go語言白皮書中提到:
  • 如果表達式s表示一個字符串常量,則表達式len(s)將在編譯時刻估值;
  • 如果表達式s表示一個數(shù)組或者數(shù)組的指針,并且s中不含有數(shù)據(jù)接收操作和估值結(jié)果為非常量的函數(shù)調(diào)用,則表達式len(s)cap(s)將在編譯時刻估值。


cap



real

默認類型為
float64
(結(jié)果為類型不確定值)


Go語言白皮書提到: 表達式real(s)imag(s)s為一個復(fù)數(shù)常量表達式時才在編譯時刻估值。

imag

complex 默認類型為
complex128
(結(jié)果為類型不確定值)


Go語言白皮書提到: 表達式complex(sr, si)只有在srsi都為常量表達式的時候才在編譯時刻估值。

哪些值是可尋址的?

請閱讀此條問答獲取詳情。

哪些類型不支持比較?

請閱讀此條問答獲取詳情。

哪些代碼元素允許被聲明卻不使用?

允許被聲明卻不使用?
包引入 不允許
類型 允許
變量 包級全局變量允許,但局部變量不允許(對于官方標準編譯器)。
常量 允許
函數(shù) 允許
跳轉(zhuǎn)標簽 不允許

哪些具名代碼元素可多個被一起聲明在一對小括號()中?

下面這些同種類的代碼元素可多個被一起聲明在一對小括號()中:

  • 包引入
  • 類型
  • 變量
  • 常量

函數(shù)是不能多個被一起聲明在一對小括號()中的。跳轉(zhuǎn)標簽也不能。

哪些具名代碼元素的聲明可以被聲明在函數(shù)內(nèi)也可以被聲明在函數(shù)外?

下面這些代碼元素的聲明既可以被聲明在函數(shù)內(nèi)也可以被聲明在函數(shù)外:

  • 類型
  • 變量
  • 常量

包引入必須被聲明在其它種類的代碼元素的聲明之前。

函數(shù)必須聲明在任何函數(shù)體之外。匿名函數(shù)可以定義在函數(shù)體內(nèi),但那不屬于聲明。

跳轉(zhuǎn)標簽必須聲明在函數(shù)體內(nèi)。

哪些表達式的估值結(jié)果可以包含一個額外的可選的值?

下列表達式的估值結(jié)果可以包含一個額外的可選的值:

語法 額外的可選的值(語法示例中的ok)的含義 舍棄額外的可選的值會對估值行為發(fā)生影響嗎?
映射元素訪問 e, ok = aMap[key] 鍵值key對應(yīng)的條目是否存儲在映射值中
數(shù)據(jù)接收 e, ok = <- aChannel 被接收到的值e是否是在通道關(guān)閉之前發(fā)送的
類型斷言 v, ok = anInterface.(T) 接口值的動態(tài)類型是否為類型T
(當可選的值被舍棄并且斷言失敗的時候,將產(chǎn)生一個恐慌。)

幾種導致當前協(xié)程永久阻塞的方法

無需引入任何包,我們可以使用下面幾種方法使當前協(xié)程永久阻塞:

  1. 向一個永不會被接收數(shù)據(jù)的通道發(fā)送數(shù)據(jù)。
    make(chan struct{}) <- struct{}{}
    // 或者
    make(chan<- struct{}) <- struct{}{}
    
  2. 從一個未被并且將來也不會被發(fā)送數(shù)據(jù)的(并且保證永不會被關(guān)閉的)通道讀取數(shù)據(jù)。
    <-make(chan struct{})
    // 或者
    <-make(<-chan struct{})
    // 或者
    for range make(<-chan struct{}) {}
    
  3. 從一個nil通道讀取或者發(fā)送數(shù)據(jù)。
    chan struct{}(nil) <- struct{}{}
    // 或者
    <-chan struct{}(nil)
    // 或者
    for range chan struct{}(nil) {}
    
  4. 使用一個不含任何分支的select流程控制代碼塊。
    select{}
    

幾種銜接字符串的方法

詳見字符串一文。

官方標準編譯器中實現(xiàn)的一些優(yōu)化

詳見Go語言101維基中的一文

在Go程序運行中將會產(chǎn)生恐慌或者崩潰的情形

詳見Go語言101維基中的一文。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號