How can I print to Stderr in Go without using log - error-handling

How can I write a message to Stderr without using log?
A comment in this SO post shows how to do it with log: log.Println("Message"), but what if I don't want a timestamp?
Is the following good Go?
os.Stderr.WriteString("Message")

If you don't want timestamps, just create a new log.Logger with flag set to 0:
l := log.New(os.Stderr, "", 0)
l.Println("log msg")
EDIT:
Is the following good Go?
os.Stderr.WriteString("Message")
This is acceptable, and you can also use fmt.Fprintf and friends to get formatted output:
fmt.Fprintf(os.Stderr, "number of foo: %d", nFoo)

Using the fmt package, you can choose to write to stderr this way:
import "fmt"
import "os"
func main() {
fmt.Fprintln(os.Stderr, "hello world")
}

The Go builtin functions print and println print to stderr. So if you simply want to output some text to stderr you can do
package main
func main() {
println("Hello stderr!")
}
Documentation: https://golang.org/pkg/builtin/#print

os.Stderr is an io.Writer, so you can use it in any function which accepts an io.Writer. Here are a few examples:
str := "Message"
fmt.Fprintln(os.Stderr, str)
io.WriteString(os.Stderr, str)
io.Copy(os.Stderr, bytes.NewBufferString(str))
os.Stderr.Write([]byte(str))
It all depends on how exactly you have the string you want to print (i.e. if you want to format it first, if you have it as an io.Reader, if you have it as a byte slice...). And there can be a lot more ways.

By default the logger flags are set to Ldate | Ltime. You can change the logger format to any of the following (from the golang log documentation):
Ldate = 1 << iota // the date in the local time zone: 2009/01/23
Ltime // the time in the local time zone: 01:23:23
Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.
Llongfile // full file name and line number: /a/b/c/d.go:23
Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone
LstdFlags = Ldate | Ltime // initial values for the standard logger
For example, flags Ldate | Ltime (or LstdFlags) produce,
2009/01/23 01:23:23 message
While flags Ldate | Ltime | Lmicroseconds | Llongfile produce,
2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
You can also set the default logger to not print anything by setting the flag to 0:
log.SetFlags(0)

use SetOutput function, set output stream to os.Stdout
import (
"log"
"os"
)
func init() {
log.SetOutput(os.Stdout)
}
func main() {
log.Println("Gene Story SNP File Storage Server Started.")
}

Related

Kotlin Comparison between BufferedReader::readText and String always false

I read stdin and stderr from the command-line using:
fun runCommand(vararg commands: String): Pair<String, String> {
val proc = Runtime.getRuntime().exec(commands)
val stdIn = BufferedReader(InputStreamReader(proc.inputStream))
val stdErr = BufferedReader(InputStreamReader(proc.errorStream))
val p = Pair(stdIn.use(BufferedReader::readText).trim(), stdErr.use(BufferedReader::readText).trim())
stdIn.close();
stdErr.close();
return p;
}
This gives me a Pair of <String, String> with the output of stdin and stderr.
However, no matter how I try to compare these Strings to another String, the comparison always returns false.
Things I've tried:
runCommand("nordvpn", "account").first.compareTo("You are not logged in.")
runCommand("nordvpn", "account").first == "You are not logged in."
runCommand("nordvpn", "account").first.equals("You are not logged in.")
Might this have something to do with the encoding?
Or am I just reading the output incorrectly?
Any help would be appreciated!
Thanks to #gidds' comment I was able to find that for some reason the output of the command (stdout) had "-CR SP SP CR" (- CarriageReturn Space Space CarriageReturn" prepended, which I removed with a simple String.drop(5).
Edit: After some more thinking, I assume that the aforementioned charts were responsible for making the output of the command in the terminal colored (yellow)

Write datas from Stripe API in a CSV file in golang

