package main import ( "fmt" "go/ast" "go/parser" "go/token" "go/types" "io/ioutil" "os" ) func main() { // Parse the source file inputFile := "hello.go" contents, err := ioutil.ReadFile(inputFile) if err != nil { fmt.Fprintf(os.Stderr, "Error reading file: %v\n", err) os.Exit(1) } fset := token.NewFileSet() file, err := parser.ParseFile(fset, inputFile, contents, parser.ParseComments) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing file: %v\n", err) os.Exit(1) } // Typecheck the AST config := types.Config{Importer: types.DefaultImporter()} info := &types.Info{Types: map[ast.Expr]types.TypeAndValue{}} _, err = config.Check(inputFile, fset, []*ast.File{file}, info) if err != nil { fmt.Fprintf(os.Stderr, "Error typechecking file: %v\n", err) os.Exit(1) } // Print information about the AST fmt.Printf("File %q contains:\n", inputFile) fmt.Printf("%d statements\n", len(file.Decls)) fmt.Printf("%d functions\n", len(info.Defs)) fmt.Printf("%d variables\n", len(info.Uses)) }
package main import ( "bufio" "fmt" "go/token" "go/types" "io/ioutil" "os" "strconv" "strings" ) func main() { // Read input from the user reader := bufio.NewReader(os.Stdin) fmt.Print("Enter an expression to evaluate: ") expr, err := reader.ReadString('\n') if err != nil { fmt.Fprintf(os.Stderr, "Error reading input: %v\n", err) os.Exit(1) } expr = strings.TrimSpace(expr) // Parse the expression string into an AST fset := token.NewFileSet() file, err := parser.ParseFile(fset, "", "package main\nfunc main() { result := "+expr+"; println(result) }", parser.ParseComments) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing expression: %v\n", err) os.Exit(1) } // Typecheck the AST to determine the result type config := types.Config{Importer: types.DefaultImporter()} info := &types.Info{Types: map[ast.Expr]types.TypeAndValue{}} _, err = config.Check("", fset, []*ast.File{file}, info) if err != nil { fmt.Fprintf(os.Stderr, "Error typechecking expression: %v\n", err) os.Exit(1) } resultType := info.Types[file.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.ExprStmt).X].Type // Evaluate the expression using the gc package's evaluator input := []byte(expr) result, _, err := types.Eval(fset, types.NewPackage("main", ""), token.NoPos, string(input), resultType) if err != nil { fmt.Fprintf(os.Stderr, "Error evaluating expression: %v\n", err) os.Exit(1) } // Print the result switch result.Kind() { case types.Bool: fmt.Printf("Result: %v\n", result.Value.(bool)) case types.Int: fmt.Printf("Result: %v\n", result.Value.(int64)) case types.Float32, types.Float64: fmt.Printf("Result: %v\n", result.Value.(float64)) case types.Complex64, types.Complex128: fmt.Printf("Result: %v\n", result.Value.(complex128)) case types.String: fmt.Printf("Result: %q\n", result.Value.(string)) case types.UntypedBool: fmt.Printf("Result: %v\n", result.Value.(bool)) case types.UntypedInt: if n, ok := result.Value.(int64); ok { fmt.Printf("Result: %v\n", n) } else { fmt.Fprintf(os.Stderr, "Error: result is not an int64: %v\n", result.Value) os.Exit(1) } case types.UntypedFloat: if f, ok := result.Value.(float64); ok { fmt.Printf("Result: %v\n", f) } else { fmt.Fprintf(os.Stderr, "Error: result is not a float64: %v\n", result.Value) os.Exit(1) } case types.UntypedComplex: fmt.Fprintf(os.Stderr, "Error: untyped complex expressions are not supported\n") os.Exit(1) case types.UntypedString: fmt.Printf("Result: %q\n", result.Value.(string)) case types.Nil: fmt.Fprintf(os.Stderr, "Error: result is nil\n") os.Exit(1) } }This example demonstrates how to use the `cmd/internal/gc` package to evaluate a Go expression entered by the user at runtime. The `go/parser` and `go/ast` packages are used to parse the expression into an AST, which is typechecked using the `go/types` package to determine the expected result type. The `go/types` package's `Eval` function is used to evaluate the expression and produce its result. Finally, the result is printed to the console, with special handling for each possible result type. Overall, the `cmd/internal/gc` package is an internal package of the Go compiler suite and is not intended for direct use by application code. Rather, it is used by the `go` command and other tools to compile and analyze Go source code.