Общий REST API Golang

Поиск SO для Общий REST API Golang дает 0 результатов. Поиск в Google дает 2 результата. Так что этот вопрос, возможно, неправильно сформулирован или его невозможно решить на Голанге.

Моя цель - не повторять один и тот же код снова и снова. Поэтому я пытаюсь сделать код на Голанге как можно более общим. Напишите один раз, используйте много.

Это моя первая попытка создать общий REST API для выбора в Golang. Приведенный ниже код дает почти то, что я хочу:

Но результат отображается в Терминале. Понятия не имею, как перенаправить результат в браузер.

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)
    }
 }

Каждая попытка записи в браузер выдает различные типы ошибок:

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

Мои вопросы

  1. Как перенаправить результат в браузер?
  2. Есть ли лучший способ добиться этого? (повторно использовать общий код)

разделите Запрос БД и Подключение к БД в отдельных функциях. при записи вывода в стандартный вывод с использованием fmt.Printf() используйте fmt.Fprintf(w, "pattern", vars), это будет записывать вывод в HTTP-ответ.

Rajmani Arya 01.04.2018 08:15

Да, это перенаправляет "результат" в браузер. Но только мусорный текст вроде «шаблон%! (EXTRA * interface {} = 0xc4201aa2b0 etc». В то же время результат по-прежнему выводится в Терминал. Дальнейшие подсказки?

sibert 01.04.2018 08:23

Вы используете безопасный тип языка, чтобы попытаться игнорировать безопасность типов. Найдите молоток получше или сгенерируйте код.

Peter 01.04.2018 11:30

@peter Не могли бы вы рассказать об этом подробнее? Что небезопасно и почему?

sibert 01.04.2018 16:34

Я не сказал, что это небезопасно. Я имел в виду, что есть лучшие варианты, чем использование статически типизированного языка, чтобы затем игнорировать систему типов, помещая interface {} повсюду. Это будет грязно. Вы также можете использовать язык с динамической типизацией, такой как Ruby, Python, PHP.

Peter 01.04.2018 17:26

@peter "rows.Columns ()" - это динамическая (?) команда из golang "database / sql". Как стандартная команда может быть беспорядочной? Простите меня, но я новичок на Голанге и только пытаюсь понять.

sibert 01.04.2018 19:31

Беспорядок заключается в том, как вы должны иметь дело с фактическими строками, а не с именами столбцов. Это намного чище и проще, если вы знаете, с чем работаете. А вы еще даже не написали код для вставок. Попробуй сам. Напишите неуниверсальный код для одной из конечных точек и сравните. Вы увидите, что это намного короче и проще.

Peter 01.04.2018 19:47
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
7
1 030
2

Ответы 2

  1. написать ответ с соответствующими HTTP-слушателями && кодом состояния

    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. звучит немного непонятно, извините

1. Итак, вызов другой функции вне "func Query" ?. Как? 2. Как получить общий REST API. Я пишу один раз, использую много раз. Ссылки, подсказки или что-то еще.

sibert 01.04.2018 08:52

Я бы порекомендовал использовать существующие пакеты, такие как "mux", для вызова REST API в браузере. В качестве быстрой демонстрации, как это можно сделать следующим образом:

ваш restapi.go cound имеет следующие API:

func SampleAPI(w http.ResponseWriter, r *http.Request) { //Assuming this is a POST request
    var example SomeSruct 
    _ = json.NewDecoder(r.Body).Decode(&example) //Decode the POST body
    result := someLogicFunction(example) //call your generic function
    json.NewEncoder(w).Encode(result) //encode the result to pass it back to browser
}

Теперь предположим, что вы пишете main.go и используете пакет mux, вот пример того, как вы бы назвали это

main.go

func main() {
    router := mux.NewRouter()
    router.HandleFunc("/testFunc",restapi.SampleAPI).Methods("POST") //This creates the route for your http request
    handler := cros.Default().Handler(router) //You will need this if you plan to deploy it in a server and call it externally for testing locally you don't need this
    log.Fatal(http.ListenAndServe(":8080", handler)) //Port that the router is listening to
}

Теперь обратите внимание, что вам нужно будет импортировать пакеты «github.com/gorilla/mux» и «github.com/rs/cors», чтобы использовать их, но таким образом вы можете создавать REST API, к которым может получить доступ браузер. Точно так же вы можете создать метод GET и использовать параметры, которые вы можете получить в своей функции и выполнить любой логический шаг.

Если вы соберете и установите приведенный выше код, вы можете выполнить POST в локальный: 8080 / testFunc через http с помощью любого веб-приложения и получить результаты в своем браузере. Если у вас был запрос GET, вы могли напрямую ввести URL-адрес в браузере и увидеть результат.

Другие вопросы по теме