Files
nl-blogs/server/runner/go_runner.go

69 lines
1.4 KiB
Go
Raw Normal View History

2026-01-15 13:51:44 +08:00
package runner
import (
"bytes"
"context"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"time"
"github.com/google/uuid"
)
type GoRunner struct {
TempDir string
}
func (r *GoRunner) Run(ctx context.Context, code string) (*ExecutionResult, error) {
// 创建唯一的工作目录
workDir := filepath.Join(r.TempDir, uuid.New().String())
if err := os.MkdirAll(workDir, 0755); err != nil {
return nil, err
}
defer os.RemoveAll(workDir) // 清理
// 写入main.go
// 注意这里假设代码是一个完整的package main
// 如果用户只提供了函数片段,可能需要包装。这里假设是完整代码。
filePath := filepath.Join(workDir, "main.go")
if err := ioutil.WriteFile(filePath, []byte(code), 0644); err != nil {
return nil, err
}
// 准备命令
// 使用 go run 运行
cmd := exec.CommandContext(ctx, "go", "run", "main.go")
cmd.Dir = workDir
// 捕获输出
var stdout, stderr bytes.Buffer
cmd.Stdout = &stdout
cmd.Stderr = &stderr
startTime := time.Now()
err := cmd.Run()
duration := time.Since(startTime).Milliseconds()
result := &ExecutionResult{
Output: stdout.String(),
Error: stderr.String(),
Duration: duration,
}
if err != nil {
if exitErr, ok := err.(*exec.ExitError); ok {
result.ExitCode = exitErr.ExitCode()
} else {
result.ExitCode = -1
}
// 如果是超时
if ctx.Err() == context.DeadlineExceeded {
result.Error += "\nExecution timed out"
}
}
return result, nil
}