-2

Writing a CLI application in GoLang and want to use URL across different sessions/commands. Implementing CLI through Cobra where I want to configure URL at the beginning and then keep using it across other commands.

Tried to use below approach -

os.Setenv("URL", URL) os.Getenv("URL")

Above approach works only inside the same process (doesn't work if set and get processes are different).

Any idea how can we do it ?

Update: I wanted to know if it's possible to be done inside Go? I know it can be easily done by storing it in file/db or even setting up in environment variable but exploring ways to do it in Go.

rai.skumar
  • 10,309
  • 6
  • 39
  • 55
  • 1
    There are countless ways to do this. Store a state file. Use a database. Require the user to set up a config file. Store the value in a known remote location (such as S3). Store it to an attached EPROM. Burn it to a CD. Output to a punch card. And literally an infinite number of other possibilities. – Jonathan Hall Aug 08 '17 at 10:20
  • @Flimzy all those approaches are external to go. I want to set and get values through native go code. – rai.skumar Aug 08 '17 at 10:37
  • You can do all of those through native Go code. You just need a Go driver for your punch card reader, and *voala!* – Jonathan Hall Aug 08 '17 at 10:37
  • 2
    If what you're saying is you want to persist a value without using external I/O, then you're asking for the impossible. Processes are ephemeral. That's the opposite of persistent. Even your `os.Setenv` approach uses resources external to Go. – Jonathan Hall Aug 08 '17 at 10:38
  • That's something I am not aware. It will be great if you could provide a link. Thanks. – rai.skumar Aug 08 '17 at 10:38
  • A link for what? – Jonathan Hall Aug 08 '17 at 10:39
  • I will search for the link. It was for getting more details on natively setting and getting values. – rai.skumar Aug 08 '17 at 10:40
  • I don't even know what you mean for "natively setting and getting values." I suspect you don't either. I think you're asking the impossible. – Jonathan Hall Aug 08 '17 at 10:41
  • I got a related link here... https://stackoverflow.com/questions/17368392/environment-variable-is-not-set-on-terminal-session-after-setting-it-with-os-p – rai.skumar Aug 08 '17 at 10:42
  • 3
    Persistent information has to be persisted *somewhere*. Pick a specific somewhere, and then perhaps we can help you to persist it. Persisting data without a somewhere to persist it is not possible. It's a fundamental quality of computing. – Adrian Aug 08 '17 at 13:34

2 Answers2

0

I also faced the similar condition, this is how I solved the issue, in my case I need to persist an endpoint and this endpoint is further used in all other commands,

I stored the value in the sqlite db, and used in all other commands.

db, err := sql.Open("sqlite3", "./value.db")
        if err != nil {
            fmt.Println("Unable to open Sqlite connection:", err)
        }
        defer db.Close()

        sqlStmt := `
    CREATE TABLE IF NOT EXISTS endpoint (name TEXT);
    DELETE FROM endpoint;
    `
        _, err = db.Exec(sqlStmt)
        if err != nil {
            fmt.Println(err)
            return
        }
        tx, err := db.Begin()
        if err != nil {
            fmt.Println(err)
            return
        }
        stmt, err := tx.Prepare("INSERT INTO endpoint(name) VALUES(?)")
        if err != nil {
            fmt.Println(err)
            return
        }
        defer stmt.Close()
        _, err = stmt.Exec(endPoint)
        if err != nil {
            fmt.Println(err)
            return
        }
        err = tx.Commit()
        if err != nil {
            fmt.Println(err)
            return
        }
        rows, err := db.Query("SELECT name FROM endpoint")
        if err != nil {
            fmt.Println(err)
            return
        }
        defer rows.Close()
        for rows.Next() {
            var endpoint string
            err = rows.Scan(&endpoint)
            if err != nil {
                fmt.Println(err)
                return
            }
        }
        err = rows.Err()
        if err != nil {
            fmt.Println(err)
            return
        }
-2

You could establish a simple listener, serving requests to other processes. It could receive and provide any kind of content.

It's quite easy to set up an listening daemon with go, using net.Listen("tcp",":8080"). Perhaps you could take this snippets as boilerplate:

package main

import (
    "fmt"
    "io"
    "log"
    "net"
    "strings"
)

type textProcessor struct {
    input *string
}

func (this textProcessor) Write(b []byte) (int, error) {
    *this.input = string(b)
    return len(strings.TrimSpace(string(b))), nil
}

func main() {
    t := textProcessor{new(string)}

    l, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatal(err)
    }
    defer l.Close()
    for {
        // Wait for connection
        conn, err := l.Accept()
        if err != nil {
            log.Fatal(err)
        }

        io.Copy(t, conn)
        fmt.Print("Echo: ", *t.input)
        conn.Close()
    }
}

Check it out with telnet localhost 8080 and enter some rubbish afterwards.