FAQ
Hello all

I have two questions.

One is just to hear from many other experienced Gophers about my FetchAll function. I find it quite useful since it works for any type of SQL database and I wrote this expecting to use fetch function in Python. All data are saved in string format and I just convert it to other data types if I need to. Would this be efficient? I want to use the best possible way in Go for querying. What do you think? If this is terrible, how would you query from SQL database?


// FetchAll returns the results from the input query.
// This returns a slice of each row from the results.
// Each map(row)'s key is the column name that maps into a value.
// Columns consist of `select` components.
// Ints and floats are all saved in string format
// to be converted later.
func FetchAll(db *sql.DB, query string) []map[string]string {

  rows, err := db.Query(query)
  if err != nil {
   time.Sleep(5 * time.Second)
   rows, err = db.Query(query)
   if err != nil {
    log.Fatal(err)
   }
  }
  defer rows.Close()

  colNames, err := rows.Columns()
  if err != nil {
   log.Fatal(err)
  }

  // Make a slice for the values
  colValues := make([]sql.RawBytes, len(colNames))

  // from sql.RawBytes to interface
  // rows.Scan wants '[]interface{}' as an argument, so we must copy the
  // references into such a slice
  // See http://code.google.com/p/go-wiki/wiki/InterfaceSlice for details
  scanArgs := make([]interface{}, len(colValues))
  for i := range colValues {
   //
   // This does only copying
   // (X) for i, col := range colValues {
   // (X) scanArgs[i] = &col
   //
   scanArgs[i] = &colValues[i]
  }

  // map column to its data
  results := []map[string]string{}

  // Fetch rows
  for rows.Next() {
   err = rows.Scan(scanArgs...)
   if err != nil {
    log.Fatal(err)
   }
   rmap := make(map[string]string)
   for i, col := range colValues {
    // Here we can check if the value is nil (NULL value)
    if col == nil {
     rmap[colNames[i]] = "NULL"
    } else {
     rmap[colNames[i]] = string(col)
    }
   }
   results = append(results, rmap)
  }

  return results
}


---

2. In general what would be the benefit of using Go in SQL at database processing? The function above can be done in much easier way with Python since it has no data types like Go but I just want to use Go to feel more of ownership.

Now I am deciding which to use for my project. A lot of queries and possible SQL database manipulation... How would I take advantage of Go when dealing with SQL?

Thank you all

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Matt Silverlock at Jul 18, 2014 at 3:28 am
    A few comments:


        1. time.Sleep and retrying sounds good in practice, but a 5 second block
        (which is effectively what that is) is a *long* time in the world of web
        applications. Many clients may even time out. If your database is returning
        a genuine error, just deal with it in the present and let the user decide
        whether to retry. Chances are it'll probably return the same error when you
        try again.
        2. In terms of code maintenance and performance, marshalling your query
        results into a struct is nearly always the best thing to do. In most cases
        you'll know what your queries are (or at least, what they might possibly
        return). If you're dealing with arbitrary queries on a regular basis, then
        use maps—but only then.
        3. Returning the results as a map[string]string means that useful types
        like times, byte strings and so on become incredibly hard to deal with.
        Your caller would have to type assert or (worse!) attempt to parse the
        values into their desired format.

    My suggestion would be that if you want an ORM,
    use https://github.com/coopernurse/gorp — otherwise, use something like
    sqlx (http://jmoiron.github.io/sqlx/) which is a fantastic "shim" over Go's
    database/sql package.

    Attempting to be "database agnostic" at a query level sounds great in
    theory, but is pretty hard to actually achieve in practice (hence the
    weakness of ORMs). Changing between datastores isn't (in my experience)
    something that happens often anyway.

    In reply to #2: it totally depends on what you are trying to do. Go is
    fast, and is probably going to be faster at *doing things with the results*
    compared to Python, but if you're only dealing with small amounts of data
    then Python can still be useful.

    On Friday, July 18, 2014 10:02:56 AM UTC+8, Gyu-Ho Lee wrote:

    Hello all

    I have two questions.

    One is just to hear from many other experienced Gophers about my FetchAll
    function. I find it quite useful since it works for any type of SQL
    database and I wrote this expecting to use fetch function in Python. All
    data are saved in string format and I just convert it to other data types
    if I need to. Would this be efficient? I want to use the best possible way
    in Go for querying. What do you think? If this is terrible, how would you
    query from SQL database?


    // FetchAll returns the results from the input query.
    // This returns a slice of each row from the results.
    // Each map(row)'s key is the column name that maps into a value.
    // Columns consist of `select` components.
    // Ints and floats are all saved in string format
    // to be converted later.
    func FetchAll(db *sql.DB, query string) []map[string]string {

    rows, err := db.Query(query)
    if err != nil {
    time.Sleep(5 * time.Second)
    rows, err = db.Query(query)
    if err != nil {
    log.Fatal(err)
    }
    }
    defer rows.Close()

    colNames, err := rows.Columns()
    if err != nil {
    log.Fatal(err)
    }

    // Make a slice for the values
    colValues := make([]sql.RawBytes, len(colNames))

    // from sql.RawBytes to interface
    // rows.Scan wants '[]interface{}' as an argument, so we must copy
    the
    // references into such a slice
    // See http://code.google.com/p/go-wiki/wiki/InterfaceSlice for
    details
    scanArgs := make([]interface{}, len(colValues))
    for i := range colValues {
    //
    // This does only copying
    // (X) for i, col := range colValues {
    // (X) scanArgs[i] = &col
    //
    scanArgs[i] = &colValues[i]
    }

    // map column to its data
    results := []map[string]string{}

    // Fetch rows
    for rows.Next() {
    err = rows.Scan(scanArgs...)
    if err != nil {
    log.Fatal(err)
    }
    rmap := make(map[string]string)
    for i, col := range colValues {
    // Here we can check if the value is nil (NULL
    value)
    if col == nil {
    rmap[colNames[i]] = "NULL"
    } else {
    rmap[colNames[i]] = string(col)
    }
    }
    results = append(results, rmap)
    }

    return results
    }


    ---

    2. In general what would be the benefit of using Go in SQL at database
    processing? The function above can be done in much easier way with Python
    since it has no data types like Go but I just want to use Go to feel more
    of ownership.

    Now I am deciding which to use for my project. A lot of queries and
    possible SQL database manipulation... How would I take advantage of Go when
    dealing with SQL?

    Thank you all
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Gyu-Ho Lee at Jul 20, 2014 at 6:16 am
    Ok I see.
    Thanks!

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Marko at Jul 18, 2014 at 8:41 am

    On Friday, July 18, 2014 4:02:56 AM UTC+2, Gyu-Ho Lee wrote:

    // Fetch rows
    for rows.Next() {
    <snip> }
    return results
    }
    You really have to look at rows.Err() after rows.Next() has returned false.


    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedJul 18, '14 at 2:02a
activeJul 20, '14 at 6:16a
posts4
users3
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase