說明一下Golang 中 make 和 new 的區別?
好的,關於 make
和 new
在 Go 語言中的區別,我來解釋一下。
-
new
函數的作用:new(T)
函數會爲 T 類型的新項分配零值內存,並返回其地址,即一個*T
類型的值(指針)。這種方法適用於各種類型,包括基本類型如int
、float
、bool
等,以及數組、結構體等。- 使用
new
分配的內存被初始化爲類型的零值,例如new(int)
返回的指針指向的值會被初始化爲 0。
-
make
函數的作用:make
函數僅用於切片(slice)、映射(map)和通道(channel)的內存分配,並返回一個有初始值(非零值)的 T 類型,而不是*T
。- 對於切片,
make
會分配內存並初始化切片的內部結構,如長度和容量等。 - 對於映射,
make
會初始化映射的結構。 - 對於通道,
make
會配置通道的緩衝大小。
-
應用場景與例子:
- 使用
new
:- 當你需要一個指向某基本類型零值的指針時,比如在需要在函數間共享或者更改數據時。
- 例子:
num := new(int)
創建了一個指向整數的指針,其值初始化爲 0。
- 使用
make
:- 創建切片、映射或通道時,並且需要它們立即可用,例如要在切片中存儲數據,或者在映射中設置鍵值對。
- 例子:
s := make([]int, 10)
創建了一個長度和容量都是 10 的整數切片。
- 使用
總結:new
和 make
都是用於分配內存,但 new
返回的是指針,且適用於所有類型,而 make
只用於切片、映射和通道,並返回一個初始化的(非零值的)類型實例。
說明一下 Golang 數組和切片的區別?
Golang 中數組和切片是兩種不同的數據類型,它們有以下幾個主要區別:
-
長度固定性:
- 數組:數組的長度是固定的,定義時必須指定長度,並且一旦定義,其長度不能更改。
- 切片:切片是動態的,長度可以改變。切片實際上是對數組的抽象。
-
聲明方式:
- 數組:聲明時需要指定長度,例如
var a [5]int
定義了一個包含 5 個整數的數組。 - 切片:在聲明切片時,不需要指定長度,例如
var s []int
是一個切片,初始時爲空。
- 數組:聲明時需要指定長度,例如
-
內部結構:
- 數組:數組直接存儲值,數組的大小和元素類型一起定義了數組的類型。
- 切片:切片包含三個元素:一個指向底層數組的指針,切片的長度,以及切片的容量。因此,切片比數組更加靈活。
-
傳遞方式:
- 數組:在函數調用時,數組是通過值傳遞的,這意味着傳遞的是整個數組的副本。
- 切片:切片是通過引用傳遞的,所以函數內部對切片的修改會影響到原切片。
-
使用場景:
- 數組:當你需要固定長度的序列時使用數組。例如,你知道你只需要存儲 12 個月的名稱,可以使用數組。
- 切片:更加常用,特別是當你需要一個可伸縮的列表時。例如,你在處理一個用戶列表,這個列表可能會根據用戶註冊的增減而變化。
-
性能考慮:
- 數組:由於大小固定,內存分配在棧上,因此訪問速度快。
- 切片:更加靈活,但需要小心處理容量和長度的變化,可能會涉及到內存重新分配。
總結:數組是靜態的、固定長度的序列,而切片是動態的、可以伸縮的序列。切片在 Go 中更加常用,提供了更高的靈活性和便利性。
使用for range 的時候,它的地址會發生變化嗎?
在 Go 語言中,for range
循環的行爲取決於你正在遍歷的數據類型。對於數組或切片,for range
會提供每個元素的副本,而不是直接引用原始元素。因此,如果你嘗試獲取這些元素的地址,你會發現地址在每次迭代中都會改變,因爲你實際上獲取的是副本的地址。
這點可以通過以下的例子來說明:
nums := []int{10, 20, 30}
for i, v := range nums {
fmt.Printf("Index: %d, Value: %d, Address: %p\n", i, v, &v)
}
在上述代碼中,v
是數組元素的副本,而不是直接引用。因此,&v
在每次迭代中都會產生不同的地址,這些地址指向的是副本的位置,而不是原始數據的位置。
但是,如果你直接操作原始數組(或切片)的元素,例如:
nums := []int{10, 20, 30}
for i := range nums {
fmt.Printf("Index: %d, Value: %d, Address: %p\n", i, nums[i], &nums[i])
}
在這個例子中,&nums[i]
將在每次迭代中提供原始元素的地址,這些地址在每次迭代中都是不變的,因爲它們直接引用了原始數據。
總結:在 for range
循環中,如果嘗試獲取每次迭代中提供的元素的地址,這些地址會在每次迭代中改變,因爲這些元素是原始數據的副本。如果你需要操作原始數據的地址,你應該直接引用原始數據。
go defer,多個 defer 的順序,defer 在什麼時機會修改返回值?
defer
關鍵字在Go語言中用於確保函數調用在程序執行完畢後,無論函數是否出現錯誤,都能正確地被執行。當有多個defer
語句在同一函數中,他們會以LIFO(後進先出)的順序執行。這就意味着在同一個函數內,最後聲明的defer
語句會被最先執行。
關於修改返回值,defer
語句在函數返回之後執行,但是它可以訪問並修改返回值。這是因爲返回值在函數結束時會被當作defer
語句的參數。這意味着如果你在defer
函數中修改了返回值,那麼實際的返回值會被改變。
以下是一個簡單的例子來解釋這個概念:
package main
import "fmt"
func main() {
fmt.Println(deferTest())
}
func deferTest() (result int) {
defer func() {
result++
}()
return 0
}
在這個例子中,deferTest
函數的返回值在沒有defer
語句的情況下應該是0
。但是,因爲我們在defer
語句中將result
增加了1
,所以最終返回的值實際上是1
。當我們運行main
函數,輸出結果就是1
,而不是0
。
簡要說明一下Golang 單引號,雙引號,反引號的區別?
在 Go 語言中,單引號 ('
), 雙引號 ("
), 和反引號 (```) 都被用於表示字符串,但是它們的用途和行爲有所不同:
-
單引號 (' ') :用於表示單個字符(rune)。它包含的字符必須是 Unicode 編碼的字符,例如
'a'
、'中'
或者 Unicode 編碼'u4E2D'
。不能用於表示字符串。例如:
var char rune = 'a' ```
-
雙引號 (" ") :用於表示字符串。字符串是 UTF-8 字符的序列。字符串內的特殊字符可以通過反斜槓 (
\
) 進行轉義。例如:
var str string = "Hello, World!\n" ```
-
反引號 (` `) :也用於表示字符串,但是反引號表示的字符串會保留原始內容,包括換行和其他特殊字符,不支持任何轉義序列。
例如:
var str string = `Hello, World!` ```
在這個例子中,反引號字符串會保留原始的換行符。
總結:單引號用於表示字符,雙引號和反引號用於表示字符串,但雙引號支持轉義序列,而反引號保留字符串的原始格式。
Go的函數與方法及方法接受者區別?
在Go語言中,函數和方法都是用來封裝代碼的,但它們在使用方式上有一些不同。
函數是具有一組輸入參數和返回值的獨立實體,它不依賴於任何類型。例如:
func Add(a int, b int) int {
return a + b
}
在這個例子中,Add
是一個函數,它接受兩個整數作爲輸入,然後返回兩個整數的和。
而方法是依賴於特定類型的函數,這個特定類型被稱爲方法的接收者。例如:
type MyInt int
func (m MyInt) Add(otherInt int) int {
return int(m) + otherInt
}
在這個例子中,Add
是一個方法,它的接收者是MyInt
類型。這意味着我們可以在任何MyInt
類型的實例上調用Add
方法。
方法接收者可以是任何類型的值或者指針,不過不能是一個接口類型或者一個指針類型。接收者的類型在方法名前,以(接收者) 方法名
的形式出現。
方法接收者有兩種類型:值接收者和指針接收者。值接收者方法在調用時,接收者的值會被複制,而指針接收者在調用方法時,會使用接收者的實際地址,所以可以修改接收者的值。
type MyInt int
func (m MyInt) valueReceiver() { // 值接收者
m = 5
}
func (m *MyInt) pointerReceiver() { // 指針接收者
*m = 5
}
func main() {
var num MyInt = 2
num.valueReceiver()
fmt.Println(num) // 輸出 2
num.pointerReceiver()
fmt.Println(num) // 輸出 5
}
在這個例子中,你會看到valueReceiver
方法沒有改變num
的值,而pointerReceiver
方法改變了num
的值。
能詳細介紹一下Golang中的defer底層數據結構和特性嗎?
在 Go 語言中,defer
關鍵字用於推遲一個函數或方法的執行,直到包含該 defer
語句的函數執行完成。這個被延遲的函數被稱爲 "deferred function"。
defer
的主要特性包括:
-
後進先出(LIFO):當在一個函數中存在多個
defer
語句時,它們將會以後進先出的順序執行。也就是說,最後一個defer
語句最先被執行,第一個defer
語句最後被執行。 -
參數在 defer 語句中立即求值:在
defer
語句中,函數的參數會立即被計算並保存,而函數本身的執行會被延遲。 -
延遲函數的執行時機:
defer
的函數會在包含defer
語句的函數返回之前執行,無論這個函數是通過 return 正常結束,還是由於 panic 導致的異常結束。
關於 defer
的底層實現,Go 運行時使用了一個叫做 "deferred function stack" 的結構來管理 defer
調用。這是一個後進先出(LIFO)的棧結構,每當遇到 defer
調用,運行時就會將其添加到當前 goroutine 的 defer 棧中。每個棧幀包含了被推遲函數的指針以及其參數,這些參數在 defer
語句被執行時就已經被求值。
當包含 defer
語句的函數即將返回時,運行時會從 defer 棧中彈出一個棧幀,並執行其中的函數。如果有多個 defer
語句,那麼就會按照後進先出的順序依次執行。
總之,defer
提供了一種強大的機制,可以用來處理資源的清理工作,如關閉文件句柄、解鎖互斥鎖等,無論函數由於何種原因結束,都能保證資源的正確清理。
能否介紹一下Golang中的slice底層數據結構和特性?
Go語言中的切片(slice)是一種動態數組,它的底層數據結構包括三個關鍵的屬性:指針、長度和容量。
- 指針(Pointer):指向數組的第一個元素。
- 長度(Length):當前切片的長度,即包含的元素數量。
- 容量(Capacity):從切片的開始位置到底層數組的結尾位置的元素數量。
Go語言的切片是引用類型,它們不存儲任何數據,只描述底層數組的一段。更改切片的元素會修改其底層數組中的對應元素。
切片的長度和容量可以通過內置的 len()
和 cap()
函數獲取。您可以通過 append()
函數向切片添加元素。如果添加的元素數量超過切片的容量,append()
會創建一個新的底層數組,並將原始數據複製到新數組中,然後返回新的切片。
這是一個簡單的例子:
package main
import "fmt"
func main() {
// 創建一個切片
s := []int{1, 2, 3}
fmt.Println(len(s), cap(s)) // 輸出:3 3
// 添加一個元素
s = append(s, 4)
fmt.Println(len(s), cap(s)) // 輸出:4 6
}
在這個例子中,我們首先創建了一個包含三個元素的切片。然後,我們向切片添加了一個元素,因爲切片的容量不足以容納新的元素,所以 append()
創建了一個新的底層數組,並將原始切片的數據複製到新數組中,然後返回了新的切片。新切片的容量是原始切片的容量的兩倍。
在Golang中,如何高效地拼接字符串?
在Go語言中,最高效的方式拼接字符串是使用strings.Builder
或bytes.Buffer
。這兩者都能夠避免在拼接過程中多次創建和複製字符串,因此它們比普通的+
或+=
運算符更加高效。
以下是一個使用strings.Builder
的例子:
package main
import (
"strings"
"fmt"
)
func main() {
var builder strings.Builder
for i := 0; i < 10; i++ {
builder.WriteString("Go ")
}
result := builder.String() // Get the concatenated string
fmt.Println(result)
}
在這個例子中,我們創建了一個strings.Builder
對象,並使用WriteString
方法向其寫入字符串。最後,我們調用String
方法獲取最終拼接的字符串。
同樣,我們可以使用bytes.Buffer
達到類似的效果:
package main
import (
"bytes"
"fmt"
)
func main() {
var buffer bytes.Buffer
for i := 0; i < 10; i++ {
buffer.WriteString("Go ")
}
result := buffer.String() // Get the concatenated string
fmt.Println(result)
}
這兩種方式都可以有效地拼接字符串,而不會像+
或+=
那樣造成大量的內存分配和複製。在處理大量字符串拼接時,這可以帶來顯著的性能提升。
Golang中2 個 interface 可以比較嗎?
在 Go 語言中,兩個接口類型的變量可以比較,但有一些規則和限制:
-
nil 接口比較:兩個 nil 接口值是相等的。
-
非 nil 接口比較:如果兩個接口值的動態類型相同,並且動態值也相等,那麼這兩個接口值就被認爲是相等的。
-
限制:如果接口的動態值是不可比較的類型(如切片),那麼在嘗試比較接口值時將會導致運行時錯誤。
下面是一些示例:
type Data struct {
num int
}
var i, j interface{}
fmt.Println(i == j) // 輸出:true
i = 10
j = 10
fmt.Println(i == j) // 輸出:true
i = Data{num: 10}
j = Data{num: 10}
fmt.Println(i == j) // 輸出:true
i = []int{1, 2, 3}
j = []int{1, 2, 3}
fmt.Println(i == j) // 運行時錯誤:slices can only be compared to nil
總的來說,可以比較兩個接口值,但你需要確保接口的動態值是可比較的類型,否則會導致運行時錯誤。
Golang中init() 函數是什麼時候執行的?
在 Go 語言中,init()
函數是一種特殊的函數,它在每個包完成初始化後自動執行。這意味着,你不能在代碼中顯式地調用 init()
函數,它由 Go 運行時系統自動調用。初始化順序爲:
-
如果一個包被導入多次,
init()
函數只會被執行一次。 -
包的初始化順序爲:首先初始化包級別(Package Level)的變量,然後是
init()
函數。如果一個包導入了其他包,會先初始化被導入的包。 -
即使一個包被多個其他包導入,它的
init()
函數也只會被執行一次。 -
在同一個包內,多個
init()
函數的執行順序爲它們在 Go 語言中,init()
函數是一種特殊的函數,它在每個包完成初始化後自動執行。這意味着,你不能在代碼中顯式地調用init()
函數,它由 Go 運行時系統自動調用。初始化順序爲: -
如果一個包被導入多次,
init()
函數只會被執行一次。 -
包的初始化順序爲:首先初始化包級別(Package Level)的變量,然後是
init()
函數。如果一個包導入了其他包,會先初始化被導入的包。 -
即使一個包被多個其他包導入,它的
init()
函數也只會被執行一次。 -
在同一個包內,多個
init()
函數的執行順序爲它們在代碼中的出現順序。
這是一個簡單的例子:
package main
import "fmt"
var foo = initFoo()
func initFoo() int {
fmt.Println("Initializing variable...")
return 42
}
func init() {
fmt.Println("Executing init function...")
}
func main() {
fmt.Println("Executing main function...")
fmt.Println("Foo:", foo)
}
在這個例子中,程序的輸出會是:
Initializing variable...
Executing init function...
Executing main function...
Foo: 42
這顯示了 Go 語言初始化的順序:首先初始化包級別的變量(在這裏是 foo
),然後執行 init()
函數,最後是 main()
函數。
Golang中如何比較兩個 map 是否相等?
Go語言的標準庫中沒有直接提供比較兩個map
是否相等的函數,所以我們需要自己編寫函數來實現這個功能。在比較兩個map
是否相等時,我們需要檢查兩個map
的長度是否相等,然後檢查每個鍵在兩個map
中都存在,並且對應的值也相等。
下面是一個簡單的函數,用於比較兩個map[string]int
是否相等:
package main
import "fmt"
func mapsEqual(a, b map[string]int) bool {
if len(a) != len(b) {
return false
}
for k, v := range a {
if vb, ok := b[k]; !ok || vb != v {
return false
}
}
return true
}
func main() {
map1 := map[string]int{"one": 1, "two": 2}
map2 := map[string]int{"one": 1, "two": 2}
fmt.Println(mapsEqual(map1, map2)) // 輸出 true
}
在這個例子中,mapsEqual
函數首先檢查兩個map
的長度是否相等。然後,它遍歷map a
的每個鍵值對,檢查該鍵在map b
中是否存在,以及map b
中的值是否與map a
中的值相等。如果所有鍵值對都匹配,那麼函數就返回true
,表示兩個map
相等。否則,返回false
。
是否可以對Golang中的map元素取地址?
在Go語言中,map
的元素並不是變量,因此你不能直接獲取map
元素的地址。嘗試這樣做會導致編譯錯誤。例如,以下代碼將無法編譯:
package main
import "fmt"
func main() {
myMap := map[string]int{
"foo": 42,
}
addr := &myMap["foo"] // 編譯錯誤:cannot take the address of myMap["foo"]
fmt.Println(addr)
}
這是因爲map
的元素可能會因爲新元素的添加或者map
的擴容而被移動,所以直接獲取map
元素的地址可能會引用到錯誤的元素。
如果你需要修改map
中的元素,你可以使用替換的方式:
package main
import "fmt"
func main() {
myMap := map[string]int{
"foo": 42,
}
myMap["foo"] = 43
fmt.Println(myMap) // 輸出:map[foo:43]
}
如果你需要一個可以取地址的map
元素,你可以將map
的值設置爲一個包含所需元素的結構體或者指向該元素的指針:
package main
import "fmt"
func main() {
myMap := map[string]*int{}
val := 42
myMap["foo"] = &val
addr := myMap["foo"]
fmt.Println(*addr) // 輸出:42
}
在這個例子中,我們創建了一個map
,它的值是整數指針。然後,我們可以獲取和修改這些值的地址。
在Golang中,Map可以邊遍歷邊刪除元素嗎?
在 Go 語言中,可以在遍歷 map 的過程中刪除元素。Go 的官方文檔明確指出:“在迭代過程中,刪除迭代器返回的映射項是安全的。”這是因爲,刪除操作不會影響迭代器的狀態。
以下是一個例子:
m := map[int]string{
1: "a",
2: "b",
3: "c",
4: "d",
}
for k := range m {
if k == 1 {
delete(m, k)
}
}
在這個例子中,我們在遍歷過程中刪除了鍵爲 1 的元素,這是完全安全的。
然而,需要注意的是,map 的遍歷順序在 Go 中是不確定的。所以,你不能預測或依賴於遍歷的順序,除非你使用某種方式對鍵進行排序。
Golang中的float類型可以作爲Map的key嗎?
在 Go 語言中,浮點類型(float32
和 float64
)可以作爲 map 的鍵(key),但這並不是一個好的實踐。原因在於浮點數的精度問題和比較的複雜性。
浮點數的比較可能會引入微小的誤差,這可能導致意料之外的結果。即使兩個浮點數看起來相等,但由於精度問題,它們可能在內存中的表示是不同的。這就意味着,即使你使用看似相同的鍵來訪問 map,你可能得到不同的結果。
這是一個例子:
package main
import "fmt"
func main() {
m := make(map[float64]string)
m[0.1+0.2] = "value1"
m[0.3] = "value2"
fmt.Println(m[0.1+0.2]) // 輸出:"value1"
fmt.Println(m[0.3]) // 輸出:"value2"
}
儘管 0.1+0.2
和 0.3
在數學上是相等的,但在浮點數的世界中,由於精度問題,它們可能不相等。所以,儘管它們看起來應該映射到同一個值,但在這個例子中,它們映射到了兩個不同的值。
因此,通常建議使用更穩定、更可預測的數據類型(例如整型或字符串)作爲 map 的鍵。
請問Golang中的map的key爲什麼是無序的?
Go 語言中的 map 數據結構是基於哈希表實現的。哈希表是一種數據結構,它通過使用哈希函數將鍵(key)映射到存儲位置。這種映射過程使得查找元素的速度非常快,幾乎與 map 的大小無關。
然而,這種映射過程並不保證元素的順序。當你向 map 添加新元素時,如果發生哈希衝突(即兩個或更多的 key 被哈希到同一個存儲位置),哈希表可能需要重新分配更多的空間,並重新哈希所有的元素以避免衝突。這個過程可能會導致元素的順序發生變化。
此外,Go 還有意地在每次運行程序時使用不同的哈希種子,以增加 map 的安全性並避免某些類型的攻擊。這意味着即使你使用相同的鍵集合,每次運行程序時 map 的元素順序也可能會改變。
因此,Go 語言中的 map 數據結構並不保證元素的順序,遍歷 map 的結果是無序的。如果你需要有序的鍵值對,你可能需要使用其他的數據結構,如排序的切片或者專門的有序 map 庫。
能介紹一下Golang中的map的擴容機制嗎?
Go語言的map
實際上是一個哈希表,它的大小會動態變化。當map
的元素數量達到一定閾值時,就會觸發擴容操作,即重新分配更大的內存空間,並將所有的元素重新哈希到新的內存空間中。
具體來說,Go語言的map
擴容規則如下:
-
初始的
map
大小是0。當第一次添加元素時,map
的大小會增加到8。 -
當
map
的元素數量超過其大小的6.5倍時,或者已經存儲的元素數量超過了2^15(32768)時,map
的大小會翻倍。 -
map
的最大大小受限於地址空間的大小和指針的大小。在32位系統中,最大大小約爲231,而在64位系統中,最大大小約爲250。
這種設計使得map
在添加新元素時仍能保持較好的性能,但也意味着添加元素可能需要重新哈希所有的元素,這可能會暫時阻塞map
的其他操作。
因此,如果你知道最終需要存儲的元素數量,那麼在創建map
時預先設置一個足夠大的容量會更加高效,因爲這樣可以避免多次擴容操作。例如:
myMap := make(map[string]int, 10000)
以上代碼創建了一個預期容量爲10000的map
,如果實際元素數量不超過這個值,那麼就不會觸發擴容操作。
Golang中Map的數據結構是什麼?
Go語言中的 map
是一種哈希表數據結構,也就是鍵值對的集合。它的底層實現包括數組、哈希函數、鏈接等關鍵組成部分。
-
數組(Array):數組是
map
的核心組成部分,用於存儲鍵值對(bucket)。每個 bucket 可以存儲一到八個鍵值對。 -
哈希函數(Hash Function):哈希函數接收一個鍵並返回一個整數。這個整數被用來確定鍵值對應該存儲在哪個 bucket 中。
-
鏈接(Linking):如果兩個或更多的鍵哈希到同一個 bucket,那麼它們會被鏈接在一起。這就是所謂的哈希衝突。爲了解決這個問題,Go 的
map
使用了鏈接技術,也就是說,它在同一個 bucket 中存儲了一個鍵值對的鏈表。
以下是一個簡單的例子:
package main
import "fmt"
func main() {
// 創建一個空的 map
m := make(map[string]int)
// 添加鍵值對
m["apple"] = 1
m["banana"] = 2
// 獲取和打印鍵值對
fmt.Println(m["apple"]) // 輸出:1
fmt.Println(m["banana"]) // 輸出:2
}
在這個例子中,我們創建了一個空的 map
,然後添加了兩個鍵值對。當我們從 map
中獲取一個值時,Go 使用哈希函數確定鍵的哈希值,然後在對應的 bucket 中查找鍵值對。
需要注意的是,Go 的 map
是動態大小的。當向 map
中添加更多的鍵值對時,如果當前的數組容量不足以容納更多的數據,Go 就會創建一個新的、更大的數組,並把舊的數據複製到新的數組中。這個過程被稱爲重新哈希(rehashing)。
在Golang中,任意類型T()都能夠調用*T的方法嗎?反過來呢?
在 Go 語言中,對於一個給定的類型 T
,接收者爲 T
的方法可以被 T
類型的值和 *T
類型的指針調用。這是因爲 Go 在嘗試匹配方法接收者的類型時會自動做取址或解引用的操作。
例如:
type MyType int
func (m MyType) ValueMethod() {
fmt.Println("ValueMethod called")
}
func (m *MyType) PointerMethod() {
fmt.Println("PointerMethod called")
}
var v MyType
var p = &v
v.ValueMethod() // 正常調用
p.ValueMethod() // 正常調用,Go 自動將 p 解引用
v.PointerMethod() // 正常調用,Go 自動取 v 的地址
p.PointerMethod() // 正常調用
然而,如果 T
是一個接口類型,情況就有所不同。接口類型的值不能調用接口類型的指針的方法。
總的來說,對於非接口類型 T
和 *T
,它們可以調用彼此的方法。但對於接口類型,值類型接口不能調用指針類型接口的方法。這是因爲接口類型的值和指針遵循不同的規則。
由於內容太多,更多內容以鏈接形勢給大家,點擊進去就是答案了
20. 請問在Golang中,函數返回局部變量的指針是否安全?
24. Golang的切片作爲函數參數是值傳遞還是引用傳遞?
26. Golang中nil map 和空 map 的區別是什麼?
27. 在Golang中,刪除一個key後,它的內存會被釋放嗎?
29. Golang 調用函數傳入結構體時,應該傳值還是指針?
43. 請說一下Go 中 uintptr 和 unsafe.Pointer 的區別?
44. 簡述一下Golang空結構體 struct{} 的使用 ?
47. Switch 中如何強制執行下一個 case 代碼塊 ?
52. 闡述一下Printf()、Sprintf()、Fprintf()函數的區別和用法?
53. 闡述一下Go 如何Array 類型的值作爲函數參數 ?
58. nil interface 和 nil interface 有什麼區別 ?
59. Golang導入包時,爲什麼可能使用’ _’ /’ .'導入? 舉例說明
60. 在Golang中,接口類型是否支持像Java那樣的多繼承?