How to interpolate a number inside a string - go

The following code
package main
import (
"fmt"
)
func main() {
fmt.Println(say(9))
}
func say(num int)(total string){
return fmt.Sprintf("There are %s reasons to code!", num)
}
Produces the following output
There are %!s(int=9) reasons to code!
My question
What should I do to interpolate a number inside a string?

If you want to always use the "default" representation of no matter what type, use %v as in
fmt.Sprintf("There are %v reasons to code!", num)

Try %d instead of %s. The d stands for decimal.
The appropriate documentation is here:
http://golang.org/pkg/fmt/

The output is saying exactly what is happening and what you need to know!
As you are trying to use a %s verb which is meant to strings the output says that:
!s(int=0) which means:
The value is not a string, but an integer.
Thus, if you want to know what to use instead take a look at the fmt package page https://golang.org/pkg/fmt/ at the "integers" table:
%b base 2
%c the character represented by the corresponding Unicode code point
%d base 10
%o base 8
%q a single-quoted character literal safely escaped with Go syntax.
%x base 16, with lower-case letters for a-f
%X base 16, with upper-case letters for A-F
%U Unicode format: U+1234; same as "U+%04X"
So you can use any of this verbs to have the output correctly represented.
Or as previous answers says, you can also use the %v verb which means:
"the value in its default format".

Related

Why _(underscore) ignored in output?

I would like to know the reason behind the output of this program.
package main
Program
import (
"fmt"
)
func main() {
a := 1_00_000
fmt.Println(a)
}
Output
100000
How come the underscore is ignored in the output. What is the use of this new feature in Go?
It's not ignored in the output; it's ignored in the source code. The underscores are a convenience to make large number literals in code easier to read; the literal is still an integer, and integers don't contain underscores. You could always use a string of course:
a := "1_00_000"
fmt.Println(a)
Underscores as separators were added as a new feature in Go 1.13: https://golang.org/doc/go1.13#language
Underscores are just digit separators.This new feature is introduced in Go 1.13 to improve readability.It is not printed along with the number.
The digits of any number literal can be separated (grouped) using underscores, such as in 1_000_000, 0b_1010_011 to make it more readable.
d := 9795696874578
d := 9_795_696_874_578 // thousand separators
Here underscored literals are much easier to read.

How do Print and Printf differ from each other in Go?

I am new to Go and understanding simple syntax and functions. Here I am confused between Print and Printf function. The output of those function is similar, so what is the difference between these two functions?
package main
import (
"fmt"
"bufio"
"os"
)
func main(){
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter Text: ")
str, _ := reader.ReadString('\n')
fmt.Printf(str)
fmt.Print(str)
}
I read https://golang.org/pkg/fmt/#Print to understand, but I did not understand it.
From the docs about Printing:
For each Printf-like function, there is also a Print function that takes no format and is equivalent to saying %v for every operand. Another variant Println inserts blanks between operands and appends a newline.
So Printf takes a format string, letting you tell the compiler what format to output your variables with and put them into a string with other information, whereas Print just outputs the variables as they are. Generally you'd prefer to use fmt.Printf, unless you're just debugging and want a quick output of some variables.
In your example you're sending the string you want to print as the format string by mistake, which will work, but is not the intended use. If you just want to print one variable in its default format it's fine to use Print.
Printf method accepts a formatted string for that the codes like "%s" and "%d" in this string to indicate insertion points for values. Those values are then passed as arguments.
Example:
package main
import (
"fmt"
)
var(
a = 654
b = false
c = 2.651
d = 4 + 1i
e = "Australia"
f = 15.2 * 4525.321
)
func main(){
fmt.Printf("d for Integer: %d\n", a)
fmt.Printf("6d for Integer: %6d\n", a)
fmt.Printf("t for Boolean: %t\n", b)
fmt.Printf("g for Float: %g\n", c)
fmt.Printf("e for Scientific Notation: %e\n", d)
fmt.Printf("E for Scientific Notation: %E\n", d)
fmt.Printf("s for String: %s\n", e)
fmt.Printf("G for Complex: %G\n", f)
fmt.Printf("15s String: %15s\n", e)
fmt.Printf("-10s String: %-10s\n",e)
t:= fmt.Sprintf("Print from right: %[3]d %[2]d %[1]d\n", 11, 22, 33)
fmt.Println(t)
}
As per docs
Print: will print number variables, and will not include a line break at the end.
Printf: will not print number variables, and will not include a line break at the end.
Printf is for printing formatted strings. And it can lead to more readable printing.
For more detail visit this tutorial.

String format with errors with %e

