%!B(MISSING) different output between fmt.Printf and log.Println - go

I have some bytes returned from json.Marshal. If log them to stdout like this:
log.Println(string(b))
They are output like this:
{"encoded":"%2B"}
If I write them to disk with
fmt.Fprintf(w, string(b))
And then cat the file they have been written like this:
{"encoded":"%!B(MISSING)"}
As far as I can tell the output of string(b) really is the first, and my expected, output. What am I doing wrong?

Fprintf takes a format definition as the first argument. The "%2B" is interpreted as a formatting directive and you are missing the following argument.
Maybe you wanted to use Fprint?

Related

Using cgo, why does C output not 'survive' piping when golang's does?

I'm experimenting with cgo to use C code from golang, but in my little hello-world test, I've ran into something I can't understand or find more information about.
I'm starting with a simple test similar to examples I've found
package main
import (
"fmt"
"unsafe"
)
/*
#import <stdio.h>
#import <stdlib.h>
*/
import "C"
func main() {
go2c := "Printed from C.puts"
var cstr *C.char = C.CString(go2c)
defer C.free(unsafe.Pointer(cstr))
C.puts(cstr)
fmt.Printf("Printed from golang fmt\n")
}
This simple example just echoes strings to stdout from both golang (using fmt.Printf) and raw C (using C.puts) via the basic cgo binding.
When I run this directly in my terminal, I see both lines:
$ ./main
Printed from C.puts
Printed from golang fmt
When I run this but redirect output in any way – pipe to less, shell redirection to a file, etc – I only see golang's output:
./main | cat
Printed from golang fmt
What happens to the C.puts content when piping / redirecting?
Secondary questions: Is this a cgo quirk, or a c standard library quirk I'm not aware of? Is this behaviour documented? How would I go about debugging this on my own (e.g. is there a good/plausible way for me to 'inspect' what FD1 really is in each block?)
Update: If it's relevant, I'm using go version go1.6.2 darwin/amd64.
This is C behavior you're seeing.
Go does not buffer stdout, while in C it is usually buffered. When the C library detects stdout is a tty, it may use line buffering, so the additional \n inserted by puts will cause the output to be displayed.
You need to flush stdout to ensure you get all the output:
go2c := "Printed from C.puts"
var cstr *C.char = C.CString(go2c)
defer C.free(unsafe.Pointer(cstr))
C.puts(cstr)
C.fflush(C.stdout)
fmt.Printf("Printed from golang fmt\n")
See also
Why does printf not flush after the call unless a newline is in the format string?
Is stdout line buffered, unbuffered or indeterminate by default?
The C library buffering is per line, so the first line can be left in the buffer before it is properly flushed (done at exit time in C programs). You can either try to flush stdout, or try adding a trailing \n in the first string. Does it work if you add the \n?

Is it possible to do standard input AND pass a command line argument in the same line?

I have a program stored in programfile in which I want to pass command line arguments (with the contents of the file of varargs). I also want to take input on stdin from the contents of file p. I then want to store the final output into variable output.
This is what I have:
"$programfile" "${varargs}" < "${p}" > "$output"
I'm not sure if this is correct or not as I think my syntax is off somewhere?
Looks fine to me, as long as you meant that you are storing the final output into a file whose name is in the variable output. If you wanted to put the output into a variable you should use backticks or $().
As you have it, your output would go to a file named after the value of $output, not the variable itself. You could do something like:
output=$("$programfile" "${varargs}" < "${p}")
The redirector > is usually used to redirect the output to a file or device. For example,
ls > list.txt
But to store the result as a variable you will need to do:
result=`ls`
The usage of < is correct.

In-place progress output to the console: How to empty the current line

I have a Ruby script that outputs progress messages on the same line, using the carriage return character, like this:
print "\r#{file_name} processed."
As an example, the output changes from 'file001.html' processed. to 'file002.html.' processed and so on until the script completes.
I'd like to replace the last progress message with Done., but I can't just write print "\rDone." because that piece of code outputs something like this:
Done.99.html processed.
I guess I have to empty the line after the last progress message and then print Done.. How do I do that?
You need to send the sequence of bytes that corresponds to the terminfo
variable clr_eol (capability name el) after using \r. There are several
ways that you could get that.
Simplest, assume that there's a constant value. On the terminals I've checked
it is \e[K, but I've only checked a couple. On both of those the following
works:
clear = "\e[K"
print "foo 123"
print "\r#{clear}bar\n"
You could also get the value using:
clear = `tput el`
Or you could use the terminfo gem:
require 'terminfo'
clear = TermInfo.control_string 'el'

Emacs lisp; how to make a string from a variable of any type?

Like error messages for wrongly called functions show, eg.:
(message (file-attributes "."))
Produces the message:
"eval: Wrong type argument: stringp, ("/home14/tjones" 1 0 0 (20415 35598) (20211 19255) (20211 19255) 14 "lrwxrwxrwx" t ...)"
How do you do this type of translation intentionally, eg.:
(message (thing-to-string (file-attributes ".")))
To message something like:
("/home14/tjones" 1 0 0 (20415 35598) (20211 19255) (20211 19255) 14 "lrwxrwxrwx" t ...)
This is for debugging/info only. I'm assuming there's a way as message is doing it, but is this exposed to us users?
Look into prin1-to-string and related functions (prin1, princ, etc). And do try the manual! http://www.gnu.org/software/emacs/manual/html_node/elisp/Output-Functions.html
In your example, message did not do anything (it just refused to run), so the translation to string was done by the read-eval-print loop which caught the error and turned it into a text message.
But yes, message can also do that, and it does that by calling format, which internally uses things like prin1-to-string.
So (format "%S" <foo>) would do your thing-to-string.
The first argument to message is supposed to be a format string (same as the one you pass to the format function. If you give it the format "%s" (or "%S" as in Stefan's answer.) it will stringify anything you give it as the next argument.
The capital S version will escape characters in the string so that it can be read again as an s-expression. In this case, I think that is what you want. So, you don't need to change your code very much to get what you are looking for:
(message "%S" (file-attributes "."))

Ruby Switch Between File and Standard Input

How would you create a variable that could be read. It would read from a certain file if it exists, otherwise it would read from standard input. Something like:
input = File.open("file.txt") || in
This doesn't work, but I think this should be done pretty often, but I can't find a nice way to do it.
This this works for you?
input = File.exist?("file.txt") ? File.open("file.txt") : STDIN
See: ...run against stdin if no arg; otherwise input file =ARGV
I think ruby has the ability to treat arguments that aren't used before STDIN is first used as if it were filenames for files piped into standard input.

Resources