Won't print anything on terminal - go

I would like to know why when I execute the command go run example.go the won't print anything on terminal.
The code below works.
package main
import "fmt"
func main() {
fmt.Println("Hello")
}
Will print Hello.
But when I would like to use the function fmt.Printf when I run the command to execute, appear very quickly the response but is deleted on terminal.
package main
import "fmt"
func main() {
var i int = 2
fmt.Printf("%v %T", i, i) // fmt.Print does not work to
}

You use fmt.Printf with a format that does not end with a newline, so your system dutifully prints out the output without a terminating newline.
Presumably your shell then overwrites the output by sending the cursor to the beginning of the line and printing something. To prevent this from happening, either have your program end its output with a newline, or update your shell's prompt to avoid printing over existing output.
(Side note: it's just Go, not Go Lang. This goes give some issues with searching, common among short-named languages like C and C++.)

When Printf is used, you need to put a \n at the end.

Your program will produce undefined: I.
By replacing I with i it should work https://play.golang.org/p/GxFh-SYePR3 and return 2 int.

Related

Checking whether a call to fmt.Errorf() failed [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
In Go, the function fmt.Errorf() returns an error interface.
What's the proper way to check if fmt.Errorf() itself failed?
fmt.Errorf returns basically a string that is wrapped as an error. If you provide wrong arguments like in the following example, you still get an error but with the error message of the format fault inside the string message:
package main
import "fmt"
func main() {
fmt.Println(fmt.Errorf("abc", 5))
}
outputs the error string:
abc%!(EXTRA int=5)
These functions are not expected to be used in a context where you do not know the arguments that you are providing. The typical use case is that you "test" your formatting code when you write it. In your output code you will spot these error messages easily. You should just make sure to test these calls before going into production.
The danger of a panic in these functions is negligible, panics are caught as stated in the documentation:
If an Error or String method triggers a panic when called by a print routine, the fmt
package reformats the error message from the panic, decorating it with an indication
that it came through the fmt package. For example, if a String method calls
panic("bad"), the resulting formatted message will look like
%!s(PANIC=bad)
You should try to catch errors at compile and test time, not run time. For fmt.Errorf, run go vet.
For example,
package main
import "fmt"
func main() {
err := fmt.Errorf("%v")
fmt.Println(err)
}
Output:
$ go vet errorf.go
# command-line-arguments
./errorf.go:6: Errorf format %v reads arg #1, but call has 0 args
$
$ go run errorf.go
%!v(MISSING)
$
Command vet
Vet examines Go source code and reports suspicious constructs, such as
Printf calls whose arguments do not align with the format string. Vet
uses heuristics that do not guarantee all reports are genuine
problems, but it can find errors not caught by the compilers.
Vet is normally invoked using the go command by running "go vet":
go vet
Printf family
Flag: -printf
Suspicious calls to functions in the Printf family, including any
functions with these names, disregarding case:
Print Printf Println
Fprint Fprintf Fprintln
Sprint Sprintf Sprintln
Error Errorf
Fatal Fatalf
Log Logf
Panic Panicf Panicln
The -printfuncs flag can be used to redefine this list. If the
function name ends with an 'f', the function is assumed to take a
format descriptor string in the manner of fmt.Printf. If not, vet
complains about arguments that look like format descriptor strings.
It also checks for errors such as using a Writer as the first argument
of Printf.
Formatted output errors, by design, are a special case. For example, an error when reporting an error can be circular.
Package fmt
Format errors:
If an invalid argument is given for a verb, such as providing a string
to %d, the generated string will contain a description of the problem,
as in these examples:
Wrong type or unknown verb: %!verb(type=value)
Printf("%d", hi): %!d(string=hi)
Too many arguments: %!(EXTRA type=value)
Printf("hi", "guys"): hi%!(EXTRA string=guys)
Too few arguments: %!verb(MISSING)
Printf("hi%d"): hi%!d(MISSING)
Non-int for width or precision: %!(BADWIDTH) or %!(BADPREC)
Printf("%*s", 4.5, "hi"): %!(BADWIDTH)hi
Printf("%.*s", 4.5, "hi"): %!(BADPREC)hi
Invalid or invalid use of argument index: %!(BADINDEX)
Printf("%*[2]d", 7): %!d(BADINDEX)
Printf("%.[2]d", 7): %!d(BADINDEX)
All errors begin with the string "%!" followed sometimes by a single
character (the verb) and end with a parenthesized description.
If an Error or String method triggers a panic when called by a print
routine, the fmt package reformats the error message from the panic,
decorating it with an indication that it came through the fmt package.
For example, if a String method calls panic("bad"), the resulting
formatted message will look like
%!s(PANIC=bad)
The %!s just shows the print verb in use when the failure occurred. If
the panic is caused by a nil receiver to an Error or String method,
however, the output is the undecorated string, "".
Errorf formats according to a format specifier and returns the string
as a value that satisfies error. The fmt package's Errorf function lets us use the package's formatting features to create descriptive error messages.
func Errorf(format string, a ...interface{}) error {
return errors.New(Sprintf(format, a...))
}
And New returns an error that formats as the given text.
func New(text string) error {
return &errorString{text}
}
And errorString is a trivial implementation of error.
type errorString struct {
s string
}
So Basically what it is returning is field of string type.

Pipe string into STDIN of command in Golang

I want to replicate the following subprocess.run function call in Golang. What would be the correct way to do it?
subprocess.run(['kinit', username], input=password.encode())
So far, I've figured out how to use exec.Command to run external commands, but what's confusing me is passing strings as input to STDIN of that command. Python's subprocess.run has a handy input parameter that takes care of this, how can I achieve similar results in Golang?
I figured out how to do it.
package main
import "os/exec"
import "strings"
func main() {
cmd := exec.Command("kinit", username)
cmd.Stdin = strings.NewReader(password)
err := cmd.Run()
}
The Stdin attribute of the Command object is the STDIN pipe, we can set it to a strings.NewReader object containing the input string to achieve the same effect as of the Python snipped mentioned in the question.

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?

Remove n characters from console

I'm writing a program in D that doesn't need a GUI. I remember that in C++, there was a way to remove a number of characters from console/terminal, but I don't know how to do this in D.
How do I remove a number of characters from the console/terminal?
(This didn't fit into a comment and I think it's what you are referring to)
Do you mean getchar? You have direct access to the entire standard C library in D. For example have a look at this simple script:
void main()
{
import core.stdc.stdio : getchar;
foreach(i; 0..3)
getchar();
import std.stdio;
writeln(readln());
}
When you compile & execute this script (e.g. here with rdmd)
echo "Hello world" | rdmd main.d
it would print:
lo world
But I have to agree with Adam that just slicing readln is easier and looks nicer ;-)

cross platform logging in Golang

I am developing a Go program on a Mac which has Parallels installed with Windows so that I can test on both platforms. My program works well. I can compile a Windows ".exe" file on my Mac and run it from Windows and it works well except the log file.
I have set the logger to write its output to a file like so:
log.SetOutput(projectsLog)
Where projectsLog is declare above it as shown below:
projectsLog *os.File
I am using log.Printf statements since I want formatted output. An example is shown below:
log.Printf("Error: wrong Hra Class value %s in row %v for project/path %s", hraClass, (rowNum + 1), testDir)
This is working great on Mac. Each line using log.Printf is logged on a separate line, but on Windows the line breaks do not show and I get one lines without line breaks. I am well aware of "\r" and "\r\n" difference between unix and windows. But I thought that log.Printf will behave appropriately based on the platform it is run on?
If my assumption is wrong then what are some of the options that I have to make sure that the log file is readable on Windows? If I can, I do not want to pass flags, e.g., -platform windows or some such thing. Can this be handled in a transparent manner?
As noted, the fmt package always uses \n as the newline "sequence" regardless of the OS (on Windows too). The log package uses fmt under the hood, so the same applies to log too. When functions that do not end with ...ln() are called (e.g. log.Printf()), a \n will be printed explicitly as documented at Logger.Output() (to which log.Printf() forwards to).
Just deal with \n as the newline. If you do need to print \r\n, you have to handle that manually by appending a \r character at the end of the format string, e.g.:
log.Printf("This will be terminated by CR+LF\r") // \n is appended automatically
You may create a wrapper function for it:
func winprintf(format string, a ...interface{}) {
log.Printf(format+"\r", a...)
}
Note that this however will only print \r\n at the end of the log entry; but if you use \n inside the format string or the arguments are strings (or will result in a string by calling their String() method) containing \n, those will not turn into \r\n automatically. You may use strings.Replace() to handle those too.

Resources