I've encountered some go code that appears to use %e for formatting an error for display to the screen. A simplified version would be code like this
err := errors.New("La de da")
fmt.Printf("%e\n", err)
outputs
&{%!e(string=La de da)}
However, if I look at the go manual, it says %e is for formatting floating point numbers in scientific notation. That output doesn't look like scientific notation, so I'm wondering
If this is a specific notation, what is it? (i.e. is there a %. formatting option I could use to get that format)
If it's not a specific notation, what weird thing is going on under the hood that leads to an error being rendered in this way?
What silly, obvious thing am I missing that renders most of what I've said in this post wrong?
Read the Go documentation.
Package fmt
Printing
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.
For your example,
package main
import (
"errors"
"fmt"
)
func main() {
err := errors.New("La de da")
fmt.Printf("%e\n", err)
}
Playground: https://play.golang.org/p/NKC6WWePyxM
Output:
&{%!e(string=La de da)}
Documentation:
All errors begin with the string "%!" followed sometimes by a single
character (the verb) and end with a parenthesized description.
Wrong type or unknown verb: %!verb(type=value)
Printf("%d", hi): %!d(string=hi)
When formatting errors into strings using fmt.Printf()/Println(), you can do the following:
err := fnThatReturnsErr()
if err != nil {
fmt.Println("The error is %v", err)
}
I believe %v is the formatting option you were looking for.

how to dynamically pass values to Sprintf or Printf

If I want to pad a string I could use something like this:
https://play.golang.org/p/ATeUhSP18N
package main
import (
"fmt"
)
func main() {
x := fmt.Sprintf("%+20s", "Hello World!")
fmt.Println(x)
}
From https://golang.org/pkg/fmt/
+ always print a sign for numeric values;
guarantee ASCII-only output for %q (%+q)
- pad with spaces on the right rather than the left (left-justify the field)
But If I would like to dynamically change the pad size how could I pass the value ?
My first guest was:
x := fmt.Sprintf("%+%ds", 20, "Hello World!")
But I get this:
%ds%!(EXTRA int=20, string=Hello World!)
Is there a way of doing this without creating a custom pad function what would add spaces either left or right probably using a for loop:
for i := 0; i < n; i++ {
out += str
}
Use * to tell Sprintf to get a formatting parameter from the argument list:
fmt.Printf("%*s\n", 20, "Hello World!")
Full code on play.golang.org
Go to: https://golang.org/pkg/fmt/
and scroll down until you find this:
fmt.Sprintf("%[3]*.[2]*[1]f", 12.0, 2, 6)
equivalent to
fmt.Sprintf("%6.2f", 12.0)
will yield " 12.00". Because an explicit index affects subsequent verbs,
this notation can be used to print the same values multiple times by
resetting the index for the first argument to be repeated
This sounds like what you want.
The real core of the description of using arguments to set field width and precision occurs further above:
Width and precision are measured in units of Unicode code points, that
is, runes. (This differs from C's printf where the units are always
measured in bytes.) Either or both of the flags may be replaced with
the character '*', causing their values to be obtained from the next
operand, which must be of type int.
The example above is just using explicit indexing into the argument list in addition, which is sometimes nice to have and allows you to reuse the same width and precision values for more conversions.
So you could also write:
fmt.Sprintf("*.*f", 6, 2, 12.0)

Why does fmt.Println in Go print the verb %s literal instead of the value?

Consider,
package main
import "fmt"
func main() {
name := "johnny"
fmt.Println("Hello world %s\n", name)
}
prints out,
Hello world %s
johnny
Why do I get the %s instead of this,
package main
import "fmt"
func main() {
name := "johnny"
fmt.Printf("Hello world %s\n", name)
}
which prints Hello world johnny?
I have tried to figure out the answer from the documentation,
If the format (which is implicitly %v for Println etc.) is valid for a
string (%s %q %v %x %X), the following two rules apply:
If an operand implements the error interface, the Error method will be invoked to convert the object to a string, which will then be
formatted as required by the verb (if any).
If an operand implements method String() string, that method will be invoked to convert the object to a string, which will then be
formatted as required by the verb (if any).
But I'm having trouble understanding if this is affecting my program.
the f in Printf is for "Formatting." That's why the %? verbs do anything at all, because the function is built to parse for them. Println does no such formatting.
Formatting isn't a property of strings like in some languages (maybe you, like myself, came from Python?)
Println just prints the string and appends a newline to it. Printf is short for 'print format' and is based off the C library which is where the conventions for format specifiers ect come from.
Simple answer is it's as designed. If you want to use format specifiers you gotta call the format method.

Resources