I am trying to retrieve Stripe datas and parse them into a CSV file.
Here is my code:
package main
import (
"github.com/stripe/stripe-go"
"github.com/stripe/stripe-go/invoice"
"fmt"
"os"
"encoding/csv"
)
func main() {
stripe.Key = "" // I can't share the API key
params := &stripe.InvoiceListParams{}
params.Filters.AddFilter("limit", "", "3")
params.Filters.AddFilter("status", "", "paid")
i := invoice.List(params)
// Create a CSV file
csvdatafile, err := os.Create("./mycsvfile.csv")
if err != nil {
fmt.Println(err)
}
defer csvdatafile.Close()
// Write Unmarshaled json data to CSV file
w := csv.NewWriter(csvdatafile)
//Column title
var header []string
header = append(header, "ID")
w.Write(header)
for i.Next() {
in := i.Invoice()
fmt.Printf(in.ID) // It is working
w.Write(in) // It is not working
}
w.Flush()
fmt.Println("Appending succed")
}
When I am running my program with go run *.go I obtain the following error:
./main.go:35:10: cannot use in (type *stripe.Invoice) as type []string in argument to w.Write
I think I am not far from the solution.
I just need to understand how to write correctly in the CSV file thank's to w.Write() command.
According to the doc, the Write function is:
func (w *Writer) Write(record []string) error
That is, it is expecting you to pass a slice of strings representing a line of CSV data with each string being a slice. So, if you have only one field, you have to pass a string slice of 1:
w.Write([]string{in.ID})

How to write a string to clipboard (Windows OS) with a Kotlin/Native application?

I'm very new to Kotlin and making a command line .exe, on Windows using Kotlin/Native. The application should read from a text file and print on screen, line by line. When it reaches the last line of the file, it should put it in the clipboard.
aFile.txt looks something like this:
one
two
three
...
...
the last line
and the code read.kt (Kotlin/Native) I have so far is this:
import kotlinx.cinterop.*
import platform.posix.*
fun main(args: Array<String>) {
if (args.size != 1) {
println("Usage: read.exe <file.txt>")
return
}
val fileName = args[0]
val file = fopen(fileName, "r")
if (file == null) {
perror("cannot open input file $fileName")
return
}
try {
memScoped {
val bufferLength = 64 * 1024
val buffer = allocArray<ByteVar>(bufferLength)
do {
val nextLine = fgets(buffer, bufferLength, file)?.toKString()
if (nextLine == null || nextLine.isEmpty()) break
print("${nextLine}")
} while (true)
}
} finally {
fclose(file)
}
}
The code above prints each line on the screen, but how do I write the string "the last line" in the computer's clipboard? I'm looking for a native (not Java) solution if that's possible.
Thank you very much.
Update:
Obviously, this is not the solution I was looking for, but I don't understand yet what are they talking about here (https://learn.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setclipboarddata).
As a temporary fix, I was able to get what I needed using system(), echo and clip with code like this:
system("echo ${nextLine} | clip")
print("${nextLine}")
Try the following:
import java.awt.Toolkit
import java.awt.datatransfer.Clipboard
import java.awt.datatransfer.StringSelection
fun setClipboard(s: String) {
val selection = StringSelection(s)
val clipboard: Clipboard = Toolkit.getDefaultToolkit().systemClipboard
clipboard.setContents(selection, selection)
}
In Windows, you can work with the Clipboard through WinAPI, as you can see there. The reference says, that you got to use functions from the winuser.h header. This header is included in windows.h, as far as I know, so it is in your platform.windows.* package. You can approve it by checking Kotlin/Native repository files.
To clarify, what I meant, I wrote this small example of platform.windows.* usage. You can add this function to your code, and call it when you got to copy some string.
import platform.windows.*
fun toClipboard(lastLine:String?){
val len = lastLine!!.length + 1
val hMem = GlobalAlloc(GMEM_MOVEABLE, len.toULong())
memcpy(GlobalLock(hMem), lastLine.cstr, len.toULong())
GlobalUnlock(hMem)
val hwnd = HWND_TOP
OpenClipboard(hwnd)
EmptyClipboard()
SetClipboardData(CF_TEXT, hMem)
CloseClipboard()
}

Perl6: check if STDIN has data

