Подтвердить что ты не робот

Можно ли получить информацию о функции вызывающего абонента в Голанге?

Можно ли получить информацию о функции вызывающего абонента в Голанге? Например, если у меня есть

func foo() {
    //Do something
}
func main() {
    foo() 
}

Как я могу получить, что foo был вызван из main?
Я могу это сделать на другом языке (например, в С# мне просто нужно использовать CallerMemberName класса CallerMemberName)

4b9b3361

Ответ 1

в продолжение моего комментария, здесь приведен код, который возвращает текущий вызов функции

import(
    "fmt"
    "runtime"
)

func getFrame(skipFrames int) runtime.Frame {
    // We need the frame at index skipFrames+2, since we never want runtime.Callers and getFrame
    targetFrameIndex := skipFrames + 2

    // Set size to targetFrameIndex+2 to ensure we have room for one more caller than we need
    programCounters := make([]uintptr, targetFrameIndex+2)
    n := runtime.Callers(0, programCounters)

    frame := runtime.Frame{Function: "unknown"}
    if n > 0 {
        frames := runtime.CallersFrames(programCounters[:n])
        for more, frameIndex := true, 0; more && frameIndex <= targetFrameIndex; frameIndex++ {
            var frameCandidate runtime.Frame
            frameCandidate, more = frames.Next()
            if frameIndex == targetFrameIndex {
                frame = frameCandidate
            }
        }
    }

    return frame
}

// MyCaller returns the caller of the function that called it :)
func MyCaller() string {
        // Skip GetCallerFunctionName and the function to get the caller of
        return getFrame(2).Function
}

// foo calls MyCaller
func foo() {
    fmt.Println(MyCaller())
}

// bar is what we want to see in the output - it is our "caller"
func bar() {
    foo()
}

func main(){
    bar()
}

Дополнительные примеры: https://play.golang.org/p/cv-SpkvexuM

Ответ 2

Вы можете использовать runtime.Caller для удобства получения информации о вызывающем абоненте:

func Caller(skip int) (pc uintptr, file string, line int, ok bool)

Пример # 1: напечатать имя и номер вызывающего абонента: https://play.golang.org/p/cdO4Z4ApHS

package main

import (
    "fmt"
    "runtime"
)

func foo() {
    _, file, no, ok := runtime.Caller(1)
    if ok {
        fmt.Printf("called from %s#%d\n", file, no)
    }
}

func main() {
    foo()
}

Пример # 2: Получить дополнительную информацию с помощью runtime.FuncForPC: <а3 >

package main

import (
    "fmt"
    "runtime"
)

func foo() {
    pc, _, _, ok := runtime.Caller(1)
    details := runtime.FuncForPC(pc)
    if ok && details != nil {
        fmt.Printf("called from %s\n", details.Name())
    }
}

func main() {
    foo()
}