http 服务响应 =》 db 存储

Run Settings
LanguageGo
Language Version
Run Command
package main import ( "log" "net/http" ) func main() { server := &http.Server{ Handler: handler, } // 创建标准输入输出监听器 listener := NewStdioListener() // 在标准输入输出连接上处理单个HTTP请求 log.Println("启动标准输入输出HTTP服务器...") go func() { listener.Wait() log.Println("关闭 Server...") log.Println("关闭标准输入输出HTTP服务器: ", server.Close()) }() // 启动 HTTP 服务 if err := server.Serve(listener); err != nil { if err != http.ErrServerClosed { panic(err) } } }
module glot require ( github.com/gorilla/mux v1.8.1 github.com/duckdb/duckdb-go/v2 v2.5.1 )
package main import ( "database/sql" "errors" "fmt" "log" "net/http" "net/http/httputil" "github.com/gorilla/mux" _ "github.com/duckdb/duckdb-go/v2" ) var ( handler = mux.NewRouter() ) func init() { handler.HandleFunc("/save/{table}", func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) // 获取路径参数 w.Header().Set("Content-Type", "text/plain; charset=utf-8") w.WriteHeader(http.StatusOK) w.Write([]byte("Hello from stdin/stdout HTTP server!\n"+handle(vars["table"]))) }) handler.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { req, _ :=httputil.DumpRequest(r, false) w.WriteHeader(http.StatusNotFound) w.Write(req) }) } func handle(table string) string { db, err := sql.Open("duckdb", "~/.cache/duckdb/duckdb.ddb") if err != nil { log.Fatal(err) } defer db.Close() _, err = db.Exec("CREATE TABLE "+table+" (id INTEGER, name VARCHAR)") if err != nil { log.Fatal(err) } _, err = db.Exec("INSERT INTO people VALUES (42, 'John')") if err != nil { log.Fatal(err) } var ( id int name string ) row := db.QueryRow("SELECT id, name FROM "+table) err = row.Scan(&id, &name) if errors.Is(err, sql.ErrNoRows) { log.Println("no rows") } else if err != nil { log.Fatal(err) } return fmt.Sprintf("id: %d, name: %s\n", id, name) }
package main import ( "bufio" "errors" "io" "log" "net" "os" "sync" "time" ) // ------------------------------ // 实现一个 net.Listener // ------------------------------ type stdioListener struct { conn net.Conn done chan struct{} close chan struct{} } func NewStdioListener() *stdioListener { done := make(chan struct{}) return &stdioListener{ conn: NewStdioConn(done), done: done, close: make(chan struct{}), } } func (l *stdioListener) Wait() { <-l.done } func (l *stdioListener) Accept() (net.Conn, error) { if l.conn != nil { conn := l.conn l.conn = nil return conn, nil } log.Println("!!!!111...") log.Println("!!!!222...") <-l.close log.Println("!!!!333...") return nil, net.ErrClosed } func (l *stdioListener) Close() error { log.Println("关闭 stdioListener...") close(l.close) return nil } func (l *stdioListener) Addr() net.Addr { return &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)} } // StdioConn 实现 net.Conn 接口,将 stdin/stdout 作为连接 type StdioConn struct { reader *bufio.Reader writer *bufio.Writer closed bool closeCh chan struct{} mutex sync.Mutex deadline time.Time } func NewStdioConn(closeCh chan struct{}) *StdioConn { return &StdioConn{ reader: bufio.NewReader(os.Stdin), writer: bufio.NewWriter(os.Stdout), closeCh: closeCh, } } func (c *StdioConn) Read(b []byte) (n int, err error) { c.mutex.Lock() defer c.mutex.Unlock() if c.closed { return 0, io.EOF } if !c.deadline.IsZero() && time.Now().After(c.deadline) { return 0, errors.New("read timeout") } return c.reader.Read(b) } func (c *StdioConn) Write(b []byte) (n int, err error) { c.mutex.Lock() defer c.mutex.Unlock() if c.closed { return 0, io.EOF } n, err = c.writer.Write(b) if err != nil { return n, err } return n, c.writer.Flush() } func (c *StdioConn) Close() error { c.mutex.Lock() defer c.mutex.Unlock() log.Println("关闭 StdioConn...") close(c.closeCh) c.closed = true return nil } func (c *StdioConn) LocalAddr() net.Addr { return &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)} } func (c *StdioConn) RemoteAddr() net.Addr { return &net.IPAddr{IP: net.IPv4(127, 0, 0, 1)} } func (c *StdioConn) SetDeadline(t time.Time) error { c.mutex.Lock() defer c.mutex.Unlock() c.deadline = t return nil } func (c *StdioConn) SetReadDeadline(t time.Time) error { return c.SetDeadline(t) } func (c *StdioConn) SetWriteDeadline(t time.Time) error { return c.SetDeadline(t) }
{ "in":"http", "out":"http", "debug": true, "command":"go mod tidy && go run ." }
Editor Settings
Theme
Key bindings
Full width
Lines