異なるゴルーチンに匿名関数によって呼び出される方法https://play.golang.org/p/c_2GECIcrW
私はgetFileNameがmain.goのようなものをプリントアウトすることを期待何:11しかし、私は何を取得asm_amd64p32.s:1014runtime.Callerによって実際のファイル名を取得するために、私は、この例のコードを持って
この場合、予期した結果を得るにはどうすればよいですか?
これをアーカイブしても、匿名機能を使用することはできますか?
異なるゴルーチンに匿名関数によって呼び出される方法https://play.golang.org/p/c_2GECIcrW
私はgetFileNameがmain.goのようなものをプリントアウトすることを期待何:11しかし、私は何を取得asm_amd64p32.s:1014runtime.Callerによって実際のファイル名を取得するために、私は、この例のコードを持って
この場合、予期した結果を得るにはどうすればよいですか?
これをアーカイブしても、匿名機能を使用することはできますか?
あなたの期待は間違っています。
私は説明を簡単にするためにここにコードを貼り付けてみましょう:
package main
import (
"fmt"
"path/filepath"
"runtime"
"time"
)
func main() {
getFileName(1)
time.Sleep(time.Hour)
}
func getFileName(shift int) {
go func() {
_, file, line, ok := runtime.Caller(shift)
if !ok {
file = "???"
line = 0
} else {
file = filepath.Base(file)
}
fmt.Printf("%s:%d", file, line)
}()
}
あなたの匿名関数がgetFileName
によって生成されたゴルーチンで実行されています。
各ゴルーチンは、getFileName
によって生成されたゴルーチンが新しくスタックから始まっても、独自のコールスタックを使用して実行されます。
スキップ値が0より大きいruntime.Caller(skip int)
を呼び出すと、現在のゴルーチンのスタックフレームを歩くことができます。あなたの例では
:
runtime.Caller(0)
プリントmain.go:それはあるので、1014:17これはruntime.Caller()
が実際に、runtime.Caller(1)
プリントasm_amd64p32.sと呼ばれるラインであるため、現在のゴルーチンのスタックの最上部、runtime.Caller(x)
x> 1の戻り値はブール値ok
がfalse
に設定されています。スタック上部のメモリにアクセスすることができます。あなたは何asm_amd64p32.s迷っている場合:1014を実際にそれが行く1.8のgoexitアセンブリ関数(ゴー遊び場が行くの最新の安定版リリースで実行)に対応して、表しています。その名前にもかかわらず、goexit
関数は常にゴルーチンスタックの最上位にあります。ゴルーチンエントリポイント関数を呼び出し、関数が復帰した後にスタックをクリーンアップします。 goexit
の実装はアーキテクチャ固有で、goroutinesスタックの詳細を処理するほとんどのコードであるためです。
戻るあなたの質問に、あなたはmain.go見ることを期待することはできません。主な機能は全くスタックではないので、getFileName
によって生成されたゴルーチンのスタックトレースで述べた11を。 main関数のスタックトレースを実際に印刷する必要がある場合は、goroutineを生成しないでください。
言われておられますが、言及すべきことがあります。 Goランタイムには、実際にゴルーチンが生成された場所に関する追加情報が実際に格納されます。
package main
import (
"time"
"runtime/debug"
)
func main() {
getFileName(1)
time.Sleep(time.Hour)
}
func getFileName(shift int) {
go func() {
debug.PrintStack()
}()
}
出力:
goroutine 5 [running]:
runtime/debug.Stack(0x0, 0x0, 0x0, 0x0)
/usr/local/go/src/runtime/debug/stack.go:24 +0x80
runtime/debug.PrintStack()
/usr/local/go/src/runtime/debug/stack.go:16 +0x20
main.getFileName.func1()
/tmp/sandbox085104368/main.go:15 +0x20
created by main.getFileName
/tmp/sandbox085104368/main.go:16 +0x40
すべてのこれらの詳細は、実装に依存し、被写体までのビーイング(runtime.Stack()に基づいて順番にある)debug.PrintStack()機能はきれいにフォーマットスタックトレースでそれをプリントアウトすることができます異なるGoリリース間で変更すると、標準ライブラリを介して簡単にアクセスすることはできません。これらはデバッグ目的で提供されており、開発者はこれらの情報に頼るべきではありません。
できません。ごめんなさい。 – Volker
「シフト」で何が欲しいか不明です。 'runtime.Caller(0)'を使うと、新しいgoroutineとして開始された無名関数内のmain.go:17 "'を得ることができます。 – icza
'main.go:11'(getFileNameの呼び出し側)を取得したい – nvcnvn