dsxpt62448 2018-04-01 06:04
浏览 55

通用REST API Golang

Searching SO for Generic REST API Golang gives 0 results. Searching Google gives 2 results. So this question is maybe not correctly formulated or it is impossible to achieve in Golang.

My goal is to avoid repeating similar code over and over again. So I am trying to make the code in Golang as generic as possible. Write once, use many.

This is my first attempt to create a generic REST API for select in Golang. The code below gives almost what I want:

But the result is presented in the Terminal. I have no idea how to redirect the result to the browser.

package main

import (
    "fmt"
    "log"
    "net/http"
    "database/sql"
    "time"
    _ "github.com/lib/pq"
)

var db *sql.DB

func main() {
   Connect()
   http.HandleFunc("/", Query)
   log.Fatal(http.ListenAndServe(":8080", nil))
}

func Connect() {
   const (
   host = "127.0.0.1"
   port = 5432
   user = "test"
   password = "test"
   dbname  = "Test")

login := fmt.Sprintf("host=%s port=%d user=%s "+"password=%s dbname=%s sslmode=require", host, port, user, password, dbname)
var err error
  db, err = sql.Open("postgres", login)
if err != nil {
    log.Fatalln(err)
}
err = db.Ping()
  if err != nil {
  panic(err)
}

func Query(w http.ResponseWriter, r *http.Request) {

   var query string
   switch r.URL.String() {
   case "/getuser":
      query = "select * from getuser()"
   case "/getco":
      query = "select * from getco()"
   case "/etc"
      query = "select * from etc"
   default:
      query = ""
   }

  var err error
  var rows *sql.Rows

  rows, err = db.Query(query)
  if err != nil {
      http.Error(w, http.StatusText(500), 500)
      return
   }
  defer rows.Close()

  cols, err := rows.Columns()
  vals := make([]interface{}, len(cols))
  for i := 0; i < len(cols); i++ {
      vals[i] = new(interface{})
      if i != 0 {
        fmt.Print("\t")
      }
      fmt.Print(cols[i])
   }
fmt.Println()

for rows.Next() {
    err = rows.Scan(vals...)
    if err != nil {
        fmt.Println(err)
        continue
    }
    for i := 0; i < len(vals); i++ {
        if i != 0 {
            fmt.Print("\t")
        }
        printValue(vals[i].(*interface{}))
    }
    fmt.Println()
}


func printValue(pval *interface{}) {
    switch v := (*pval).(type) {
    case nil:
        fmt.Print("NULL")
    case bool:
        if v {
           fmt.Print("1")
        } else {
           fmt.Print("0")
        }
    case []byte:
        fmt.Print(string(v))
    case time.Time:
        fmt.Print(v.Format("2006-01-02"))
    default:
        fmt.Print(v)
    }
 }

Every attempt to write to the browser gives various type of errors:

fmt.Printf("%s
", vals...)

My questions are

  1. How do I redirect the result to the browser?
  2. Is there any better way to achieve this? (reuse generic code)
  • 写回答

2条回答 默认 最新

  • dpjjmo3079 2018-04-01 06:35
    关注
    1. write response with appropriahe HTTP hearers && status code

      import "net/http"
      
      func writeResponse(w http.ResponseWriter, contents []byte) {
          w.Header().Set("Content-Type", "text/plain; charset=utf-8")
          w.Header().Set("X-Content-Type-Options", "nosniff")
          w.WriteHeader(http.StatusOK)
          fmt.Fprintln(w, contents)
      }
      
    2. sounds a little unclear, sorry

    评论

报告相同问题?

悬赏问题

  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100