how to load toml settings (GOLANG) - postgresql

I'm trying to use toml to store the connection settings of a database.
I want to load these settings that are in a config.toml file and thus do my operations
I tried the following:
go code:
func Init() *sql.DB {
config, err := toml.LoadFile("config.toml")
if err != nil {
log.Fatal("Erro ao carregar variaveis de ambiente")
}
host := config.Get("postgres.host").(string)
port := config.Get("postgres.port").(string)
user := config.Get("postgres.user").(string)
password := config.Get("postgres.password").(string)
dbname := config.Get("postgres.dbname").(string)
stringConnection := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s", host, port, user, password, dbname)
db, err := sql.Open("postgres", stringConnection)
if err != nil {
panic(err)
}
fmt.Println("Sucesso ao realizar conexão com o banco de dados")
err = db.Ping()
return db
}
config.toml:
[postgres]
host = "localhost"
port = 5432
user = "postgres"
password = "ivaneteJC"
dbname = "webhook"
this attempt is returning an error, which unfortunately I do not know how to proceed
error:
panic: interface conversion: interface {} is int64, not string
Any solution ?

As for your error, like #tkausl said, you define port as integer, and not a string, yet you do type assertion of the value to string in this line
port := config.Get("postgres.port").(string)
Change the string to int64 like the error said and you should be fine.
Are you using the https://github.com/pelletier/go-toml package? If so, this package seems to also support unmarshalling config files into Go struct directly. This is a more convenient approach instead of having to config.Get each config one by one.
type PostgreConfig struct {
Host string
Port int
User string
Password string
Dbname string
}
type MyConfig struct {
Postgres *PostgreConfig
}
// Read the toml file content
doc, err := os.ReadFile("config.toml")
if err != nil {
panic(err)
}
// Parse the content
var cfg MyConfig
err = toml.Unmarshal(doc, &cfg)
if err != nil {
panic(err)
}
fmt.Println(cfg.Postgres.Host)
fmt.Println(cfg.Postgres.Port)

The solution with minimal changes:
// solution 1
port := config.Get("postgres.port")
stringConnection := fmt.Sprintf("host=%s port=%v user=%s password=%s dbname=%s", host, port, user, password, dbname)
// solution 2
port := config.Get("postgres.port").(int64)
stringConnection := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s", host, port, user, password, dbname)
// solution 3
// config.toml
port = "5432"

Related

(GoLang) panic: sql: Register called twice for driver postgres

I have probably spent way to much time on this, so I decided to try here.
I'm having trouble figuring out why my Register is being called twice?
Best I can figure, it seems to be calling once at sql.Register() and again at sqlx.Connect(). But if I remove the sql.Register(), then theres no drivers.
Honestly, I am pretty new to GoLang, I'm hoping for any sort of direction here.
Code - w/o sql.Register
package main
import (
"fmt"
"database/sql"
"github.com/jmoiron/sqlx"
)
const (
host = "localhost"
port = 5432
user = "postgres"
password = "password"
dbname = "sampledb"
)
/*-------------------------------------------*\
|| Functions ||
\*-------------------------------------------*/
// Error Checking Fn
func CheckError(err error, str string) {
if err != nil {
fmt.Printf("Error # : %s\n", str)
panic(err)
}
}
/*-------------------------------------------*\
|| Main() ||
\*-------------------------------------------*/
func main() {
// Open DB Conn
psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
// sql.Register("postgres", &pq.Driver{})
fmt.Printf(":: Drivers ::\n%s\n", sql.Drivers())
db, err := sqlx.Connect("postgres", psqlconn)
CheckError(err, "Main: sqlx.connect")
defer db.Close()
}
Error - w/o sql.Register
$ go run name-generator.go
:: Drivers ::
[]
Error # : Main: sqlx.connect
panic: sql: unknown driver "postgres" (forgotten import?)
goroutine 1 [running]:
main.CheckError({0xc84320, 0xc000056680}, {0xc6073f, 0x5})
C:/path/to/program.go:26 +0xa7 <--- Func CheckError(): panic(err)
main.main()
C:/path/to/program.go:40 +0x125 <--- Func Main(): CheckError()
exit status 2
Code - w/ sql.Register
package main
import (
"fmt"
"database/sql"
"github.com/jmoiron/sqlx"
"github.com/lib/pq"
)
const (
host = "localhost"
port = 5432
user = "postgres"
password = "password"
dbname = "sampledb"
)
/*-------------------------------------------*\
|| Functions ||
\*-------------------------------------------*/
// Error Checking Fn
func CheckError(err error, str string) {
if err != nil {
fmt.Printf("Error # : %s\n", str)
panic(err)
}
}
/*-------------------------------------------*\
|| Main() ||
\*-------------------------------------------*/
func main() {
// Open DB Conn
psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", host, port, user, password, dbname)
sql.Register("postgres", &pq.Driver{})
fmt.Printf(":: Drivers ::\n%s\n", sql.Drivers())
db, err := sqlx.Connect("postgres", psqlconn)
CheckError(err, "Main: sqlx.connect")
defer db.Close()
}
Error - w/ sql.Register
$ go run name-generator.go
panic: sql: Register called twice for driver postgres
goroutine 1 [running]:
database/sql.Register({0xa98bc9, 0x8}, {0xae6680, 0xc8a950})
C:/Program Files/Go/src/database/sql/sql.go:51 +0x13d
main.main()
C:/path/to/program.go:38 +0x11b
exit status 2
Additional Resources
Similar issue, but doesn't solve my problem Link
SQLX Documentation Link
SQL Documentation Link
The package github.com/lib/pq registers it's driver in an init function.
Remove the direct call to register the driver from the application:
sql.Register("postgres", &pq.Driver{}) <-- delete this line
Import github.com/lib/pq for the side effect of executing the init() function:
package main
import (
"fmt"
"database/sql"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq" // <-- add this line
)

