How to use Scan interface to lowercase a string read from the database

huangapple go评论90阅读模式
英文:

How to use Scan interface to lowercase a string read from the database

问题

我想要将从数据库中读取的字符串转换为小写。我知道这可以在SQL中完成,但这是我使用Go的第一天,这更多是一个概念验证(以及对Go的理解),而不是实际需求。

类型EmailAddress在使用Scan接口从数据库中读取时应始终为小写,但这会导致panic: interface conversion: interface is []uint8, not string。

package main

import (
  "database/sql"
  "github.com/kisielk/sqlstruct"
  _ "github.com/lib/pq"
  "log"
  "strings"
)

type EmailAddress string

func (g *EmailAddress) Scan(src interface{}) error {
  *g = EmailAddress(strings.ToLower(src.(string)))
  return nil
}

type User struct {
  Id          int
  MobilePhone string `sql:"mobile_phone"`
  Email       EmailAddress
}

func main() {
  db, _ := sql.Open("postgres", "host=localhost dbname=test sslmode=disable")
  defer db.Close()

  rows, _ := db.Query("SELECT id, mobile_phone, COALESCE(email,'') as email FROM users limit 5")

  for rows.Next() {
    var t User
    _ = sqlstruct.Scan(&t, rows)
    log.Printf("%+v\n", t)
  }
}

以上是你提供的代码的翻译。

英文:

I want to lower case a string as I read it in from the database. I know this can be done in SQL, but this is my first day with go and this is more of a proof of concept (and understanding of go) rather than an actual requirement.

type EmailAddress should always be lowercase when read from the db using the Scan interface, this breaks with panic: interface conversion: interface is []uint8, not string

package main

import (
  "database/sql"
  "github.com/kisielk/sqlstruct"
  _ "github.com/lib/pq"
  "log"
  "strings"
)

type EmailAddress string

func (g *EmailAddress) Scan(src interface{}) error {
  *g = EmailAddress(strings.ToLower(src.(string)))
  return nil
}

type User struct {
  Id          int
  MobilePhone string `sql:"mobile_phone"`
  Email       EmailAddress
}

func main() {
  db, _ := sql.Open("postgres", "host=localhost dbname=test sslmode=disable")
  defer db.Close()

  rows, _ := db.Query("SELECT id, mobile_phone, COALESCE(email,'') as email FROM users limit 5")

  for rows.Next() {
    var t User
    _ = sqlstruct.Scan(&t, rows)
    log.Printf("%+v\n", t)
  }
}

答案1

得分: 11

你看到[]uint8错误是因为EmailAddress被提供为一个字节切片,而不是一个字符串。记住,byte只是uint8的别名。这里有一个简单的示例展示了你看到的错误:http://play.golang.org/p/iN5y3PaFAL

所以,最简单的修复方法是改变scan函数:

func (g *EmailAddress) Scan(src interface{}) error {
  b, ok := src.([]byte)
  if !ok {
    return fmt.Errorf("expected []byte, got %T", src)
  }
  *g = EmailAddress(strings.ToLower(string(b)))
  return nil
}
英文:

You're seeing the []uint8 error because the EmailAddress is being provided as a byte slice, rather than a string. Remember, byte is just an alias for uint8. Here's a simple example which shows the error you're seeing: http://play.golang.org/p/iN5y3PaFAL

So, the easiest fix would be to change the scan function:

func (g *EmailAddress) Scan(src interface{}) error {
  b, ok := src.([]byte)
  if !ok {
    return fmt.Errorf("expected []byte, got %T", src)
  }
  *g = EmailAddress(strings.ToLower(string(b))
  return nil
}

huangapple
  • 本文由 发表于 2013年12月14日 15:19:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/20580746.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定