In my Perl 6 script, I want to do a (preferably non-blocking) check of standard input to see if data is available. If this is the case, then I want to process it, otherwise I want to do other stuff.
Example (consumer.p6):
#!/usr/bin/perl6
use v6.b;
use fatal;
sub MAIN() returns UInt:D {
while !$*IN.eof {
if some_fancy_check_for_STDIN() { #TODO: this needs to be done.
for $*IN.lines -> $line {
say "Process '$line'";
}
}
say "Do something Else.";
}
say "I'm done.";
return 0;
}
As a STDIN-Generator I wrote another Perl6 script (producer.p6):
#!/usr/bin/perl6
use v6.b;
use fatal;
sub MAIN() returns UInt:D {
$*OUT.say("aaaa aaa");
sleep-until now+2;
$*OUT.say("nbbasdf");
sleep-until now+2;
$*OUT.say("xxxxx");
sleep-until now+2;
return 0;
}
If consumer.p6 works as expected, it should produce the following output, if called via ./producer.p6 | ./consumer.p6:
Process 'aaaa aaa'
Do something Else.
Process 'nbbasdf'
Do something Else.
Process 'xxxxx'
Do something Else.
I'm done.
But actually, it produces the following output (if the if condition is commented out):
Process 'aaaa aaa'
Process 'nbbasdf'
Process 'xxxxx'
Do something Else.
I'm done.
You are using an old version of Perl 6, as v6.b is from before the official release of the language.
So some of what I have below may need a newer version to work.
Also why are you using sleep-until now+2 instead of sleep 2?
One way to do this is to turn the .lines into a Channel, then you can use .poll.
#!/usr/bin/env perl6
use v6.c;
sub MAIN () {
# convert it into a Channel so we can poll it
my $lines = $*IN.Supply.lines.Channel;
my $running = True;
$lines.closed.then: {$running = False}
while $running {
with $lines.poll() -> $line {
say "Process '$line'";
}
say "Do something Else.";
sleep ½;
}
say "I'm done.";
}
Note that the code above blocks at the my $lines = … line currently; so it doesn't start doing something until the first line comes in. To get around that you could do the following
my $lines = supply {
# unblock the $*IN.Supply.lines call
whenever start $*IN.Supply {
whenever .lines { .emit }
}
}.Channel;

How to test the passing of arguments in Golang?

package main
import (
"flag"
"fmt"
)
func main() {
passArguments()
}
func passArguments() string {
username := flag.String("user", "root", "Username for this server")
flag.Parse()
fmt.Printf("Your username is %q.", *username)
usernameToString := *username
return usernameToString
}
Passing an argument to the compiled code:
./args -user=bla
results in:
Your username is "bla"
the username that has been passed is displayed.
Aim: in order to prevent that the code needs to be build and run manually every time to test the code the aim is to write a test that is able to test the passing of arguments.
Attempt
Running the following test:
package main
import (
"os"
"testing"
)
func TestArgs(t *testing.T) {
expected := "bla"
os.Args = []string{"-user=bla"}
actual := passArguments()
if actual != expected {
t.Errorf("Test failed, expected: '%s', got: '%s'", expected, actual)
}
}
results in:
Your username is "root".Your username is "root".--- FAIL: TestArgs (0.00s)
args_test.go:15: Test failed, expected: 'bla', got: 'root'
FAIL
coverage: 87.5% of statements
FAIL tool 0.008s
Problem
It looks like that the os.Args = []string{"-user=bla is not able to pass this argument to the function as the outcome is root instead of bla
Per my comment, the very first value in os.Args is a (path to) executable itself, so os.Args = []string{"cmd", "-user=bla"} should fix your issue. You can take a look at flag test from the standard package where they're doing something similar.
Also, as os.Args is a "global variable", it might be a good idea to keep the state from before the test and restore it after. Similarly to the linked test:
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
This might be useful where other tests are, for example, examining the real arguments passed when evoking go test.
This is old enough but still searched out, while it seems out dated.
Because Go 1.13 changed sth.
I find this change helpful, putting flag.*() in init() and flag.Parse() in Test*()
-args cannot take -<test-args>=<val> after it, but only <test-args>, otherwise the test-args will be taken as go test's command line parameter, instead of your Test*'s