ERRO[0003] ERROR: relation "public.databases" does not exist (SQLSTATE 42P01)

I am using gorm (Golang) to connect to my postgres database below the connection code
func NewDatabase(config *config.Config) *gorm.DB {
dsn := fmt.Sprintf(
"host=%s user=%s password=%s dbname=%s port=%s sslmode=disable",
config.DBHost, config.DBUser, config.DBPass, config.DBName, config.DBPort)
db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Info),
NamingStrategy: schema.NamingStrategy{
TablePrefix: "public.",
SingularTable: false,
NameReplacer: CustomReplacer{func(s string) string {
return strings.NewReplacer("\"", "").Replace(s)
}},
},
})
if err != nil {
logrus.Fatal("Error connecting to database ", err)
}
logrus.Info("Database connection successful")
sqlDB, err := db.DB()
if err != nil {
return nil
}
if err != nil {
logrus.Fatal("Error getting sql connection", err)
}
sqlDB.SetMaxIdleConns(config.DBMaxIdlePoolSize)
sqlDB.SetMaxOpenConns(config.DBMaxOpenPoolSize)
return db
}
I am getting unusual error ERRO[0003] ERROR: relation "public.databases" does not exist (SQLSTATE 42P01) because databases table exists in my database in the public schema.
However if I point the database to a remote DB which has same data as local it works perfectly fine.
Add search_path=public parameter to the connection string.

Failed to connect MongoDB by native db driver

