Go: DSN

Нам часто на практике приходится работать c настройки подключения к базам данных (и не только) в стиле pq:

user=mylogin password=mypass database=mydb host=127.0.0.1 port=5432

Один из способов парсинга их — это регулярные выражения:

package main

import (
  "fmt"
  "regexp"
)

var rex = regexp.MustCompile("(\\w+)=(\\w+)")

func main() {
  conn := `user=mylogin password=mypass database=mydb
           host=127.0.0.1 port=5432 sslmode=true`

  data := rex.FindAllStringSubmatch(conn, -1)

  res := make(map[string]string)
  for _, kv := range data {
    k := kv[1]
    v := kv[2]
    res[k] = v
  }

  fmt.Println(res)
}

Но тут есть одно неудобство, если параметр содержит пробельные или специальные символы. В этом случае все усложняется. Чтобы не думать об этом, можно воспользоваться библиотекой wmentor/dns, написанной на Go.

Установка:

go get github.com/wmentor/dsn

Пример использования:

package main

import (
  "fmt"

  "github.com/wmentor/dsn"
)

func main() {

  str := `user=mylogin passwd=mypass database=mydb
          port=5432 sslmode=true`

  ds, err := dsn.New(str)
  if err != nil {
    panic("invalid string")
  }

  // print user=mylogin
  fmt.Printf( "user=%s\n", ds.GetString("user","unknown") )

  // print passwd=mypass
  fmt.Printf( "passwd=%s\n", ds.GetString("passwd","nopass") )

  // host is not exists, print host=127.0.0.1
  fmt.Printf( "host=%s\n", ds.GetString("host","127.0.0.1") )

  // get int value and print port=5432
  fmt.Printf( "port=%d\n", ds.GetInt("port", 4321) )

  // print sslmode=true
  fmt.Printf( "sslmode=%t\n", ds.GetBool("sslmode", false) )

  // print keepalive=false
  fmt.Printf( "keepalive=%t\n", ds.GetBool("keepalive", false) )
}

dsn.New возвращает объект dsn.DSN или ошибку, если не удалось распарсить строку. После получения объекта доступ к параметрам осуществляется через методы GetString, GetBool, GetInt, GetInt64, GetFloat, которые принимают два параметра (название параметра и значение по умолчанию, которое используется если параметра нет или его значение невалидно).

Более того поддерживается эскепинг спец символов (\s,\t,\r,\n,=,\,",'). Пример ниже:

package main

import (
  "fmt"

  "github.com/wmentor/dsn"
)

func main() {

  str := `message=Hello,\sWorld! calc=1+1\=2`

  ds, err := dsn.New(str)
  if err != nil {
    panic("invalid string")
  }

  // print message=Hello, World!
  fmt.Printf( "message=%s\n", ds.GetString("message","") )

  // print calc=1+2=2
  fmt.Printf( "calc=%s\n", ds.GetString("calc","") )
}

Если у вас есть объект DSN, то вы можете изменить существующий или добавить новый параметр, воспользовавшись одним из следующих методов: SetString, SetBool, SetInt, SetInt64, SetFloat. Каждый из них принимает два параметра (ключ и значение).

ds.SetString("host", "192.168.1.1")

Объет dsn.DSN реализует интерфейс Stringer, поэтому его легко преобразовать обратно в строку:

str := ds.String()
// or
fmt.Println(ds)

источник

 

12.03.2020









 
архив

подписка