What is "%!s" in the output of a float? - go

I'm getting coordinates (location) as an output of 2 float64 numbers, and it looks like this:
&{%!s(float64=42.539679) %!s(float64=42.601339)}
This is the first time I'm seeing anything like that, so what is "%!s"?
"TypeOf" says "%!s(float64=42.539679)" is float64. So how do I work with this kind of floats? Is there any way to parse it, or somehow to make the %!s(float64=42.539679) look like 42.539679?
UPD: the highlighted line is a *tgbotapi.Location object from Syfaro's telegram bot api.
The api has this structure:
type Location struct {
Longitude float64 `json:"longitude"`
Latitude float64 `json:"latitude"`
}
and the Location.Latitude gives me this: "%!s(float64=42.539679)" (float64)(?)

https://golang.org/pkg/fmt/
%!s is basically used in errors to help you identify a problem.

I think this is a matter of using an incorrect format "verb." You need to use %f instead of %s
package main
import (
"fmt"
)
func main() {
var f float64 = 3.14
fmt.Printf("attempting to print as string: %s \n", f)
fmt.Printf("attempting to print as float: %f", f)
}
Runnable: https://play.golang.org/p/Pec_QrxBIl

Related

html/template is not showing a float value with e+07 notation in exact decimal places

I'm trying an example where I'm passing a value 1.8e+07 to the TestVal field of struct Student. Now I want this 1.8e+07 value to be in exact decimal places but it is not doing so. It is able to show the value in exact decimal places(180000) if the value is 1.8e+05. But if it is greater than e+05 then it is unable to show it.
Example
package main
import (
"fmt"
"os"
"text/template"
)
// declaring a struct
type Student struct {
Name string
TestVal float32
}
// main function
func main() {
std1 := Student{"AJ", 1.8e+07}
// "Parse" parses a string into a template
tmp1 := template.Must(template.New("Template_1").Parse("Hello {{.Name}}, value is {{.TestVal}}"))
// standard output to print merged data
err := tmp1.Execute(os.Stdout, std1)
// if there is no error,
// prints the output
if err != nil {
fmt.Println(err)
}
}
Please help.
That's just the default formatting for floating point numbers. The package doc of fmt explains it: The %v verb is the default format, which for floating numbers means / reverts to %g which is
%e for large exponents, %f otherwise. Precision is discussed below.
If you don't want the default formatting, use the printf template function and specify the format you want, for example:
{{printf "%f" .TestVal}}
This will output (try it on the Go Playground):
Hello AJ, value is 18000000.000000
Or use:
{{printf "%.0f" .TestVal}}
Which will output (try it on the Go Playground):
Hello AJ, value is 18000000
See related:
Format float in golang html/template

How to get the natural log of a big integer

I am trying to convert a string to integer and then to calculate its log.
My first approach was to convert the string using strconv library, but I got an error about the length of the string to be converted.
After that, I used math/big library which worked fine. Now I am not able to apply math.Log()on the resulted big integer.
Code:
package main
import (
"fmt"
"math"
"math/big"
)
func main() {
bb := "11948904162160164791281681976941230184120142151411311314211115130161285142991119211447"
bi := big.NewInt(0)
if _, ok := bi.SetString(bb, 10); ok {
fmt.Println(math.Log(bi))
} else {
fmt.Printf("error parsing line %#v\n", bb)
}
}
Error:
cannot use bi (type *big.Int) as type float64 in argument to math.Log
There are very few situations in which you'd need a precision greater than the one provided by the standard float64 type.
But just to satisfy any "midnight crazy ideas" (or even some very in-depth scientific research!) anyone might run into, Rob Pike's implementations of some operations with big floats are probably the best you can get right now with Go. The log function can be found here.

What is the correct string format specifier for integer in fmt.Printf?

var count int = 5
fmt.Printf("count:%i\n", count)
Its output is
count:%!i(int=5)
What is the correct format specifier so that the output is
count:5
I look up the package fmt's method Printf in Go's package website, but it doesn't say about the syntax for a format specifier. Where can I find the syntax?
Thanks.
%d is the format specifier for base 10 integers (what you typically want) a full listing of fmt's format specifiers can be found here; https://golang.org/pkg/fmt/
var count int = 5
fmt.Printf("count:%d\n", count)
// prints count:5
%d is the format specifier for integer. However, You can use %v to print the value of the variable in default format, no matter what the data type is.
For example:
package main
import (
"fmt"
)
func main() {
//prints Hello 1 0.5 {Hello}
fmt.Printf("%v %v %v %v", "Hello", 1, 0.5, struct{ v string }{"Hello"})
}
You could also simply opt for the Println function:
fmt.Println("count:", count)

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.

Struct field names starting with a string

I have a go struct and I need to work with one of the fields. However I am starting with a string. How do I case it to get the field itself.
package main
import "fmt"
func main() {
type Point struct{
x int
y int
}
pt := Point{x:2, y:3}
a := "x"
fmt.Printf("%s", pt.a)
}
Since a = "x" I am expecting pt.x = 2. Here's the error message it prints out. I am definitely starting with a string so I can't just remove the quotation marks.
$ go run point.go
# command-line-arguments
./point.go:14: pt.a undefined (type Point has no field or method a)
If you need to access a field whose name is given as a string, you have no choice but to use reflection. Go ain't Python. :-)
This blog has a nice explanation.
Here is the reflect package documentation.
But note that reflection should usually be used as a last resort only. It removes the static type safety and is detrimental for performance.
What are you really looking for? There may be a way to address your requirements without using reflection. For example, if you don't need methods attached to your struct, you could use map[string]int.

Resources