2017-05-27 4 views
-1

次のコードは、次のエラーでクラッシュします。RWMutexの初期化はgolangでクラッシュしますか?

package main 

import (
    "sync" 

) 

var foo *sync.RWMutex 

func main() { 
    foo.Lock() 
} 

出力:

panic: runtime error: invalid memory address or nil pointer dereference 
[signal SIGSEGV: segmentation violation code=0xffffffff addr=0x0 pc=0x8125c] 

goroutine 1 [running]: 
sync.(*RWMutex).Lock(0x0, 0x104000f0) 
    /usr/local/go/src/sync/rwmutex.go:86 +0x1c 
main.main() 
    /tmp/sandbox093456788/main.go:11 +0x20 

Program exited. 

それは発生しません、あなたがfoo変数の初期化のため

var foo = new(sync.RWMutex) 
var foo sync.RWMutex 

次の行のいずれかを使用します。

+0

歓迎は、私はあなたが行くツアーを見てお勧めしますhttps://tour.golang.org/welcome/1 –

答えて

2

ミューテックスは、一般に、どのようなタイプの初期化も行わないように設計されています。つまり、ゼロ値のミューテックスを使用するだけです。プログラムを修正するには、fooを値として宣言します。あなたはポインタとしてfooを宣言すると

var foo sync.RWMutex 

func main() { 
    foo.Lock() 
} 

:ミューテックスのないポインタが

var foo *sync.RWMutex 

fooがゼロ値ポインタであるsync.RWMutexを入力する)、すなわち、それは指していません有効なミューテックス値。 foonilです。そのため、メソッドを呼び出すときにnilポインタ例外が発生します。

しかし、ゴルーチンと関数の間のミューテックスを共有するには、それらをポインタとして渡す必要があります(上記のように初期化された後、または共有されません)。ドキュメントから

アンRWMutexは、最初の使用後にコピーしてはいけません。

ドキュメント:StackOverflowのにhttps://golang.org/pkg/sync/#RWMutex

+0

OKので、パニックがあるため構造体のメンバにアクセスするので起こりますRWMutex構造体のwです。このためには、この構造体へのポインタはnilであるため、逆参照する必要があります。 Goの奇妙なデフォルトは、ポインタを返すnew()演算子のように初期化しないのはなぜですか? – dibbidabbi

+0

'new'は型を完全に初期化し、それにポインタを返します。初期化を行わずに 'var'を実行すると、その型のゼロ値に設定された型が作成されます。 'foo'が完全に初期化されたmutexへのポインタであるため、元のコードを' var foo = new(sync.RWMutex) 'に変更するとエラーも修正されます。 – abhink

関連する問題