github.com/enetx/g@v1.0.80/pkg/dbg/dbg.go (about)

     1  package dbg
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"os"
     7  	"path/filepath"
     8  	"runtime"
     9  	"strings"
    10  )
    11  
    12  // CallerInfo retrieves and formats the file name and line number of the caller's
    13  // location in the source code.
    14  //
    15  // It uses the runtime.Caller function to determine the caller's file and line
    16  // information.
    17  //
    18  // Example usage:
    19  //
    20  //	callerInfo := CallerInfo()
    21  //	fmt.Println("Caller:", callerInfo)
    22  //
    23  // The output will look like this:
    24  //
    25  //	Caller: [filename:line]
    26  //
    27  // Where "filename" is the name of the file where the caller is located, and
    28  // "line" is the line number in that file.
    29  func CallerInfo() string {
    30  	pc, file, line, ok := runtime.Caller(1)
    31  	if !ok {
    32  		fmt.Fprintln(os.Stderr, "dbg.CallerInfo: Unable to parse runtime caller")
    33  		return ""
    34  	}
    35  
    36  	out := fmt.Sprintf("[%s:%d] [%s]", filepath.Base(file), line, runtime.FuncForPC(pc).Name())
    37  
    38  	return out
    39  }
    40  
    41  // Dbg is a debugging utility function that prints the given expression and its
    42  // location in the source code to standard output. It also prints the file name
    43  // and line number where the Dbg function is called.
    44  //
    45  // Parameters:
    46  //
    47  //	exp  - The expression or value to be printed.
    48  //
    49  // Example:
    50  //
    51  //	Dbg(someValue)
    52  //
    53  // The output will look like this:
    54  //
    55  //	[filename:line] variable = value
    56  //
    57  // Where "filename" is the name of the file where Dbg is called, "line" is the
    58  // line number in that file, "variable" is the variable or expression being
    59  // debugged, and "value" is the value of the expression.
    60  func Dbg(exp any) {
    61  	pc, file, line, ok := runtime.Caller(1)
    62  	if !ok {
    63  		fmt.Fprintln(os.Stderr, "dbg.Dbg: Unable to parse runtime caller")
    64  		return
    65  	}
    66  
    67  	f, err := os.Open(file)
    68  	if err != nil {
    69  		fmt.Fprintln(os.Stderr, "dbg.Dbg: Unable to open expected file")
    70  		return
    71  	}
    72  
    73  	defer f.Close()
    74  
    75  	scanner := bufio.NewScanner(f)
    76  	scanner.Split(bufio.ScanLines)
    77  
    78  	var out string
    79  	for i := 1; scanner.Scan(); i++ {
    80  		if i == line {
    81  			v := scanner.Text()[strings.Index(scanner.Text(), "(")+1 : strings.LastIndex(scanner.Text(), ")")]
    82  			out = fmt.Sprintf("[%s:%d] [%s] %s = %+v", filepath.Base(file), line, runtime.FuncForPC(pc).Name(), v, exp)
    83  			break
    84  		}
    85  	}
    86  
    87  	if err := scanner.Err(); err != nil {
    88  		fmt.Fprintln(os.Stderr, "error:", err)
    89  		return
    90  	}
    91  
    92  	switch exp.(type) {
    93  	case error:
    94  		fmt.Fprintln(os.Stderr, out)
    95  	default:
    96  		fmt.Fprintln(os.Stdout, out)
    97  	}
    98  }