[Golang] 指針類型和非指針類型的一個比較有意思的案例

從指針類型和非指針類型引發的一個比較有意思的案例

前景提要:

在用golang開發的時候難免會碰到併發的情況,要控制數據的一致性的時候就得用到鎖這個對象。我定義的一個結構體裏面聲明sync.Map或者sync.Mutex。我發現可以直接用這個結構體裏面的sync對象去lock。這是一個比較有意思的現象,我們知道如果nil去調用就會引發panic。這可能就涉及到一些指針和非指針初始化的概念。

案例介紹

接下來就簡單的演示一下代碼和從sync的源碼上面分析一波爲什麼可以直接使用函數而不需要做任何的初始化。

結構體裏面就只定義一個互斥鎖的值類型對象。

package main

import (
	"fmt"
	"sync"
)

type foo struct {
	l sync.Mutex
}

func main() {
	f := foo{}
	f.l.Lock()
	fmt.Println("hello world")
	f.l.Unlock()
}

上面的代碼執行結果就是“hello world”。

結構體裏面就只定義一個互斥鎖的指針類型對象。

package main

import (
	"fmt"
	"sync"
)

type foo struct {
	l *sync.Mutex
}

func main() {
	f := foo{}
	f.l.Lock()
	fmt.Println("hello world")
	f.l.Unlock()
}

上面的代碼執行結果就是直接panic。上面的這兩個結果還是比較有意思的。指針類型和值類型的初始化爲啥會引發這麼大的差別。
結論是因爲sync.Mutex這個結構體裏面就是兩個基礎類型,一個是int32,一個是uint32. 如果值類型自動初始化的話會是0,也就是說這個結構對象直接是{0,0}。但是如果是指針類型的話,就會是nil。nil直接去調用用接受者是他本身的方法就會直接報panic,值類型反而不會報錯就是因爲0的存在。 mutex的結構如下。sync的map也是用的mutex,所以本質上還是一樣的。

type Mutex struct {
	state int32
	sema  uint32
}

總結

這個設計還是很有意思的。這種設計要怎麼引入到客戶端而不那麼突兀也是一個值得思考的問題。這裏也引發了另外一個問題,什麼時候用指針,什麼時候用值類型,config如果用指針的話,怎麼在入口打印參數的時候不顯示地址直接顯示值?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章