I am trying to connect MongoDB by the native MongoDB driver with go language
(ref).
Here is my snapcode.
package main
import (
"context"
"fmt"
"log"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
const (
account = "rootAdmin"
password = "12345678"
iP = "127.0.0.1"
port = 27017
tlsCertificateKeyFile = "D:/cert/wa.pem"
)
type mongoStuff struct {
ctx context.Context
client *mongo.Client
cancel context.CancelFunc
}
func connectToMongoDB() *mongoStuff {
uri := fmt.Sprintf("mongodb://%v:%v#%v:%v/?authSource=admin&tlsCertificateKeyFile=%v&tls=true",
account,
password,
iP,
port,
tlsCertificateKeyFile)
credential := options.Credential{
AuthMechanism: "MONGODB-X509",
Username: account,
Password: password,
}
log.Println(uri)
clientOpts := options.Client().ApplyURI(uri).SetAuth(credential)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
client, err := mongo.Connect(ctx, clientOpts)
if err != nil {
log.Println("Dead connect")
log.Fatal(err)
}
return &mongoStuff{ctx, client, cancel}
}
func disconnectMongoDB(mongodb *mongoStuff) {
cancel := mongodb.cancel
client := mongodb.client
ctx := mongodb.ctx
defer cancel()
defer func() {
if err := client.Disconnect(ctx); err != nil {
log.Println("Dead disconnect")
panic(err)
}
}()
}
func insertExamples(mongodb *mongoStuff) {
ctx := mongodb.ctx
var db *mongo.Database = mongodb.client.Database("documentation_examples")
coll := db.Collection("inventory_insert")
err := coll.Drop(ctx)
if err != nil {
log.Println("Dead drop")
log.Fatal(err)
}
{
result, err := coll.InsertOne(
ctx,
bson.D{
{"item", "canvas"},
{"qty", 100},
{"tags", bson.A{"cotton"}},
{
"size", bson.D{
{"h", 28},
{"w", 35.5},
{"uom", "cm"},
}},
})
if err != nil {
log.Println("Dead insertone")
log.Fatal(err)
}
log.Printf("insertone success. id=%v", result.InsertedID)
}
}
func main() {
mongodb := connectToMongoDB()
defer disconnectMongoDB(mongodb)
insertExamples(mongodb)
}
Whenever I run the code, it just comes up with the below error.
connection() error occured during connection handshake: auth error: round trip error: (AuthenticationFailed) No user name provided
I can't figure out what's going on.
To authenticate with x.509, the username should be either the common name of the certificate or empty. You seem to be attempting some mix of password and x.509 authentication.
All required options can be provided in the URI. See How can I connect with X509 by putting all options in the connection string in node.js driver for mongodb?.
If you insist on specifying credentials not in a URI, reference driver documentation that describes how to do that for x509 credentials.

SSL Socket client in Golang

I'm trying to connect to a server through a socket using an ssl certificate. I have the private key and the certificate needed to connect to the server, i have looked around for something to help me write this code in Go but i have not found anything helpful. Here is the code i write so far, but it does not seem to get me anywhere, it seems to be sending data(tls.dial) before getting to the actual data, which forces the server to reply with some encrypted data which i am unable to check.
func main() {
cert, err := tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil {
log.Fatalf("server: loadkeys: %s", err)
}
config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
conn, err := tls.Dial("tcp", "1.2.3.4:1234", &config)
if err != nil {
log.Fatalf("client: dial: %s", err)
}
defer conn.Close()
log.Println("client: connected to: ", conn.RemoteAddr())
state := conn.ConnectionState()
for _, v := range state.PeerCertificates {
fmt.Println(x509.MarshalPKIXPublicKey(v.PublicKey))
fmt.Println(v.Subject)
}
log.Println("client: handshake: ", state.HandshakeComplete)
log.Println("client: mutual: ", state.NegotiatedProtocolIsMutual)
message := "data"
n, err := io.WriteString(conn, message)
if err != nil {
log.Fatalf("client: write: %s", err)
}
log.Printf("client: wrote %q (%d bytes)", message, n)
reply := make([]byte, 256)
n, err = conn.Read(reply)
log.Printf("client: read %q (%d bytes)", string(reply[:n]), n)
log.Print("client: exiting")
}

socket programming, getting getsockopt: connection refused

I'm having trouble with socket programming.
I have a program that reads from localhost:7777 and writes to localhost:8000.
I use netcat from the command line to write and read to 7777 and 8000 respectively.
This is the reader:
netcat -l -p 8000
And this is the writer:
printf "asti||" | netcat localhost 7777
But my program gets network errors when it tries to write to port 8000 for the second
time. The error is Fatal error: dial tcp 127.0.0.1:8000: getsockopt: connection refused.
What's happening? Why on the second write the error appears?
Furthermore, I noticed that if I kill the netcat reader and restart it then there's no network errors. So to reiterate, the program writes once to 8000 and netcat reads it. Then I kill netcat reader and restart it. At this point the program can write again to 8000. But if the program tries to write two successive times to 8000 without me restarting netcat, then the error appears.
Here is the entire program (it's short). If you like, you experience this mystical behaviour yourself:
package main
import (
"fmt"
"net"
"os"
"strings"
// "io/ioutil"
)
func main() {
end_of_message_terminator := "||"
beginning_of_next_message := ""
request := make([]byte, 512)
service_port := ":7777"
tcpAddr, err := net.ResolveTCPAddr("tcp4", service_port)
checkError(err)
listener, err := net.ListenTCP("tcp", tcpAddr)
checkError(err)
for {
conn, err := listener.Accept()
if err != nil {
continue
}
read_len, err := conn.Read(request)
if read_len == 0 {
continue
}
request_string := string(request[:read_len])
fmt.Printf("Request String %s\\END", request_string)
messages := strings.Split(request_string, end_of_message_terminator)
fmt.Printf("%q\n", messages)
messages[0] = beginning_of_next_message + messages[0]
if messages[len(messages) - 1] != "" {
beginning_of_next_message = messages[len(messages) - 1]
messages[len(messages) - 1] = ""
fmt.Printf("was here 00\n")
}
if len(messages) == 1 {
continue
}
for i := range messages {
go func(){
fmt.Printf("was here 04\n")
respond_to_message(messages[i])
}()
fmt.Printf("was here 01\n")
}
conn.Close()
}
}
func respond_to_message(message string){
message_parameters := strings.Split(message, "|")
response_port := "localhost:8000"
tcpAddr_res, err := net.ResolveTCPAddr("tcp4", response_port)
checkError(err)
response_writer, err := net.DialTCP("tcp", nil, tcpAddr_res)
for i := range message_parameters {
fmt.Printf("was here03\n")
param_parts := strings.Split(message_parameters[i], "=")
fmt.Printf("message: %s\n", message)
fmt.Printf("message_parameters%q\n", message_parameters)
fmt.Printf("params_parts: %q\n", param_parts)
//param_name := param_parts[0]
//param_value := param_parts[1]
checkError(err)
response_writer.Write([]byte("asti de crhis"))
checkError(err)
//result, err := ioutil.ReadAll(response_writer)
//checkError(err)
//fmt.Println(string(result))
}
//response_writer.Close()
}
func checkError(err error) {
if err != nil {
fmt.Fprintf(os.Stderr, "Fatal error: %s", err.Error())
os.Exit(1)
}
}